介绍
Spring AOP(面向切面编程)是 Spring 框架的一个重要特性,它允许我们在程序运行期间为方法注入额外的行为。通过使用 AOP,我们可以将应用程序的关注点分离,使代码更清晰、可维护和可扩展。
Spring AOP 采用了代理模式来实现切面编程。在代理模式中,代理对象充当了目标对象的替代品,它可以在目标对象的方法执行前后注入额外的逻辑。
代理创建方式
Spring AOP 提供了两种代理创建方式:JDK 动态代理和 CGLIB 代理。这两种方式都是通过生成代理类来实现的,但是采用的实现方式有所不同。
JDK 动态代理
JDK 动态代理是通过 Java 反射机制来实现的。在 JDK 动态代理方式下,目标对象必须实现至少一个接口。Spring AOP 使用 java.lang.reflect.Proxy
类来生成代理对象。
代理对象的生成过程如下:
- 创建一个实现
InvocationHandler
接口的代理处理器对象,该对象用于处理方法的调用。 - 调用
Proxy.newProxyInstance()
方法,传入目标对象的类加载器和接口类型,以及代理处理器对象。该方法返回一个代理对象。 - 当调用代理对象的方法时,实际上会调用代理处理器的
invoke()
方法来处理方法调用。
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 class Main {
public static void main(String[] args) {
// 创建目标对象
UserService userService = new UserServiceImpl();
// 创建代理处理器
MyInvocationHandler handler = new MyInvocationHandler(userService);
// 创建代理对象
UserService proxy = (UserService) Proxy.newProxyInstance(
userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),
handler
);
// 调用代理对象的方法
proxy.login("username", "password");
}
}
CGLIB 代理
CGLIB(Code Generation Library)是一个强大的、高性能的代码生成库,可以在运行时动态生成字节码。CGLIB 代理不要求目标对象实现接口,因此更加灵活。Spring AOP 使用 CGLIB 库生成代理类和代理对象。
代理对象的生成过程如下:
- 创建一个
Enhancer
对象。 - 设置父类(目标对象)和回调函数(代理处理器)。
- 调用
Enhancer.create()
方法生成代理对象。 - 当调用代理对象的方法时,实际上会调用代理处理器的
intercept()
方法来处理方法调用。
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 class Main {
public static void main(String[] args) {
// 创建目标对象
UserService userService = new UserServiceImpl();
// 创建代理处理器
MyMethodInterceptor interceptor = new MyMethodInterceptor();
// 创建代理对象
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(userService.getClass());
enhancer.setCallback(interceptor);
UserService proxy = (UserService) enhancer.create();
// 调用代理对象的方法
proxy.login("username", "password");
}
}
总结
通过使用 Spring AOP 的代理创建方式,我们可以在方法调用前后注入额外的逻辑,提高应用程序的可维护性和可扩展性。JDK 动态代理适用于目标对象实现了至少一个接口的情况,而 CGLIB 代理则适用于任意的目标对象。在实际应用中,我们可以根据具体情况选择适合的代理创建方式,并利用 AOP 实现横切关注点的解耦。
本文来自极简博客,作者:无尽追寻,转载请注明原文链接:Spring AOP 代理创建方式