代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。
1.静态代理: 在编译时就已经实现,编译完成后代理类是一个实际的class文件
静态代理的方式:创建一个接口,然后创建被代理的类实现该接口并且实现该接口中的抽象方法。之后再创建一个代理类,同时使其也实现这个接口。在代理类中持有一个被代理对象的引用,而后在代理类方法中调用该对象的方法。
参考:什么是动态代理?
2.动态代理: 在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中
动态代理的方式:JDK动态代理 和 CGLIB动态代理
在springboot 2.x中默认使用的CGLIB动态代理,如果要强制使用JDK代理的话,需要添加配置
1 | spring.aop.proxy-target-class=false |
参考:springboot2.x默认使用的代理是cglib代理
JDK动态代理 和 CGLIB动态代理的区别:
1.JDK动态代理只能对实现了接口的类生成代理,而不能针对类
JDK动态代理使用 java.lang.reflect.InvocationHandler,参考:Java动态代理之InvocationHandler最简单的入门教程
使用JDK动态代理的五大步骤:
- 通过实现InvocationHandler接口来自定义自己的InvocationHandler;
- 通过
Proxy.getProxyClass
获得动态代理类; - 通过反射机制获得代理类的构造方法,方法签名为
getConstructor(InvocationHandler.class)
; - 通过构造函数获得代理对象并将自定义的
InvocationHandler
实例对象传为参数传入; - 通过代理对象调用目标方法;
2.Cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成final
Cglib动态代理使用 org.springframework.cglib.proxy.*,
CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM
,来转换字节码并生成新的类
CGLIB代理实现如下:
- 首先实现一个MethodInterceptor,方法调用会被转发到该类的intercept()方法。
- 然后在需要使用的时候,通过CGLIB动态代理获取代理对象。
和 什么是动态代理?
在SpringBoot中如何使用动态代理,参考:【Spring Boot实战与进阶】AOP的两种动态代理(JDK和Cglib)