SpringAOP-说说 JDK动态代理和 CGLIB 代理

发布时间:2024年01月16日

Spring 的 AOP 是通过动态代理来实现的,动态代理主要有两种方式 JDK 动态代理和 Cglib 动态代理,这两种动态代理的使用和原理有些不同。

JDK 动态代理

  1. Interface:JDK动态代理是基于接口的代理,它要求目标类实现一个接口。
  2. InvocationHandler:InvocationHandler 是一个接口,可以通过实现这个接口,定义横切逻辑,再通过反射机制(invoke)调用目标类的代码,在次过程,可能包装逻辑,对目标方法进行前置后置处理。
  3. Proxy:Proxy 利用 InvocationHandler 动态创建一个符合目标类实现的接口的实例,生成目标类的代理对象。

CgLib 动态代理

  1. 使用 JDK 创建代理有一大限制,它只能为接口创建代理实例,而 CgLib 动态代理就没有这个限制。
  2. CgLib 动态代理是使用字节码处理框架 ASM,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
  3. CgLib 创建的动态代理对象性能比 JDK 创建的动态代理对象的性能高不少,但是 CGLib 在创建代理对象时所花费的时间却比 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();
    }
}
文章来源:https://blog.csdn.net/weixin_62079735/article/details/135634058
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。