jdk代理步骤:
1、创建目标类及切面类的有参构造方法;
2、通过反射获取目标类的类加载器、接口,以及重写了invoke方法的代理对象,并返回代理对象;
newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)创建一个代理
cglib代理步骤:
1、创建目标类及切面类的有参构造方法;(不需要目标类实现接口,代理工厂实现MethodInterceptor接口);
2、重写intercept方法
3、创建代理对象
public Object getProxyObject() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this.target);
return enhancer.create();
}
jdk 代理和 cglib 代理的区别:
- JDK 代理只能对实现了接口的类生成代理,而不能针对类 ,使用的是 Java反射技术实现,生成类的过程比较高效。
- CGLIB 是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 ,使用 ASM 字节码框架实现,相关执行的过程比较高效,生成类的过程可以利用缓存弥补,因为是继承,所以该类或方法最好不要声明成final
- 1. 代理对象类型:
- JDK代理: 只能代理实现了接口的类,而不能针对类 。
- CGLIB代理: 可以代理任何类,包括没有实现接口的类。CGLIB代理生成的代理对象是目标对象的子类。
- 2. 继承关系:
- JDK代理: 生成的代理对象实现了与原始对象相同的接口。因此它们与原始对象之间没有继承关系。
- CGLIB代理:生成的代理对象是目标对象的子类。
- 3. 性能:
- JDK代理: 通常比CGLIB代理略快,但性能差异可能不太明显。JDK代理的性能受到接口方法调用的限制,对于接口代理来说性能较好。
- CGLIB代理: 生成的代理对象直接调用目标对象的方法,没有接口方法调用的限制。对于非接口代理,CGLIB通常更灵活,但在某些情况下可能稍慢。
- CGLib实现动态代理,使用字节码技术生成代理类,在jdk6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。
- 在jdk6、jdk7、jdk8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLIB代理效率,只有当进行大量调用的时候,jdk6和jdk7比CGLIB代理效率低一点,但是到jdk8的时候,jdk代理效率高于CGLIB代理。总之,每一次jdk版本升级,jdk代理效率都得到提升,而CGLIB代理消息确有点跟不上步伐。
- 4. 对象构建:
- JDK代理: 不需要第三方库支持,只需要JDK环境就可以进行代理,使用条件:使用Proxy.newProxyInstance产生代理对象 + 实现InvocationHandler(重写invoke) + 被代理的对象必须要实现接口
- CGLIB代理: 必须依赖于CGLib的类库。CGLIB代理使用一个MethodInterceptor来处理方法调用。
- 5. 可见性:
- JDK代理: 只能代理接口中声明的方法,对于未在接口中声明的方法无法代理。
- CGLIB代理: 可以代理目标对象的所有非final方法,包括未在接口中声明的方法。
参考:https://blog.csdn.net/xiaofeng10330111/article/details/105361028