spring 11 jdk 动态代理进阶

jdk 动态代理进阶

模拟 jdk 动态代理

点击查看代码

    public static void main(String[] args) {
        B b = new B();
        A proxyInstance = (A) new $Proxy0(new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("before...");
                Object result = method.invoke(b, args);
                System.out.println("after...");
                return result;
            }
        });
        proxyInstance.a();
        proxyInstance.b();
    }

模拟代理实现
// Proxy 类中含有 protected 属性 InvocationHandler 
public class $Proxy0 extends Proxy implements A{
//    private java.lang.reflect.InvocationHandler h;

    static Method a;
    static Method b;

    static {
        try {
            a = A.class.getMethod("a");
            b = A.class.getMethod("b");
        } catch (NoSuchMethodException e) {
            throw new NoSuchMethodError(e.getMessage()); //静态代码块错误,说明错误很严重,用 Error.
        }
    }

    @Override
    public int a() {
        try {
            Object result = h.invoke(this, a, new Object[0]);
            return (int) result;

        } catch (RuntimeException | Error e) {
            throw e;  //运行时异常可直接抛出
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public int b() {
        try {
            Object result = h.invoke(this, b, new Object[0]);
            return (int) result;
        }catch (RuntimeException | Error e){
            throw e;
        }catch (Throwable e){
            throw new UndeclaredThrowableException(e);
        }
    }

    public $Proxy0(InvocationHandler h) {
        super(h);
//        this.invocationHandler = invocationHandler;
    }


}

// 如果 b 方法有参数,更改即可。
 public int b(int i) {
        try {
            Object result = h.invoke(this, b, new Object[]{i});
            return (int) result;
        }catch (RuntimeException | Error e){

public interface A {
    int a();
    int b();
}

public class B implements A{
    @Override
    public int a() {
        System.out.println("B a running...");
        return 57;
    }

    @Override
    public int b() {
        System.out.println("B b running...");
        return 58;
    }
}

public interface InvocationHandler {
    Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

代理一点都不难,无非就是利用了多态、反射的知识

  1. 方法重写可以增强逻辑,只不过这【增强逻辑】千变万化,不能写死在代理内部
  2. 通过接口回调将【增强逻辑】置于代理类之外
  3. 配合接口方法反射(是多态调用),就可以再联动调用目标方法
  4. 会用 arthas 的 jad 工具反编译代理类, jdk 动态代理生成的代理类直接就是字节码,没有源代码,所有要借助工具查看。(运用 ASM 技术,用于很多框架)
  5. 限制⛔:代理增强是借助多态来实现,因此成员变量、静态方法、final 方法均不能通过代理实现

方法反射优化

  1. 前 16 次反射性能较低
  2. 第 17 次调用会生成代理类,优化为非反射调用,一个方法优化生成一个代理类。两个方法就是两个。而 cjlib 中一个类的所有方法的优化生成两个代理类就行。
  3. 会用 arthas 的 jad 工具反编译第 17 次调用生成的代理类

注意

运行时请添加 --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/jdk.internal.reflect=ALL-UNNAMED

arthas 的使用

参考:https://blog.csdn.net/u012002125/article/details/125066186

posted @ 2022-06-21 17:16  xy7112  阅读(57)  评论(0)    收藏  举报