4

Spring Boot(8)AOP

 3 years ago
source link: https://guisu.blog.csdn.net/article/details/52641295
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Spring Boot(8)AOP

hguisu 2021-07-04 15:03:01 5

Spring Boot与普通的Spring JavaConfig项目还有有所区别的,如果出现无效的问题,八成是加了多余的配置导致混乱。

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是Spring框架中的一个重要内容,它通过对既有程序定义一个切入点,然后在其前后切入不同的执行内容,比如常见的有:打开数据库连接/关闭数据库连接、打开事务/关闭事务、记录日志等。基于AOP不会破坏原来程序逻辑,因此它可以很好的对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

下面主要讲两个内容,一个是如何在Spring Boot中引入Aop功能,二是如何使用Aop做切面去统一处理Web请求的日志。

Spring Boot开启AOP的方法其实相对简单

1 pom.xml 中引入web模块

在Spring Boot中引入AOP就跟引入其他模块一样,非常简单,只需要在 pom.xml中加入如下依赖:

在完成了引入AOP依赖包后,一般来说并不需要去做其他配置。也许在Spring中使用过注解配置方式的人会问是否需要在程序主类中增加 @EnableAspectJAutoProxy来启用,实际并不需要。

2 . 在application.properties中加入配置

在完成了引入AOP依赖包后,一般来说并不需要去做其他配置。也许在Spring中使用过注解配置方式的人会问是否需要在程序主类中增加 @EnableAspectJAutoProxy来启用,实际并不需要。

可以看下面关于AOP的默认配置属性,其中 spring.aop.auto 属性默认是开启的,也就是说只要引入了AOP依赖后,默认已经增加了 @EnableAspectJAutoProxy

而当我们需要使用CGLIB来实现AOP的时候,需要配置 spring.aop.proxy-target-class=true ,不然默认使用的是标准Java的实现。

3. 实现Web层的日志切面

实现AOP的切面主要有以下几个要素:
使用 @Aspect 注解将一个java类定义为切面类
使用 @Pointcut 定义一个切入点,可以是一个规则表达式,比如下例中某个package下的所有函数,也可以是一个注解等。
根据需要在切入点不同位置的切入内容
使用 @Before 在切入点开始处切入内容
使用 @After 在切入点结尾处切入内容
使用 @AfterReturning 在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
使用 @Around 在切入点前后切入内容,并自己控制何时执行切入点自身的内容
使用 @AfterThrowing 用来处理当切入内容部分抛出异常之后的处理逻辑

Spring 内部方法AOP不生效问题


问题描述, 如下Abc定义为一个Bean, b()方法添加@TargetDatasource,定义切面DynamicDataSourceAspect,期望:调用a()方法,b()方法上的AOP拦截能生效。实际不生效。

AOP代码:

问题分析:

我们都知道Spring aop有两种实现方式,基于Interface生成代理和cglib生成代理。上面的例子中,当调用a()方法时,调用者拿到的是Abc的代理类,即增强类。如果a()方法上有@TargetDatasource注解,拦截会生效。然而,在a()方法里调用b(),b方法上的拦截不会生效。原因是因为a()调用b(), 用的是b()方法的目标类,而不是代理类,所以拦截不生效。

解决方法:

1. 重构代码, 把b()方法移到一个Bean里面。

2. 调整a()方法如下:

@Service

public class Abc {

public void a(){
   ((Abc)AopContext.currentProxy()).b();
}

@TargetDatasource(value=abc)
public void b(){
}
}

Sping 官方解释 - https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#aop 


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK