- 封装 around 方法 注意参数:ProceedingJoinPoint point
@Component
public class TransciationUtil {
@Autowired
private ConnectionHolder connectionHolder;
public void start() throws SQLException {
connectionHolder.getConnection().setAutoCommit(false);
}
public void commit() throws SQLException {
connectionHolder.getConnection().commit();
}
public void rollback() {
try {
connectionHolder.getConnection().rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void close(){
try {
connectionHolder.getConnection().close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//参数ProceedingJoinPoint: 代表调用对象方法本身
// point.proceed()方法代表执行原本代理方法, 可以在此方法前后进行自己需要的操作
public void around(ProceedingJoinPoint point){
try {
start();
point.proceed();
commit();
} catch (Throwable throwable) {
rollback();
throwable.printStackTrace();
}finally {
close();
}
}
}
- 配置 pom.xml 文件: 导入 spring-aop 包和 aspecj 切面编程的三方包
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<!--
逻辑织入功能模块
第三方提供了
-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
- 配置全局配置文件:
<aop:config>
// ref 指向配置织入方法的文件
<aop:aspect id="t" ref="transciationUtil">
// aop:around 配置文件中织入的方法名, 以及切入点execution(* com.lily.service..*.*(..))"
<aop:around method="around" pointcut="execution(* com.lily.service..*.*(..))" />
</aop:aspect>
</aop:config>
execution(* com.lily.service...(..)) 通配符: (..)代表任何一个方法
- AccountServiceImpl
@Component("accountService")
public class AccountServiceImpl implements AccountService {
@Resource
private AccountDao accountDao;
@Override
public void transfer(String fromUser, String toUser, double money) {
accountDao.update(fromUser, -money);
int i = 4/0;
accountDao.update(toUser, money);
}
}
- 测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class MyTest01 {
@Autowired
private AccountService accountService;
@Test
public void testTransfer2(){
accountService.transfer("小明","小李",100);
}
}
数据库金额未发生非同步变化
`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
使用注解开发时:
注解配置文件需要配置: @EnableAspectJAutoProxy
//开启使用切面编程
提供直接的切面类 @Aspect
方法: @Around("xx")
xx为切入点, 例如:execution(* com.lily.service...(..))"
@Component
@Aspect
public class TransciationUtil {
@Around("execution(* com.lily.service..*.*(..))")
public void around(ProceedingJoinPoint point){
try {
start();
point.proceed();
commit();
} catch (Throwable throwable) {
rollback();
throwable.printStackTrace();
}finally {
close();
}
}
}