java代理

Java 代理模式实现方式,主要有如下五种方法

静态代理,工程师编辑代理类代码,实现代理模式;在编译期就生成了代理类。

基于 JDK 实现动态代理,通过jdk提供的工具方法Proxy.newProxyInstance动态构建全新的代理类(继承Proxy类,并持有InvocationHandler接口引用 )字节码文件并实例化对象返回。(jdk动态代理是由java内部的反射机制来实例化代理对象,并代理的调用委托类方法)

基于CGlib 动态代理模式 基于继承被代理类生成代理子类,不用实现接口。只需要被代理类是非final 类即可。(cglib动态代理底层是借助asm字节码技术

基于 Aspectj 实现动态代理(修改目标类的字节,织入代理的字节,在程序编译的时候 插入动态代理的字节码,不会生成全新的Class )

基于 instrumentation 实现动态代理(修改目标类的字节码、类装载的时候动态拦截去修改,基于javaagent)-javaagent:spring-instrument-4.3.8.RELEASE.jar(类装载的时候 插入动态代理的字节码,不会生成全新的Class )

静态代理实现步骤:

委托类和代理类之间的约束接口Cat

约束接口实现类 Lion,实现 Cat 接口,委托角色

代理类实现 FeederProxy,实现Cat 接口并含有一个 Cat接口引用属性。 代理角色,代理 cat接口属性引用实例的行为并可以新增公共逻辑。

基于 JDK 实现动态代理:java的java.lang.reflect包下提供了Proxy类和一个 InvocationHandler 接口这个类Proxy定义了生成JDK动态代理类的方法getProxyClass(ClassLoader loader,Class<?>... interfaces)生成动态代理类,返回class实例代表一个class文件。可以保存该 class 文件查看jdk生成的代理类文件长什么样。该生成的动态代理类继承Proxy类,(重要特性) ,并实现公共接口。InvocationHandler这个接口 是被动态代理类回调的接口,我们所有需要增加的针对委托类的统一处理逻辑都增加到invoke 方法里面在调用委托类接口方法之前或之后 结束战斗。

①创建一个与代理类相关联的InvocationHandler,并将代理类引用传递进去,Proxy.newProxyInstance的方式创建代理类。

②创建 InvocationHandler 实例并设置代理的目标类对象,通过 proxyClass 获得 一个带有InvocationHandler参数的构造器constructor,通过构造器创建一个 动态代理类实例。ProxyConstructor.newInstance

一个典型的基于JDK动态代理创建对象过程可分为以下四个步骤:

1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(...);

2、通过为Proxy类指定ClassLoader对象和一组interface代理类需要实现的接口,创建动态代理类类文件,默认JDK并不会保存这个文件到文件中;可以保存起来观察生成的代理类结构Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...});

3、通过上面新建的代理clazz的反射机制获取动态代理类的一个构造函数,其构造函数入参类型是调用处理器接口(IvocationHandler)类型Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});

4、通过构造函数实例创建代理类实例,此时需将调用处理器对象作为参数被传入 Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler)); 为了简化对象创建过程,Proxy类中的newInstance工具方法封装了2~4,只需两步即可完成代理对象的创建。

基于CGlib 技术动态代理代理类实现 (基于继承)

Cglib是针对类来实现代理的,他的原理是对代理的目标类生成一个子类,并覆盖其中方法实现增强,因为底层是基于创建被代理类的一个子类,所以它避免了JDK动态代理类的缺陷。

但因为采用的是继承,所以不能对final修饰的类进行代理。final修饰的类不可继承。

创建Enhancer加强器,用来创建动态代理类,同时需要设置方法拦截器回调引用,对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept() 方法进行拦截,enhancer.create()创建实例。

Cglib 总结

CGlib可以传入接口也可以传入普通的类,接口使用实现的方式,普通类使用会使用继承的方式生成代理类.

由于是继承方式,如果是 static方法,private方法,final方法等描述的方法是不能被代理的

做了方法访问优化,使用建立方法索引的方式避免了传统JDK动态代理需要通过Method方法反射调用.

提供callback 和filter设计,可以灵活地给不同的方法绑定不同的callback。编码更方便灵活。

CGLIB会默认代理Object中equals,toString,hashCode,clone等方法。比JDK代理多了clone。


太好了!总算有人把动态代理、CGlib、AOP都说清楚了! - 云+社区 - 腾讯云 (tencent.com)

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容