在Spring中,主要使用两种动态代理方式:JDK动态代理和CGLIB动态代理。
-
JDK动态代理:
- JDK动态代理是基于Java反射机制实现的。它要求目标对象必须实现一个或多个接口,然后通过
java.lang.reflect.Proxy
类创建代理对象。代理对象实现了被代理接口,并将方法的调用委托给InvocationHandler
接口的实现类,从而实现动态代理。
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MyInvocationHandler implements InvocationHandler { private 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 invocation"); Object result = method.invoke(target, args); System.out.println("After method invocation"); return result; } public Object createProxy() { return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } }
- JDK动态代理是基于Java反射机制实现的。它要求目标对象必须实现一个或多个接口,然后通过
-
CGLIB动态代理:
- CGLIB动态代理是通过继承的方式实现的。它创建目标对象的子类,并重写了目标对象的方法。因为CGLIB是基于字节码生成的,所以不要求目标对象实现接口。
import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class MyMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 在方法调用前后添加逻辑 System.out.println("Before method invocation"); Object result = proxy.invokeSuper(obj, args); System.out.println("After method invocation"); return result; } public Object createProxy(Class<?> targetClass) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(targetClass); enhancer.setCallback(this); return enhancer.create(); } }
在Spring中,如果目标对象实现了接口,则使用JDK动态代理;如果目标对象没有实现接口,则使用CGLIB动态代理。Spring AOP默认使用JDK动态代理,但可以通过配置强制使用CGLIB动态代理。例如:
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true) // 强制使用CGLIB代理
public class AppConfig {
// 配置内容
}
总体而言,JDK动态代理和CGLIB动态代理各有优劣,选择取决于具体的业务需求和对象结构。
Was this helpful?
0 / 0