spring 12 cglib 代理进阶

cglib 代理进阶

模拟 cglib 代理

示例
    public static void main(String[] args) {
        S12Target target = new S12Target();
        S12Proxy s12Proxy = new S12Proxy(new MethodInterceptor() {
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("前置增强");

//                method.invoke(target, args);// 反射调用
                  methodProxy.invoke(target, args); // 非反射调用,需要目标对象 Spring 使用
//                  methodProxy.invokeSuper(proxy, args); // 非反射调用,需要代理对象

                System.out.println("后置增强");
                return null;
            }
        });
        s12Proxy.s120();
        s12Proxy.s121(1);
        s12Proxy.s122(2,3);
    }
// 模拟代理类
public class S12Proxy extends S12Target {

    // cjlib 提供的接口
    private MethodInterceptor methodInterceptor;

    public S12Proxy(MethodInterceptor methodInterceptor) {
        this.methodInterceptor = methodInterceptor;
    }


    static Method m1;
    static Method m2;
    static Method m3;
    static MethodProxy mp1;
    static MethodProxy mp2;
    static MethodProxy mp3;

    static {
        try {
            m1 = S12Target.class.getMethod("s120");
            m2 = S12Target.class.getMethod("s121", int.class);
            m3 = S12Target.class.getMethod("s122", int.class, int.class);
            mp1 = MethodProxy.create(S12Target.class, S12Proxy.class, "()V", "s120", "ss120");
            mp2 = MethodProxy.create(S12Target.class, S12Proxy.class, "(I)V", "s121", "ss121");
            mp3 = MethodProxy.create(S12Target.class, S12Proxy.class, "(II)V", "s122", "ss122");
        } catch (NoSuchMethodException e) {
            throw new NoSuchMethodError(e.getMessage());
        }
    }

    public void ss120() {
        super.s120();
    }

    public void ss121(int i) {
        super.s121(i);
    }

    public void ss122(int i, int j) {
        super.s122(i, j);
    }


    @Override
    public void s120() {
        try {
            methodInterceptor.intercept(this, m1, new Object[0], mp1);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public void s121(int i) {
        try {
            methodInterceptor.intercept(this, m2, new Object[]{i}, mp2);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public void s122(int i, int j) {
        try {
            methodInterceptor.intercept(this, m3, new Object[]{i,j}, mp3);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }
}

// 目标类
public class S12Target {

    public void s120() {
        System.out.println("s120 running...");
    }

    public void s121(int i) {
        System.out.println("s121 running...");
    }

    public void s122(int i,int j) {
        System.out.println("s122 running...");
    }
}

和 jdk 动态代理原理查不多

  1. 回调的接口换了一下,InvocationHandler 改成了 MethodInterceptor
  2. 调用目标时有所改进,见下面代码片段
    1. method.invoke 是反射调用,必须调用到足够次数才会进行优化
    2. methodProxy.invoke 是不反射调用,它会正常(间接)调用目标对象的方法(Spring 采用)
    3. methodProxy.invokeSuper 也是不反射调用,它会正常(间接)调用代理对象的方法,可以省略目标对象

注意

  • 调用 Object 的方法, 后两种在 jdk >= 9 时都有问题, 需要 --add-opens java.base/java.lang=ALL-UNNAMED
posted @ 2022-06-22 16:03  xy7112  阅读(42)  评论(0)    收藏  举报