动态代理是一种在运行时创建代理类的技术,它允许我们在不修改目标对象的情况下,为对象添加额外的功能。动态代理主要分为以下几种实现方式:
-
Java 动态代理(JDK 动态代理) :
- 通过
java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现。 - 需要代理的类必须实现一个或多个接口。
- 适用于接口较多且不需要对每个方法进行单独处理的场景。
- 通过
-
CGLIB 动态代理:
- 通过字节码技术为一个类创建子类来实现。
- 不需要实现接口,直接代理类。
- 适用于需要代理没有实现接口的类的场景。
-
ASM 动态代理:
- 通过操作字节码来生成新的类。
- 性能较高,但使用复杂,通常用于高性能要求的场景。
-
Javassist 动态代理:
- 通过修改字节码来生成新的类。
- 使用相对简单,性能较好,适用于需要动态生成类的场景。
动态代理的应用场景
-
事务管理:
- 在企业级应用中,事务管理是一个常见的需求。通过动态代理可以在方法调用前后自动开启和提交事务,简化事务管理代码。
-
日志记录:
- 在方法调用前后记录日志,方便调试和监控系统行为。
-
权限校验:
- 在方法调用前进行权限校验,确保只有授权用户才能执行特定的操作。
-
性能监控:
- 在方法调用前后记录时间,计算方法的执行时间,用于性能监控和优化。
-
缓存:
- 在方法调用前检查缓存,如果缓存中有结果则直接返回,减少重复计算。
-
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();
}
}