Spring 框架支持两种主要的动态代理技术:JDK 动态代理和 CGLIB 代理。它们都可以用于实现面向切面编程(AOP)功能。下面将详细介绍这两种代理的实现方式,并提供示例代码。
1. JDK 动态代理
JDK 动态代理要求被代理的对象实现一个或多个接口。Spring 使用 java.lang.reflect.Proxy 类来创建代理实例。
步骤:
定义接口
public interface GreetingService {
void greet(String name);
}
实现接口
public class GreetingServiceImpl implements GreetingService {
@Override
public void greet(String name) {
System.out.println("Hello, " + name);
}
}
创建 InvocationHandler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class LoggingInvocationHandler implements InvocationHandler {
private final Object target;
public LoggingInvocationHandler(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;
}
}
使用代理
public class Main {
public static void main(String[] args) {
GreetingService service = new GreetingServiceImpl();
GreetingService proxy = (GreetingService) Proxy.newProxyInstance(
service.getClass().getClassLoader(),
service.getClass().getInterfaces(),
new LoggingInvocationHandler(service)
);
proxy.greet("Alice");
}
}
2. CGLIB 代理
CGLIB 代理不需要目标对象实现接口,而是通过继承目标类来创建代理。Spring 使用 CGLIB 来实现对非接口类的代理。
步骤:
创建目标类
public class GreetingService {
public void greet(String name) {
System.out.println("Hello, " + name);
}
}
创建 MethodInterceptor
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class LoggingMethodInterceptor 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;
}
}
使用 CGLIB 代理
import org.springframework.cglib.proxy.Enhancer;
public class Main {
public static void main(String[] args) {
GreetingService service = new GreetingService();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(GreetingService.class);
enhancer.setCallback(new LoggingMethodInterceptor());
GreetingService proxy = (GreetingService) enhancer.create();
proxy.greet("Bob");
}
}
Spring 动态代理通过 JDK 动态代理和 CGLIB 代理提供了强大的功能。JDK 动态代理适用于实现了接口的类,而 CGLIB 代理则可以用于没有实现接口的类。通过动态代理,你可以在不修改目标对象代码的情况下,添加横切关注点(如日志、事务管理等)。