本文主要是介绍代理模式———静态代理、动态代理(JDK代理)、CGLIB代理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、代理模式
代理模式就是为某个对象Q,提供一个代理对象,通过代理对象,完成对对象Q的引用。
通过代理对象的增强可以无侵入的扩展委托类。真正的业务实现还是交与委托类,代理类相当于包装了一层委托类,可以在委托类执行的前后加入扩展,比如缓存,切面,消息等。
在SpringAOP的实现中,使用的核心技术就是动态代理,使用了JDK代理(对象实现了接口使用)与CGLIB(对象没实现接口使用)代理的结合。
二、静态代理
如上图所示,代理类和目标对象分别实现相同的接口。代理对象调用实现类,完成方法的调用和封装。
优点:
- 可以做到不修改目标对象的情况下,对目标功能扩展
缺点:
- 每个目标对象都需要一个代理类。
- 接口每增加一个方法,都需要同时改动,代理类与目标对象。
- (不用接口实现代理的是委托模式,直接用另一个对象包装,目标对象)
三、动态代理
动态代理也叫jdk代理,接口代理。
特点:
- jdk 调用jdk,API接口,动态生成代理对象
- 代理对象不需要实现接口
上代码
代理对象: 调用:
JDK实现代理只需要使用newProxyInstance方法
这个方法需要三个参数:
ClassLoader loader,
:定义代理类的类加载器Class<?>[] interfaces,
:代理类的实现接口集合InvocationHandler h
:调用方法时的调用处理器
根据这个newProxyInstance()方法会动态的创建出,代理对象
优点:
- 代理类不需要实现接口
- 相比静态代理,运行时生成代理对象,可在运行时指定代理的目标对象,和代理的逻辑。相比静态代理更加灵活,静态代理在编译期以及指定了,代理的目标对象和代理逻辑。
- 可以任意指定目标对象,和代理逻辑。
缺点:
- 目标对象需要实现对应的接口,没有接口的类,无法实现jdk动态代理。
四、CGLib代理
CGLib代理也叫做子类代理类。
CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。但因为采用的是继承,所以不能对final修饰的类进行代理。
特点:
- 可以对无接口的类实现代理
- 代理的类不能为final,否则报错
- 目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
public class CglibProxy implements MethodInterceptor {private Object target;//业务类对象,供代理方法中进行真正的业务方法调用// //获得一个代理对象public Object getProxyInstance(Object target){this.target =target;//给业务对象赋值//1.工具类Enhancer en = new Enhancer();//创建加强器,用来创建动态代理类//2.设置父类en.setSuperclass(this.target.getClass());//为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)//设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦//3.设置回调函数en.setCallback(this);//4.创建子类(代理对象)return en.create();}@Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("代理对象调用前处理");Object result = methodProxy.invoke(o,args);//调用业务类(父类中)的方法System.out.println("代理对象调用后处理");return result;}
}
调用
//3.cglib代理SubjectCGImpl target = new SubjectCGImpl();CglibProxy cglibProxy = new CglibProxy();SubjectCGImpl proxyInstance = (SubjectCGImpl)cglibProxy.getProxyInstance(target);proxyInstance.requ11est();
这里调用的时候还会出现堆栈溢出的问题,目前还没找到原因。
CGLIB动态代理的性能比JDK动态代理的性能高10倍左右,但创建代理对象的速度却比JDK创建代理对象的速度慢15倍左右。对单利的代理对象创建使用CGLIB更合适。
这篇关于代理模式———静态代理、动态代理(JDK代理)、CGLIB代理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!