Spring AOP 代理创建方式

无尽追寻 2024-05-22 ⋅ 21 阅读

介绍

Spring AOP(面向切面编程)是 Spring 框架的一个重要特性,它允许我们在程序运行期间为方法注入额外的行为。通过使用 AOP,我们可以将应用程序的关注点分离,使代码更清晰、可维护和可扩展。

Spring AOP 采用了代理模式来实现切面编程。在代理模式中,代理对象充当了目标对象的替代品,它可以在目标对象的方法执行前后注入额外的逻辑。

代理创建方式

Spring AOP 提供了两种代理创建方式:JDK 动态代理和 CGLIB 代理。这两种方式都是通过生成代理类来实现的,但是采用的实现方式有所不同。

JDK 动态代理

JDK 动态代理是通过 Java 反射机制来实现的。在 JDK 动态代理方式下,目标对象必须实现至少一个接口。Spring AOP 使用 java.lang.reflect.Proxy 类来生成代理对象。

代理对象的生成过程如下:

  1. 创建一个实现 InvocationHandler 接口的代理处理器对象,该对象用于处理方法的调用。
  2. 调用 Proxy.newProxyInstance() 方法,传入目标对象的类加载器和接口类型,以及代理处理器对象。该方法返回一个代理对象。
  3. 当调用代理对象的方法时,实际上会调用代理处理器的 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 库生成代理类和代理对象。

代理对象的生成过程如下:

  1. 创建一个 Enhancer 对象。
  2. 设置父类(目标对象)和回调函数(代理处理器)。
  3. 调用 Enhancer.create() 方法生成代理对象。
  4. 当调用代理对象的方法时,实际上会调用代理处理器的 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 实现横切关注点的解耦。


全部评论: 0

    我有话说: