蒙圈的备忘录:SpringBoot AOP

SpringBoot AOP切面编程

引言

springboot是对原有项目中spring框架和springmvc的进一步封装,因此在springboot中同样支持spring框架中AOP切面编程,不过在springboot中为了快速开发仅仅提供了注解方式的切面编程.

使用

引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

相关注解

 切面注解
 @Aspect 用来类上,代表这个类是一个切面
 @Before 用在方法上代表这个方法是一个前置通知方法 
 @After 用在方法上代表这个方法是一个后置通知方法 @Around 用在方法上代表这个方法是一个环绕的方法
 @Around 用在方法上代表这个方法是一个环绕的方法
前置切面
@Aspect
@Configuration
public class MyAspect {
   //@Before 代表这是一个核心业务逻辑执行之前附加操作  value:用来书写切入点表达式 配置附加操作在哪里生效
    @Before("execution(* com.wdj.springboot_aop.service1.*.*(..))")
    public void before(JoinPoint joinPoint) {
        System.out.println("=========前置附加操作=========");
        System.out.println("当前执行目标类: " + joinPoint.getTarget());
        System.out.println("当前执行目标类中方法: " + joinPoint.getSignature().getName());
        System.out.println("当前执行目标方法所属类的简单类名: " + joinPoint.getSignature().getDeclaringType().getSimpleName());
        System.out.println("当前执行目标方法所属类的类名: " + joinPoint.getSignature().getDeclaringTypeName());
        System.out.println("当前执行目标方法声明类型: " + Modifier.toString(joinPoint.getSignature().getModifiers()));
    }
}
后置切面
@Aspect
@Configuration
public class MyAspect {
    @After("within(com.wdj.springboot_aop.service2.*)")
    public void after(JoinPoint joinPoint){
        System.out.println("========后置附加操作==========");
        System.out.println("当前执行目标类: "+ joinPoint.getTarget());
        System.out.println("当前执行目标类中方法: "+ joinPoint.getSignature().getName());
        System.out.println("当前执行目标方法所属类的简单类名: " + joinPoint.getSignature().getDeclaringType().getSimpleName());
        System.out.println("当前执行目标方法所属类的类名: " + joinPoint.getSignature().getDeclaringTypeName());
        System.out.println("当前执行目标方法声明类型: " + Modifier.toString(joinPoint.getSignature().getModifiers()));
    }
}

注意: 前置通知和后置通知都没有返回值,方法参数都为joinpoint

环绕切面
@Aspect
@Configuration
public class MyAspect {
    //表示被@MyAdvice注释标注的类会执行此环绕方法
    @Around("@annotation(com.wdj.springboot_aop.annotations.MyAdvice)")
    // 返回值作用: 用来讲业务方法返回结果返回给调用者
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("==========进入环绕的前置操作===========");
        //ProceedingJoinPoint继承了JoinPoint
        System.out.println("当前执行类: "+proceedingJoinPoint.getTarget());
        System.out.println("方法名: "+proceedingJoinPoint.getSignature().getName());
        //放行目标方法执行
        //还可以更改目标方法的参数
        Object proceed = proceedingJoinPoint.proceed();//继续处理  业务逻辑方法执行
        System.out.println("==========进入环绕的后置操作===========");
        return proceed;
    }
}

注意: 环绕通知存在返回值,参数为ProceedingJoinPoint,如果执行放行,不会执行目标方法,一旦放行必须将目标方法的返回值返回,否则调用者无法接受返回数据

自定义注解
//指定运行时生效
//用来控制注解的生命周期
@Retention(RetentionPolicy.RUNTIME)//@Retention作用是定义被它所注解的注解保留多久

//用于描述注解的适用范围 {被描述的注解可以用在什么地方}
@Target(ElementType.METHOD)

//用于描述其他类型的annotation应该被做为被标注的程序成员的公告Api(非必要)
@Documented
public @interface MyAdvice {

}

Spring AOP 切入点表达式

Spring AOP 支持以下用于切入点表达式的 AspectJ 切入点指示符 (PCD):

1、execution: 用于匹配方法执行连接点。这是使用 Spring AOP 时要使用的主要切入点指示符。

* :匹配任何数量字符
..:匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数
+ :匹配指定类型的子类型;仅能作为后缀放在类型模式后边

在这里插入图片描述

//任何公共方法:
 execution(public * *(..))
// 任何名称以set开头的方法:
 execution(* set*(..))
//AccountService接口定义的任何方法的执行:
execution(* com.xyz.service.AccountService.*(..))
//service包中定义的任何方法的执行:
execution(* com.xyz.service.*.*(..))
//service或其子包之一中定义的任何方法的执行:
execution(* com.xyz.service..*.*(..))

2、within:将匹配限制为某些类型内的连接点(使用 Spring AOP 时在匹配类型中声明的方法的执行)。

注意:within只能指定类,然后该类内的所有方法都将被匹配

//service内的任何连接点(方法只在 Spring AOP 中执行):
within(com.xyz.service.*)
//service或其子包之一中的任何连接点(仅在 Spring AOP 中执行方法):
within(com.xyz.service..*)
//目标对象的声明类型具有@Transactional注释的任何连接点(仅在 Spring AOP 中执行方法):
@within(org.springframework.transaction.annotation.Transactional)

3、this: 限制匹配连接点(使用 Spring AOP 时的方法执行),其中 bean 引用(Spring AOP 代理)是给定类型的实例。

//代理实现AccountService接口的任何连接点(仅在 Spring AOP 中执行方法) :
this(com.xyz.service.AccountService)

4、target: 限制匹配连接点(使用 Spring AOP 时的方法执行),其中目标对象(被代理的应用程序对象)是给定类型的实例。

功能:匹配type类型的目标对象的所有方法。即目标对象可以向上转型为type类型就算是匹配成功

//当前目标对象(非AOP代理对象)实现了 IPointcutService接口的任何方法
target(cn.javass.spring.chapter6.service.IPointcutService)
//当前目标对象(非AOP代理对象) 实现了IIntroductionService 接口的任何方法。不可能是引入接口
target(cn.javass.spring.chapter6.service.IIntroductionService)

5、 args: 限制匹配连接点(使用 Spring AOP 时的方法执行),其中参数是给定类型的实例。

性能消耗比较大,一般不用

//任何带有单个参数的连接点(仅在 Spring AOP 中执行方法),并且在运行时传递的参数是Serializable:
args(java.io.Serializable)

6、@target: 将匹配限制为连接点(使用 Spring AOP 时的方法执行),其中执行对象的类具有给定类型的注释。

//目标对象具有@Transactional注释的任何连接点(仅在 Spring AOP 中执行方法) :
@target(org.springframework.transaction.annotation.Transactional)

7、@args:限制匹配连接点(使用 Spring AOP 时的方法执行),其中传递的实际参数的运行时类型具有给定类型的注释。

//任何带有单个参数的连接点(仅在 Spring AOP 中执行方法),并且传递的参数的运行时类型具有@Classified注释:
@args(com.xyz.security.Classified)

8、@within: 限制匹配到具有给定注解的类型中的连接点(使用 Spring AOP 时,在具有给定注解的类型中声明的方法的执行)。

在这里插入代码片

9、@annotation:将匹配限制为连接点的主题(在 Spring AOP 中运行的方法)具有给定注释的连接点。

//任何连接点(方法仅在 Spring AOP 中执行),其中执行的方法有一个 @Transactional注解:
 @annotation(org.springframework.transaction.annotation.Transactional)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值