说说 JDK 动态代理和 CGLIB 代理 ?

说说 JDK 动态代理和 CGLIB 代理 ?
Spring的AOP实现了动态代理,主要有两种方式:JDK动态代理和Cglib动态代理,它们在使用和原理上有一些区别。
JDK动态代理
- 接口:对于JDK动态代理,目标类需要实现一个接口。
- InvocationHandler:InvocationHandler是一个接口,通过实现该接口来定义横切逻辑。在调用目标类的方法时,可以通过反射机制(invoke)执行目标方法,并在此过程中进行前置和后置处理等包装逻辑。
- Proxy:Proxy利用InvocationHandler动态创建一个实现目标类接口的代理对象。
Cglib动态代理
- 使用JDK创建代理的限制是只能为接口创建代理实例,而Cglib动态代理没有这个限制。
- Cglib动态代理使用字节码处理框架ASM。它的原理是通过字节码技术为目标类创建一个子类,并使用方法拦截技术拦截父类所有方法的调用,从而将横切逻辑织入其中。
- Cglib创建的动态代理对象性能比JDK创建的动态代理对象性能更高,但是创建代理对象的时间比JDK更长。因此,对于单例对象而言,由于无需频繁创建对象,使用Cglib更合适;而对于非单例对象,使用JDK方式更适合。此外,由于Cglib是通过动态创建子类的方式实现代理,所以对于final方法无法进行代理。
让我们看一个常见的场景:客户服务中转,用于解决用户问题的例子:
用户向客服提问题
JDK 动态代理实现:
接口
public interface ISolver { void solve(); }
目标类:需要实现对应接口
public class Solver implements ISolver { @Override public void solve() { System.out.println("疯狂掉头发解决问题……"); } }
态代理工厂:ProxyFactory,直接用反射方式生成一个目标对象的代理对象,这里用了一个匿名内部类方式重写 InvocationHandler 方法,实现接口重写也差不多
public class ProxyFactory { // 维护一个目标对象 private Object target; public ProxyFactory(Object target) { this.target = target; } // 为目标对象生成代理对象 public Object getProxyInstance() { return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("请问有什么可以帮到您?"); // 调用目标对象方法 Object returnValue = method.invoke(target, args); System.out.println("问题已经解决啦!"); return null; } }); } }
客户端:Client,生成一个代理对象实例,通过代理对象调用目标对象方法
public class Client { public static void main(String[] args) { //目标对象:程序员 ISolver developer = new Solver(); //代理:客服小姐姐 ISolver csProxy = (ISolver) new ProxyFactory(developer).getProxyInstance(); //目标方法:解决问题 csProxy.solve(); } }
Cglib 动态代理实现:
目标类:Solver,这里目标类不用再实现接口。
public class Solver { public void solve() { System.out.println("疯狂掉头发解决问题……"); } }
动态代理工厂:
public class ProxyFactory implements MethodInterceptor { //维护一个目标对象 private Object target; public ProxyFactory(Object target) { this.target = target; } //为目标对象生成代理对象 public Object getProxyInstance() { //工具类 Enhancer en = new Enhancer(); //设置父类 en.setSuperclass(target.getClass()); //设置回调函数 en.setCallback(this); //创建子类对象代理 return en.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("请问有什么可以帮到您?"); // 执行目标对象的方法 Object returnValue = method.invoke(target, args); System.out.println("问题已经解决啦!"); return null; } }
客户端:Client
public class Client { public static void main(String[] args) { //目标对象:程序员 Solver developer = new Solver(); //代理:客服小姐姐 Solver csProxy = (Solver) new ProxyFactory(developer).getProxyInstance(); //目标方法:解决问题 csProxy.solve(); } }