Spring的AOP

一、什么是AOP   

        Spring的AOP(面向切面编程,Aspect-Oriented Programming)是一种编程范式,它允许你将横切关注点(cross-cutting concerns)从业务逻辑中分离出来。横切关注点是指那些影响多个类或模块的功能,如日志记录、事务管理、权限检查等。通过AOP,这些功能可以被集中管理和处理,而无需在每个业务逻辑方法中重复编写代码。

二、AOP的核心概念

1、切面(Aspect)

        切面是包含横切逻辑的组件。它可以是一个类,其中定义了通知(Advice)和切入点(Pointcut)。切面将横切关注点模块化为可重用的组件。

2、通知(Advice)

        通知是在特定连接点执行的代码。它定义了在何处以及如何执行横切逻辑。Spring AOP支持五种类型的通知:

  1. Before:前置通知,在方法调用之前执行。
  2. After:后置通知,在方法调用之后执行,无论方法是否抛出异常。
  3. After-returning:返回通知,仅在方法成功返回后执行。
  4. After-throwing:异常通知,仅在方法抛出异常时执行。
  5. Around:环绕通知,在方法调用前后都可以执行自定义逻辑。

 3、切入点(Pointcut)

        切入点定义了通知应该应用到哪些连接点。它是一组匹配的方法或类的规则,通常使用表达式来指定。例如,execution(* com.example.service.*.*(..))表示匹配com.example.service包下的所有方法。

 4、连接点(Join Point)

        连接点是程序执行过程中的某个点,比如方法调用、异常抛出等。在Spring AOP中,连接点通常是方法调用。

5、引入(Introduction)

        引入允许你向现有类添加新的方法或属性。虽然不常用,但在某些情况下可以增强现有类的功能。

6、织入(Weaving)

        织入是将切面应用到目标对象的过程。织入可以在编译时、类加载时或运行时进行。Spring AOP采用的是运行时织入,即通过代理机制在运行时动态地将切面应用到目标对象。

三、Spring AOP的工作原理

        Spring AOP基于代理模式实现。对于Spring管理的Bean,默认使用JDK动态代理(如果接口存在)或CGLIB代理(如果不存在接口)。代理对象会拦截对目标对象方法的调用,并在适当的时候插入横切逻辑。
        AOP适用于以下场景:
            1、日志记录:在方法调用前后记录日志。
            2、事务管理:在服务层方法上自动管理事务。
            3、权限检查:在访问敏感资源前进行权限验证。
            4、性能监控:统计方法执行时间。
            5、缓存管理:在方法调用前后控制缓存的读取和写入。
       通过AOP,开发者可以更清晰地分离关注点,使代码更加模块化和易于维护。

四、配置Spring AOP的切面

        在Spring框架中,配置AOP切面主要可以通过‌注解驱动‌和‌XML配置‌两种方式实现。

1、注解驱动配置(推荐方式)

(1)启用AOP自动代理

  在Spring Boot或Java配置类中添加注解启用自动代理:

@Configuration
    @EnableAspectJAutoProxy  // 启用AOP自动代理
    public class AppConfig {
}
(2)定义切面类

   使用@Aspect注解标记切面类,并通过@Component使其被Spring管理:

@Aspect
@Component
public class LoggingAspect {

    // 定义切点:匹配com.example.service包下所有类的所有方法
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceLayer() {}

    // 前置通知
    @Before("serviceLayer()")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("方法调用前:" + joinPoint.getSignature().getName());
    }

    // 环绕通知(可控制是否执行原方法)
    @Around("serviceLayer()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕通知-方法开始");
        Object result = joinPoint.proceed(); // 执行目标方法
        System.out.println("环绕通知-方法结束");
        return result;
    }
}
(3)切点表达式说明
  • execution(* com.service.*.*(..)): 匹配com.service包下的所有方法
  • @annotation(com.example.Loggable): 匹配带有@Loggable注解的方法

2、XML配置方式(传统配置)

(1)启用AOP命名空间 

  在applicationContext.xml中添加AOP命名空间:


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>

(2)配置切面

<!-- 定义切面Bean -->
<bean id="loggingAspect" class="com.example.aspect.LoggingAspect"/>

<!-- AOP配置 -->
<aop:config>
    <aop:aspect ref="loggingAspect">
        <!-- 定义切点 -->
        <aop:pointcut id="serviceMethods" 
            expression="execution(* com.example.service.*.*(..))"/>
        
        <!-- 前置通知 -->
        <aop:before method="logBefore" pointcut-ref="serviceMethods"/>
        
        <!-- 环绕通知 -->
        <aop:around method="logAround" pointcut-ref="serviceMethods"/>
    </aop:aspect>
</aop:config>

3、进阶配置技巧

(1)组合切点表达式

@Pointcut("execution(* com.service.*.*(..)) && args(param)")
public void serviceMethodsWithParam(String param) {}

@Before("serviceMethodsWithParam(param)")
public void logParam(String param) {
    System.out.println("参数值:" + param);
}

(2)使用自定义注解标记切点

   定义注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Auditable {}

   切面配置:

@After("@annotation(com.example.Auditable)")
public void auditAction() {
    System.out.println("执行XXX操作");
}

4、配置方式对比

配置方式优点缺点
注解驱动简洁直观,与代码紧密结合切面逻辑分散在多个类中
XML配置集中管理切面,便于统一修改配置冗余,可读性较低

        实际开发中‌推荐注解驱动方式‌,特别是在Spring Boot项目中默认支持自动代理,XML配置更适合需要集中管理AOP规则的传统项目。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码的余温

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值