java动态代理怎么实现

478
2023/11/29 14:40:03
栏目: 编程语言
开发者测试专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

Java动态代理可以通过以下几种方式实现:

  1. 使用java.lang.reflect.Proxy类:Proxy类提供了一个静态方法newProxyInstance(),可以通过传入目标对象的类加载器、目标对象实现的接口和InvocationHandler接口的实现类来创建代理对象。InvocationHandler接口的实现类负责处理代理对象的方法调用。代理对象在调用方法时,会把方法调用转发给InvocationHandlerinvoke()方法,从而实现代理功能。
public interface Subject {
    void doSomething();
}

public class RealSubject implements Subject {
    public void doSomething() {
        System.out.println("RealSubject doSomething");
    }
}

public class MyInvocationHandler implements InvocationHandler {
    private Subject target;

    public MyInvocationHandler(Subject target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method invoke");
        Object result = method.invoke(target, args);
        System.out.println("After method invoke");
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        Subject realSubject = new RealSubject();
        Subject proxySubject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),
                realSubject.getClass().getInterfaces(),
                new MyInvocationHandler(realSubject));
        proxySubject.doSomething();
    }
}
  1. 使用CGLib库:CGLib是一个基于ASM框架的字节码生成库,它可以在运行时动态生成目标对象的子类,并覆盖其中的方法以实现代理功能。
public interface Subject {
    void doSomething();
}

public class RealSubject implements Subject {
    public void doSomething() {
        System.out.println("RealSubject doSomething");
    }
}

public class MyMethodInterceptor implements MethodInterceptor {
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before method invoke");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("After method invoke");
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(RealSubject.class);
        enhancer.setCallback(new MyMethodInterceptor());
        Subject proxySubject = (Subject) enhancer.create();
        proxySubject.doSomething();
    }
}

需要注意的是,使用CGLib实现动态代理时,目标对象不能是final类或者包含final方法,因为CGLib是通过生成目标对象的子类来实现代理的。

  1. 使用ByteBuddy库:ByteBuddy是一个轻量级的字节码操作库,它可以在运行时动态生成目标对象的子类,并覆盖其中的方法以实现代理功能。
public interface Subject {
    void doSomething();
}

public class RealSubject implements Subject {
    public void doSomething() {
        System.out.println("RealSubject doSomething");
    }
}

public class MyInterceptor implements MethodInterceptor {
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before method invoke");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("After method invoke");
        return result;
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        Class<? extends Subject> proxyClass = new ByteBuddy()
                .subclass(Subject.class)
                .method(any()).intercept(MethodDelegation.to(MyInterceptor.class))
                .make()
                .load(RealSubject.class.getClassLoader())
                .getLoaded();
        Subject proxySubject = proxyClass.getDeclaredConstructor().newInstance();
        proxySubject.doSomething();
    }
}

需要注意的是,使用ByteBuddy实现动态代理时,需要引入net.bytebuddy:byte-buddynet.bytebuddy:byte-buddy-agent两个依赖。

辰迅云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

推荐阅读: java触发器的作用是什么