Spring 提供了两种主要的代理(proxy)方式,分别是基于JDK动态代理和基于CGLIB的代理。这两种代理方式各有其特点和适用场景。
1. JDK动态代理
特点:
 - 基于Java的接口(Interface)。
 - 代理类必须实现一个或多个接口。
 - 使用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现。
优点:
 - 实现简单,性能较好。
 - 生成的代理类是接口的实现类,遵循面向接口编程的原则。
缺点:
 - 只能代理接口,无法代理具体类。
适用场景:
 - 被代理对象有一个或多个接口时。
代码示例:
java
 public interface Service {
     void perform();
 }
public class ServiceImpl implements Service {
     @Override
     public void perform() {
         System.out.println("Performing service...");
     }
 }
import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
public class ServiceInvocationHandler implements InvocationHandler {
     private final Object target;
    public ServiceInvocationHandler(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 static void main(String[] args) {
         ServiceImpl service = new ServiceImpl();
         Service proxy = (Service) Proxy.newProxyInstance(
                 service.getClass().getClassLoader(),
                 new Class[]{Service.class},
                 new ServiceInvocationHandler(service)
         );
         proxy.perform();
     }
 }
  2. CGLIB代理
特点:
 - 基于字节码生成,使用底层字节码增强技术。
 - 可以代理没有实现接口的具体类。
 - 使用net.sf.cglib.proxy.Enhancer类和net.sf.cglib.proxy.MethodInterceptor接口来实现。
优点:
 - 可以代理具体类,不需要依赖接口。
 - 能够代理方法调用,提高灵活性。
缺点:
 - 性能比JDK动态代理稍差。
 - 生成的代理类是目标类的子类,可能会有一些不兼容的情况(例如目标类是final类,或者目标方法是final方法时无法代理)。
适用场景:
 - 被代理对象没有接口,或者需要代理类中的具体方法时。
代码示例:
java
 import net.sf.cglib.proxy.Enhancer;
 import net.sf.cglib.proxy.MethodInterceptor;
 import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class Service {
     public void perform() {
         System.out.println("Performing service...");
     }
 }
public class ServiceMethodInterceptor 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 static void main(String[] args) {
         Enhancer enhancer = new Enhancer();
         enhancer.setSuperclass(Service.class);
         enhancer.setCallback(new ServiceMethodInterceptor());
         Service proxy = (Service) enhancer.create();
         proxy.perform();
     }
 }
  总结
- 使用JDK动态代理时,必须有接口,适用于面向接口编程的场景。
 - 使用CGLIB代理时,不需要接口,适用于需要代理具体类的方法的场景。
 - Spring AOP默认使用JDK动态代理,如果没有接口才使用CGLIB代理。可以通过配置明确指定代理方式。