在Spring中,主要使用两种动态代理方式:JDK动态代理和CGLIB动态代理。

  1. 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);
        }
    }
    
  2. 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

发表回复 0

Your email address will not be published.