Java设计模式--代理模式+动态代理+CGLib代理
静态代理
抽象主题角色:声明真实主题和代理主题的共同接口。
代理主题角色:代理主题内部含有对真实主题的引用,从而在任何时候操作真实主题对象;代理主题提供一个与真实主题相同的接口,以便在任何时候都可以代替真实主题。代理角色通常在将客户端调用传递给真实的主题之前或之后,都要执行某个操作,而不是单纯的传递调用。
真实主题角色:定义代理角色所代表的的真实对象。
UML图:

抽象主题
public interface Subject {
void request();
}
真实主题
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("真实对象的方法");
}
}
代理主题
public class ProxySubject implements Subject {
private RealSubject subject;
public ProxySubject() {
}
@Override
public void request() {
pre();
if (subject == null){
subject = new RealSubject();
}
subject.request();
post();
}
private void pre(){
System.out.println("方法执行之前");
}
private void post(){
System.out.println("方法执行之后");
}
}
执行:
public static void main(String[] args) throws Exception {
ProxySubject subject = new ProxySubject();
subject.request();
}
输出:
方法执行之前
真实对象的方法
方法执行之后
动态代理
JDK自带的动态代理,实现InvocationHandler接口。
声明接口
public interface MyConnection extends AutoCloseable {
void createStatement() throws Exception;
@Override
void close() throws Exception;
}
真实主题
public class MyDefaultConnection implements MyConnection {
@Override
public void createStatement() throws Exception {
System.out.println("Create Statement ...");
}
@Override
public void close() throws Exception {
System.out.println("Close Connection ...");
}
}
代理主题
public class MyConnectionProxy implements InvocationHandler {
private MyConnection conn;
private MyConnection proxyConn;
public MyConnectionProxy(MyConnection conn) {
this.conn = conn;
this.proxyConn = (MyConnection) Proxy.newProxyInstance(MyConnection.class.getClassLoader(), new Class<?>[] {MyConnection.class}, this);
}
public MyConnection getConn() {
return conn;
}
public MyConnection getProxyConn() {
return proxyConn;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
System.out.println("==代理方法:" + methodName);
if("close".equals(methodName)){
System.out.println("**不执行close方法");
}else{
return method.invoke(conn, args);
}
return null;
}
}
执行:
public static void main(String[] args) throws Exception {
MyConnection connection = new MyDefaultConnection();
MyConnectionProxy proxy = new MyConnectionProxy(connection);
proxy.getProxyConn().createStatement();
proxy.getProxyConn().close();
}
你会发现我的代理对象去哪里了?实际上我放在InvocationHandler的实现类里面了,这里参考的是mybatis源码的设计。
输出:
==代理方法:createStatement
Create Statement ...
==代理方法:close
**不执行close方法
CGLib
CGLib不需要接口就能实现动态代理。
CGLIB 原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。它比使用java反射的JDK动态代理要快。
CGLIB 底层:使用字节码处理框架ASM,来转换字节码并生成新的类。
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.12</version>
</dependency>
需要代理的对象
public class Programmer {
public void work(){
System.out.println("程序员正在敲代码...");
}
public final void finalCannotOverride(){
System.out.println("final方法不能被生成的子类覆盖");
}
private void privateCannotOverride(){
System.out.println("private方法不能被生成的子类覆盖");
}
}
代理类
public class ProgrammerProxy implements MethodInterceptor {
// 真实对象
private Object realObject;
// 代理对象
private Object proxyObject;
public ProgrammerProxy(Object realObject) {
this.realObject = realObject;
Enhancer enhancer = new Enhancer();
// 设置需要代理的对象
enhancer.setSuperclass(realObject.getClass());
// 设置代理人
enhancer.setCallback(this);
this.proxyObject = enhancer.create();
}
public Programmer getProxyObject() {
return (Programmer) proxyObject;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
pre();
Object result = method.invoke(realObject, objects);
post();
return result;
}
private void pre(){
System.out.println("==先吃早餐");
}
private void post(){
System.out.println("==下班打卡");
}
}
执行:
public static void main(String[] args) throws Exception {
Programmer programmer = new Programmer();
ProgrammerProxy proxy = new ProgrammerProxy(programmer);
proxy.getProxyObject().finalCannotOverride();
proxy.getProxyObject().work();
}
输出:
final方法不能被生成的子类覆盖
==先吃早餐
程序员正在敲代码...
==下班打卡
Java设计模式--代理模式+动态代理+CGLib代理的更多相关文章
- Java设计模式系列之动态代理模式(转载)
代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public interface Sub ...
- java设计模式中的动态代理
Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩 ...
- 代理模式详解:静态代理、JDK动态代理与Cglib动态代理
代理模式简介分类 概念 代理,是为了在不修改目标对象的基础上,增强目标方法的业务逻辑. 客户类需要执行的是目标对象的目标方法,但是真正执行的是代理对象的代理方法,客户类对目标对象的访问是通过代 ...
- 黑马程序员:Java基础总结----静态代理模式&动态代理
黑马程序员:Java基础总结 静态代理模式&动态代理 ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public class Ts { ...
- java 代理模式一: 静态代理
代理模式: 代理模式的作用:为其他对象提供一种代理以控制对 特定对象 的访问. 某种情况下,一个客户不想或者直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用:通过代理对象引用. ...
- 总结两种动态代理jdk代理和cglib代理
动态代理 上篇文章讲了什么是代理模式,为什么用代理模式,从静态代理过渡到动态代理. 这里再简单总结一下 什么是代理模式,给某个对象提供一个代理对象,并由代理对象控制对于原对象的访问,即客户不直接操控原 ...
- java 设计模式 --委派模式
委派模式(Delegate)原理: 类B和类A是两个互相没有任何关系的类,但是B具有和A一模一样的方法和属性:并且调用B中的方法/属性就是调用A中同名的方法和属性. B好像就是一个受A授权委托的中介, ...
- 3.java设计模式-建造者模式
Java设计模式-建造者模式 在<JAVA与模式>一书中开头是这样描述建造(Builder)模式的: 建造模式是对象的创建模式.建造模式可以将一个产品的内部表象(internal repr ...
- Java设计模式——组合模式
JAVA 设计模式 组合模式 用途 组合模式 (Component) 将对象组合成树形结构以表示“部分-整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有唯一性. 组合模式是一种结构型模 ...
- java设计模式--单列模式
java设计模式--单列模式 单列模式定义:确保一个类只有一个实例,并提供一个全局访问点. 下面是几种实现单列模式的Demo,每个Demo都有自己的优缺点: Demo1: /** * 单列模式需要满足 ...
随机推荐
- cors劫持用户凭证任意登陆
漏洞作者:rcoil 挖洞过程无意中看到一个数据包,响应包中包含有Access-Control-Allow-Origin这个字段,然后就随手尝试看看有没有CORS漏洞!结果如图 再尝试 发现如下图! ...
- if语句的嵌套:从键盘输入3个实数,利用条件表达式求其最大者。
#include<stdio.h>void main(){ float a,b,c,max; scanf("%f%f%f",&a,&b,&c); ...
- learning java Paths Path
import java.nio.file.Path; import java.nio.file.Paths; public class PathTest { public static void ma ...
- 2019.11.30 Mysql查询知识
不等于:<> 判断为空的条件:null和空格(空字符串) 判断是否为null:xxxx is not null / xxxx is null 判断null: SE ...
- a list of frequently asked questions about Circus
转自:https://circus.readthedocs.io/en/latest/faq/,可以帮助我们了解circus 的使用,以及问题解决 How does Circus stack comp ...
- 产品生命周期(Product Life Circle,PLC)
什么是产品生命周期? 产品生命周期是新产品从开发进入市场到被市场淘汰的整个过程.产品生命周期可分为初创期.成长期.成熟期.衰退期. 产品生命周期有什么用? 在产品不同的生命阶段,公司的业务目的都不同. ...
- 【loj3120】【CTS2019】珍珠
题目 $laofu $出的题 \(n\)个离散型随机变量\(X_i\)可能的值为\([1,D]\) ,求有至少\(m\)对的概率 $0 \le m \le 10^9 , 1 \le n ...
- qtcreator 添加 cppreference 离线文档
https://en.cppreference.com/w/File:qch_book_20190607.zip 下载后放到 D:\Qt\Qt5.10.0\Docs\Qt-5.10.0目录下, 并在q ...
- jmeter测试 flask 接口请求
jmeter测试 flask 接口请求 flask的代码如下: #!/usr/bin/env python # -*- coding: utf-8 -*- from flask import Flas ...
- PostgreSQL递归查询示例
PostgreSQL提供了WITH语句,允许你构造用于查询的辅助语句.这些语句通常称为公共表表达式或cte.cte类似于只在查询执行期间存在的临时表. 递归查询是指递归CTE的查询.递归查询在很多情况 ...