动态代理一般有哪几种实现方式?动态代理的应用场景有哪些?

103 阅读2分钟

动态代理是一种在运行时创建代理类的技术,它允许我们在不修改目标对象的情况下,为对象添加额外的功能。动态代理主要分为以下几种实现方式:

  1. Java 动态代理(JDK 动态代理)

    • 通过 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来实现。
    • 需要代理的类必须实现一个或多个接口。
    • 适用于接口较多且不需要对每个方法进行单独处理的场景。
  2. CGLIB 动态代理

    • 通过字节码技术为一个类创建子类来实现。
    • 不需要实现接口,直接代理类。
    • 适用于需要代理没有实现接口的类的场景。
  3. ASM 动态代理

    • 通过操作字节码来生成新的类。
    • 性能较高,但使用复杂,通常用于高性能要求的场景。
  4. Javassist 动态代理

    • 通过修改字节码来生成新的类。
    • 使用相对简单,性能较好,适用于需要动态生成类的场景。

动态代理的应用场景

  1. 事务管理

    • 在企业级应用中,事务管理是一个常见的需求。通过动态代理可以在方法调用前后自动开启和提交事务,简化事务管理代码。
  2. 日志记录

    • 在方法调用前后记录日志,方便调试和监控系统行为。
  3. 权限校验

    • 在方法调用前进行权限校验,确保只有授权用户才能执行特定的操作。
  4. 性能监控

    • 在方法调用前后记录时间,计算方法的执行时间,用于性能监控和优化。
  5. 缓存

    • 在方法调用前检查缓存,如果缓存中有结果则直接返回,减少重复计算。
  6. AOP(面向切面编程)

    • AOP 是一种编程范式,通过动态代理可以实现横切关注点的分离,如日志、事务、安全等。

示例代码

Java 动态代理示例

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface MyInterface {
    void doSomething();
}

class MyInterfaceImpl implements MyInterface {
    @Override
    public void doSomething() {
        System.out.println("Doing something...");
    }
}

class MyInvocationHandler implements InvocationHandler {
    private final Object target;

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

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

public class DynamicProxyExample {
    public static void main(String[] args) {
        MyInterface target = new MyInterfaceImpl();
        MyInterface proxy = (MyInterface) Proxy.newProxyInstance(
            MyInterface.class.getClassLoader(),
            new Class[]{MyInterface.class},
            new MyInvocationHandler(target)
        );
        proxy.doSomething();
    }
}

CGLIB 动态代理示例

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

class MyClass {
    public void doSomething() {
        System.out.println("Doing something...");
    }
}

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

public class CglibProxyExample {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyClass.class);
        enhancer.setCallback(new MyMethodInterceptor());
        MyClass proxy = (MyClass) enhancer.create();
        proxy.doSomething();
    }
}