朱晔和你聊Spring系列S1E6:容易犯错的Spring AOP (3)

程序启动的时候记录数为1,第一次调用insertData方法后记录数为2,第二次调用方法如果事务生效方法会回滚记录数会维持在2,在输出中我们看到记录数最后是3。

那么,如何解决这个问题呢,有三种方式:

使用AspjectJ来实现AOP,这种方式是直接修改代码的,不是走代理实现的,不会有这个问题,下面我们会详细说明一下这个过程。

在代码中使用AopContext.currentProxy()来获得当前的代理进行_insertData方法调用。这种方式侵入太强,而且需要被代理类意识到自己是通过代理被访问,显然不是合适的方式。

改造代码,使需要事务代理的方法直接调用,类似:

@Override @Transactional(rollbackFor = Exception.class) public void insertData(boolean success) { dbMapper.personInsertWithoutId(); if(!success) dbMapper.personInsertWithId(); }

这里还容易犯错的地方是,这里不能对异常进行捕获,否则Spring事务代理无法捕获到异常也就无法实现回滚。

使用AspectJ静态织入进行改造

那么原来这段代码如何不改造实现事务呢?可以通过AspjectJ编译时静态织入实现。整个配置过程如下:
首先在pom中加入下面的配置:

<build> <sourceDirectory>${project.build.directory}/generated-sources/delombok</sourceDirectory> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.projectlombok</groupId> <artifactId>lombok-maven-plugin</artifactId> <version>1.18.0.0</version> <executions> <execution> <phase>generate-sources</phase> <goals> <goal>delombok</goal> </goals> </execution> </executions> <configuration> <addOutputDirectory>false</addOutputDirectory> <sourceDirectory>src/main/java</sourceDirectory> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.10</version> <configuration> <complianceLevel>1.8</complianceLevel> <source>1.8</source> <aspectLibraries> <aspectLibrary> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </aspectLibrary> </aspectLibraries> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>test-compile</goal> </goals> </execution> </executions> </plugin> </plugins> </build>

这里的一个坑是ajc编译器无法支持lambok,我们需要先使用lombok的插件在生成源码阶段对lombok代码进行预处理,然后我们再通过aspjectj插件来编译代码。Pom文件中还需要加入如下依赖:

<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </dependency>

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzfgzw.html