Spring (10)AOP(面向切面编程)

71 阅读2分钟

面向切面编程(AOP)是一种编程范式,旨在提高代码的模块化程度。AOP通过将横切关注点(如日志、事务管理等)从业务逻辑代码中分离出来,增强了代码的重用性和可维护性。Spring框架中的AOP模块提供了强大的AOP支持,允许开发者以声明的方式来定义切面和通知(advice),从而实现横切关注点的模块化。

AOP核心概念

  • 切点(Pointcut):定义在哪些方法上进行拦截的规则。
  • 通知(Advice):拦截到方法后,所要执行的动作。通知类型包括前置通知(Before)、后置通知(After)、环绕通知(Around)、返回通知(AfterReturning)和异常通知(AfterThrowing)。
  • 切面(Aspect):切点和通知的结合。切面定义了在某个连接点(Join Point,如方法执行、异常抛出等)上采取的操作。
  • 织入(Weaving):将切面应用到目标对象并创建新的代理对象的过程。

Spring AOP实现

Spring AOP的实现是基于动态代理的。对于实现了接口的类,Spring AOP使用JDK动态代理;对于没有实现接口的类,Spring AOP使用CGLIB库生成被代理对象的子类。

源码分析

ProxyFactoryBean为例,展示Spring AOP是如何工作的。

ProxyFactoryBean是Spring AOP中用于生成代理对象的工厂Bean。在配置时,可以指定要代理的目标对象、接口和拦截器(advice)。

public class ProxyFactoryBean implements FactoryBean<Object>, BeanClassLoaderAware, ... {

    private TargetSource targetSource; // 目标对象
    private Advice[] interceptorsAndDynamicInterceptionAdvice; // 拦截器(advice)
    private Class<?>[] proxyInterfaces; // 代理接口

    // 创建代理对象的逻辑
    @Override
    public Object getObject() throws BeansException {
        // 根据targetSource、interceptorsAndDynamicInterceptionAdvice等创建代理对象
    }
}

代码演示

定义一个简单的业务接口及其实现类:

public interface UserService {
    void addUser();
}

public class UserServiceImpl implements UserService {
    @Override
    public void addUser() {
        System.out.println("Adding a user");
    }
}

创建一个切面,定义前置通知:

@Aspect
public class LogAspect {

    @Before("execution(* UserService.addUser(..))")
    public void beforeAddUser(JoinPoint joinPoint) {
        System.out.println("Before addUser: logging start");
    }
}

在Spring配置文件中配置切面和代理:

<aop:config>
    <aop:aspect ref="logAspect">
        <aop:pointcut id="addUserPointcut" expression="execution(* UserService.addUser(..))"/>
        <aop:before method="beforeAddUser" pointcut-ref="addUserPointcut"/>
    </aop:aspect>
</aop:config>

<bean id="userService" class="UserServiceImpl"/>
<bean id="logAspect" class="LogAspect"/>

addUser方法被调用时,切面中定义的前置通知会首先执行,打印日志信息。

关键点总结

  • Spring AOP通过提供声明式的切面定义,使得横切关注点的实现更加简洁和易于管理。
  • Spring AOP主要是通过动态代理实现的,这意味着它在运行时生成代理对象,通过代理对象来管理原始对象的调用并插入额外的行为。
  • AOP的使用能够提升代码的可维护性和可重用性,是实现关注点分离的有效技术手段。