1、静态代理和动态代理的概念:
在我的另一篇博文:Java 静态代理和动态代理 中有讲到,这里就不做赘述了。
JDK动态代理它的好处理是可以为我们生成任何一个接口的代理类,并将需要增强的方法织入到任意目标函数。
但它仍然具有一个局限性,就是只有实现了接口的类,才能为其实现代理。
2、CGLIB
CGLIB解决了动态代理的难题,它通过生成目标类子类的方式来实现来实现代理,而不是接口,规避了接口的局限性。
CGLIB是一个强大的高性能代码生成包,其在运行时期(非编译时期)生成被 代理对象的子类,并重写了被代理对象的所有方法,从而作为代理对象。
要使用CGLIB先要在POM文件中引入
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency>
1、业务类
public class UserServiceImpl { public void addUser() { System.out.println("=========增加用户=========="); } }
2、代理类
import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class UserCglib implements MethodInterceptor { private Object _obj; public Object getInstance(Object obj) { this._obj = obj; Enhancer enhancer = new Enhancer();
// 设置代理目标 enhancer.setSuperclass(this._obj.getClass()); // 设置回调 enhancer.setCallback(this); //创建代理对象 return enhancer.create(); }
//回调方法 @Override public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("=========执行前=========="); Object result = proxy.invokeSuper(object, args); System.out.println("=========执行后=========="); return result; } }
3、测试类
public class TestCglib { public static void main(String[] args) { UserCglib cglib = new UserCglib(); UserServiceImpl userServiceImpl = (UserServiceImpl) cglib.getInstance(new UserServiceImpl()); userServiceImpl.addUser(); } }
4、测试结果
=========执行前==========
=========增加用户==========
=========执行后==========
JDK动态代理和CGLIB库优点和局限:
- JDK动态代理只能对实现了接口的类生成代理,而不能针对类。
- CGLIB是针对类实现代理,对指定的类生成一个子类,覆盖其中的方法(继承),对于无法生成子类的类(final类),肯定是没有办法生成代理子类的。
注:静态代理、动态代理、CGlib看上去实现起来复杂,其实Spring AOP已经帮我们封装好了,我们直接拿来用就可以了。
本文主要是为了了解 AOP 的实现原理(即基于代理)。
注2:CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。
参考:https://juejin.im/post/591d8c8ba22b9d00585007dd