- JDK的动态代理:只能用于实现了接口的类产生代理。
- Cglib代理:针对没有实现接口的类产生代理,应用的是底层的字节码增强技术,生成当前类的子类对象。
JDK动态代理:
JDK的动态代理主要涉及到java.lang. reflect
包中的两个类:Proxy和InvocationHandler
。
其中 InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,在并通过反射机制
调用目标类的代码,动态将横切逻辑和业务逻辑编织在一起。
newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
JDK的动态代理必须具备四个条件: 目标接口,目标类,拦截器(处理器),代理类
1、因为利用JDKProxy生成的代理类实现了接口,所以目标类中所有的方法在代理类中都有。
2、生成的代理类的所有的方法都拦截了目标类的所有的方法。而拦截器(处理器)中invoke方法的内容正好就是代理类的各个方法的组成体。
3、利用JDKProxy方式必须有接口的存在。
4、invoke方法中的三个参数可以访问目标类的被调用方法的API、被调用方法的参数、被调用方法的返回类型。
CGLib
CGLib采用非常底层的字节码技术
,可以为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,并在拦截方法相应地方织入横切逻辑。
1、 CGlib是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。
2、 用CGlib生成代理类是目标类的子类
。
3、 用CGlib生成代理类不需要接口。
4、 用CGLib生成的代理类重写了父类的各个方法。
5、 拦截器中的intercept方法内容正好就是代理类中的方法体。
CGLib所创建的动态代理对象的性能依旧比JDK的所创建的代理对象的性能高不少(大概10倍)。
而CGLib在创建代理对象时性能却比JDK动态代理慢很多(大概8倍),
所以对于singleton的代理对象或者具有实例池的代理,因为不需要频繁创建代理对象,所以比较适合用CGLib动态代理技术,反之适合用JDK动态代理技术。此外,由于CGLib采用生成子类的技术创建代理对象,所以不能对目标类中的final方法进行代理。