CodingTechWork
在 Java 开发中,动态代理技术被广泛应用于 AOP(面向切面编程)等场景。JDK 动态代理和 CGLIB 代理是两种常见的动态代理实现方式。它们各有特点和适用场景。本文将详细介绍这两种代理技术的原理、区别,并通过示例代码展示它们的实际应用,帮助你更好地选择合适的代理方式。
动态代理是指在运行时动态生成代理类和代理对象的技术。代理对象可以拦截对目标对象的调用,并在调用前后执行额外的逻辑。动态代理的核心在于:
JDK 动态代理是基于 Java 的反射机制
实现的。它要求目标类必须实现一个接口。代理类在运行时动态生成,实现了与目标类相同的接口。通过 java.lang.reflect.Proxy
类和 java.lang.reflect.InvocationHandler
接口来创建代理对象。
public interface MyService {
void doSomething();
}
public class MyServiceImpl implements MyService {
@Override
public void doSomething() {
System.out.println("Doing something...");
}
}
InvocationHandler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public 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: " + method.getName());
Object result = method.invoke(target, args);
System.out.println("After method: " + method.getName());
return result;
}
}
import java.lang.reflect.Proxy;
public class JdkProxyExample {
public static void main(String[] args) {
MyService target = new MyServiceImpl();
MyInvocationHandler handler = new MyInvocationHandler(target);
MyService proxy = (MyService) Proxy.newProxyInstance(
MyService.class.getClassLoader(),
new Class<?>[]{MyService.class},
handler
);
proxy.doSomething();
}
}
Before method: doSomething
Doing something...
After method: doSomething
CGLIB(Code Generation Library)是一个高性能的代码生成库,它通过字节码操作技术动态生成目标类的子类。因此,CGLIB 代理不需要目标类实现接口,但目标类不能是 final
类。通过 net.sf.cglib.proxy.Enhancer
类来创建代理对象。代理类在运行时动态生成,继承了目标类,并通过 MethodInterceptor
接口来处理方法调用。
public class MyService {
public void doSomething() {
System.out.println("Doing something...");
}
}
MethodInterceptor
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method: " + method.getName());
Object result = proxy.invokeSuper(obj, args);
System.out.println("After method: " + method.getName());
return result;
}
}
import net.sf.cglib.proxy.Enhancer;
public class CglibProxyExample {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MyService.class);
enhancer.setCallback(new MyMethodInterceptor());
MyService proxy = (MyService) enhancer.create();
proxy.doSomething();
}
}
Before method: doSomething
Doing something...
After method: doSomething
final
类,因为 CGLIB 通过生成子类来实现代理。JDK 动态代理和 CGLIB 代理各有优缺点,适用于不同的场景。JDK 动态代理简单易用,但需要目标类实现接口;CGLIB 代理无需接口,性能在某些场景下更好,但实现相对复杂。在实际开发中,可以根据具体需求选择合适的代理技术。