Spring中的AOP机制

一、AOP的定义

        AOP,也就是 Aspect - oriented Programming,译为面向切面编程,是计算机科学中的一个设计思想,旨在通过切面技术为业务主体增加额外的通知(Advice),从而对声明为“切点”(Pointcut)的代码块进行统一管理和装饰。

注:一般在项目的日志模块中使用。

        AOP 是对面向对象编程( Object - oriented Programming,简称 OOP)的一种补充,OOP 的核心单元是类( class),而 AOP 的核心单元是切面( Aspect)。利用 AOP 可以对业务逻辑的各个部分进行隔离,从而降低耦合度,提高程序的可重用性,同时也提高了开发效率。

注: AOP 理解为贯穿于方法之中,在方法执行前、执行时、执行后、返回值后、异常后要执行的操作。

二、AOP的相关术语

 AOP 涉及到的 5 个关键术语:

        1. 横切关注点,从每个方法中抽取出来的同一类非核心业务。

        2. 切面(Aspect),对横切关注点进行封装的类,每个关注点体现为一个通知方法;通常使用 @Aspect 注解来定义切面。

        3. 通知(Advice),切面必须要完成的各个具体工作,比如我们要获得日志调用接口前后的时长,就需要在调用接口前后记录时间,再取差值。

通知的方式有五种: 

  •         @Before:通知方法会在目标方法调用之前执行
  •         @After:通知方法会在目标方法调用后执行
  •         @AfterReturning:通知方法会在目标方法返回后执行
  •         @AfterThrowing::通知方法会在目标方法抛出异常后执行事
  •         @Around:把整个目标方法包裹起来,在被调用前和调用之后分别执行通知方法

例如: 

@Aspect
@Component
public class MyAspect {

    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceMethods() {}

    @Before("serviceMethods()")
    public void beforeServiceMethods(JoinPoint joinPoint) {
        System.out.println("Before method: " + joinPoint.getSignature());
    }

    @AfterReturning(pointcut = "serviceMethods()", returning = "result")
    public void afterReturningServiceMethods(JoinPoint joinPoint, Object result) {
        System.out.println("After returning method: " + joinPoint.getSignature() + ", with result: " + result);
    }
}

        4. 连接点(JoinPoint),通知应用的时机,比如接口方法被调用时就是日志切面的连接点。

        5. 切点(Pointcut),通知功能被应用的范围,比如本篇日志切面的应用范围是所有 controller 的接口。通常使用 @Pointcut 注解来定义切点表达式。

三、切点表达式的基本结构

@Pointcut("切点表达式")
public void pointcutMethod() {}
 1、切点表达式语法

        切点表达式由多个部分组成,每个部分用于匹配不同的连接点。

主要有以下几种常用的表达式类型:

 1.1、'execution' 表达式

  用于匹配方法执行的连接点。语法如下:

execution(modifiers-pattern? 
           ret-type-pattern declaring-type-pattern? 
            name-pattern(param-pattern) 
             throws-pattern?)
  • 'modifiers-pattern':方法的修饰符,如 publicprotected 等。可以省略。
  • 'ret-type-pattern':返回类型模式,可以是具体类型,也可以是通配符 * 表示所有类型。
  • 'declaring-type-pattern':方法所属类的模式,可以是具体类名,也可以是包名加通配符。
  • 'name-pattern':方法名模式,可以是具体方法名,也可以是通配符。
  • 'param-pattern':参数模式,用于匹配方法的参数列表。
  • 'throws-pattern':抛出异常模式,可以省略。

 例如:

@Pointcut("execution(public * com.example.service.*.*(..))")
public void anyPublicMethod() {}

匹配 'com.example.service' 包中所有类的任何 public 方法。

 1.2、'within' 表达式

 用于匹配指定类型内的所有连接点。语法如下:

within(type-pattern)

 例如:

@Pointcut("within(com.example.service..*)")
public void inServiceLayer() {}

匹配 'com.example.service' 包及其子包中的所有类的所有方法。

1.3、'this' 表达式

用于匹配代理对象是指定类型的连接点。语法如下:

this(type)

例如:

@Pointcut("this(com.example.service.MyService)")
public void proxyIsMyService() {}

匹配代理对象是 'MyService' 类型的连接点。

1.4、'target' 表达式

用于匹配目标对象(即被代理的对象)是指定类型的连接点。语法如下:

target(type)

例如:

@Pointcut("target(com.example.service.MyService)")
public void targetIsMyService() {}

匹配目标对象是 'MyService' 类型的连接点。

1.5、'args' 表达式

用于匹配方法参数是指定类型的连接点。语法如下:

args(argument-type-pattern)

例如:

@Pointcut("args(java.io.Serializable)")
public void argsSerializable() {}

匹配方法参数是 'Serializable' 类型的连接点。

1.6、'@annotation' 表达式

用于匹配方法上有指定注解的连接点。语法如下:

@annotation(annotation-type)

例如:

@Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
public void transactionalMethods() {}

匹配所有带有 '​​​​​​​@Transactional' 注解的方法。

2、组合表达式

        切点表达式可以通过逻辑运算符进行组合。

组合类型:

  • '&&' :与
  • '||' :或
  • '!'   :非

例如:

@Pointcut("execution(* com.example..*.*(..)) && !within(com.example.service..*)")
public void excludeServiceLayer() {}

匹配 '​​​​​​​com.example' 包及其子包中的所有方法,但不包括 '​​​​​​​com.example.service' 包及其子包中的方法。

四、小结

        遵循Spring AOP中切点表达式的基本规范和使用方法,通过合理定义切点表达式,可以精确控制切面逻辑的应用范围。

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值