SpringBoot中的AOP使用

SpringBoot中的AOP使用

1.AOP介绍

Spring的AOP利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,
简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。

总结:AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。

2. AOP 编程术语

2.1切面(Aspect)

切面泛指交叉业务逻辑,或是公共的,通用的业务。上例中的事务处理、日志处理就可以理解为切面。常用的切面是通知(Advice)。实际就是对主业务逻辑的一种增强。

切面有切点和通知组成,即包括横切逻辑的定义也包括连接点的定义

2.2连接点(JoinPoint)

连接点指可以被切面织入的具体方法。通常业务接口中的方法均为连接点。

程序执行的某个特定位置,如某个方法调用前后等。

2.3切入点(Pointcut)

切入点指声明的一个或多个连接点的集合。通过切入点指定一组方法。
被标记为 final 的方法是不能作为连接点与切入点的。因为最终的是不能被修改的,不能被增强的。

在程序应用中就是你要增强功能的类或方法(确认位置)。

2.4目标对象(Target)

目标对象指 将要被增强 的对象。 即包含主业 务逻辑的 类的对象。 上例中 的
BookServiceImpl 的对象若被增强,则该类称为目标类,该类对象称为目标对象。当然, 不被增强,也就无所谓目标不目标了。

目标对象,通知织入的目标类。

2.5通知(Advice)

通知表示切面的执行时间,Advice 也叫增强。上例中的 MyInvocationHandler 就可以理解为是一种通知。换个角度来说,通知定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是之后执行等。通知类型不同,切入时间不同。
切入点定义切入的位置,通知定义切入的时机。

通知,是织入到目标类连接点上的一段代码,就是增强到什么地方?增强什么内容?

3.切入点表达式

3.1AspectJ表达式

表达式共 4 个部分可简化如下:
execution(访问权限 方法返回值 方法声明(参数) 异常类型)

AspectJ 定义了专门的表达式用于指定切入点。

切入点表达式要匹配的对象就是目标方法的方法名。所以,execution 表达式中明显就是方法的签名。注意,表达式中黑色文字表示可省略部分,各部分间用空格分开。在其中可以使用以下符号:

在这里插入图片描述

3.2表达式举例:

execution(public * *(..))
指定切入点为:任意公共方法。

execution(* set*(..))
指定切入点为:任何一个以“set”开始的方法。

execution(* com.xyz.service.impl.*.*(..))
指定切入点为:定义在 service 包里的任意类的任意方法。

execution(* com.xyz.service..*.*(..)) * com.xyz.service.power2.aa.*.*(..)
指定切入点为:定义在 service 包或者子包里的任意类的任意方法。“…”出现在类名中时,后面必须跟“*”,表示包、子包下的所有类。
execution(* *..service.*.*(..)) a.b.service.*.*(..) a.b.c.d.service.*.*(..)
指定所有包下的 serivce 子包下所有类(接口)中所有方法为切入点

execution(* *.service.*.*(..))
指定只有一级包下的 serivce 子包下所有类(接口)中所有方法为切入点

4.Aspect中的通知类型

4.1常用四种类型

(1)前置通知@Before
切入点方法执行之前执行的方法@Before

(2)环绕通知@Around

切入点前后都执行 @Around
(3)异常通知@AfterThrowing
切入发点方法执行异常后执行的方法@AfterThrowing:切入点里面的出现异常如10/0,才会执行的方法。
(4)后置通知@After
后置通知,在方法执行之后执行

4.2相关概念

Joinpoint(连接点)
所谓连接点是指那些被拦截到的点,在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的连接点,通俗的说就是被增强类中的所有方法

PointCut(切入点)
所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义,通俗的说就是被增强类中的被增强的方法,因为被增强类中并不是所有的方法都被代理了

Advice(通知/增强)
所谓通知是指拦截到 Joinpoint (被增强的方法)之后所要做的事情就是通知,通俗的说就是对被增强的方法进行增强的代码

4.3相关注解

@Component 将当前类注入到Spring容器内

@Aspect :表明是一个切面类

@Pointcut :切入点,PointCut(切入点)表达式有很多种,其中execution用于使用切面的连接点。

5.spring boot集成AOP

5.1环境准备

在这里插入图片描述

引入AOP相关的依赖

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

在这里插入图片描述
创建controller测试访问

在这里插入图片描述

5.2实例一

使用aop来完成全局请求日志处理
步骤一:创建一个aspect切面类

@Component
@Aspect
public class MyAop {

    //切入点
    //表示public 这个包下的任意方法作为切入点
    @Pointcut("execution(public * com.jierlung.controller.*.*(..))")
    public void log(){
        System.out.println("pointCut签名......");
    }

    //前置通知
    @Before(value = "log()")
    public void deBefore(){
        System.out.println("我是前置通知呀...");
    }


    //返回通知
    @AfterReturning(returning = "ret", pointcut = "log()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求,返回内容
        System.out.println("返回通知:方法的返回值 : " + ret);
    }

    //异常通知
    @AfterThrowing(throwing = "ex", pointcut = "log()")
    public void throwss(JoinPoint jp,Exception ex){
        System.out.println("异常通知:方法异常时执行.....");
        System.out.println("产生异常的方法:"+jp);
        System.out.println("异常种类:"+ex);
    }

    //后置通知
    @After("log()")
    public void after(JoinPoint jp){
        System.out.println("后置通知:最后且一定执行.....");
    }

}

测试访问
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

分析:
第一步:首先通过注解形式定义切面类,把切面类注入容器,交给spring管理

第二步:定义一个方法,加上切入点的注解,指定切哪个包下的类的所有方法,这个作为切入点,该类的方法执行时,例如我访问controller里面的方法时,这个controller就被我作为切入点,该方法执行时,会执行到切入的方法,执行相关业务代码。

第三步:注解方式加上通知,切入点写之前定义的方法,构成一个切面(由切入点和通知组成)。

5.3实例二

@annotation方式

编写一个自定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface MyLogAnnotation {

    //定义一个变量,可以接受参数
    String desc() default " ";
}

在这里插入图片描述
定义一个切面类

@Component
@Aspect
public class MyAopAnnotation {

    @Pointcut(value = "@annotation(com.jierlung.annotation.MyLogAnnotation)")
    //切入点签名
    public void logAnnotation(){
        System.out.println("pointCut签名。。。");
    }

    //前置通知
    @Before("logAnnotation()")
    public void deBefore(JoinPoint jp) throws Throwable {
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容
        System.out.println("URL : " + request.getRequestURL().toString());
    }
    //返回通知
    @AfterReturning(returning = "ret", pointcut = "logAnnotation()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求,返回内容
        System.out.println("返回通知:方法的返回值 : " + ret);
    }

    //异常通知
    @AfterThrowing(throwing = "ex", pointcut = "logAnnotation()")
    public void throwss(JoinPoint jp,Exception ex){
        System.out.println("异常通知:方法异常时执行.....");
        System.out.println("产生异常的方法:"+jp);
        System.out.println("异常种类:"+ex);
    }

    //后置通知
    @After("logAnnotation()")
    public void after(JoinPoint jp){
        System.out.println("后置通知:最后且一定执行.....");
    }


}

在目标方法上加上注解
在这里插入图片描述
测试访问
在这里插入图片描述

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值