spring 事务管理 使用AOP切面 优化代码
在service实现类的代码
public void transfer(String outName, String inName, Integer money) {
//开启事务
PlatformTransactionManager ptm = new DataSourceTransactionManager(dataSource);
//事务定义
DefaultTransactionDefinition td = new DefaultTransactionDefinition();
//事务状态
TransactionStatus ts = ptm.getTransaction(td);
//调用dao层转入资金方法
accountDao.inMoney(outName,money);
//调用daoceng转出资金方法
accountDao.outMoney(inName,money);
//提交事务
ptm.commit(ts);
}
开启事务、事务定义、事务状态、提交事务
这四段代码都会在其它需要开启事务的实体类中
写出来,这就会重复写这段代码,
这就可以利用AOP切面技术将这四段代码做横向抽取。
使用AOP 先的在pom文件里写出 AOP的坐标
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
然后新建一个专门用于写aop通知类的包
用aop横向抽取出来的代码是要放在通知类里进行操作的
public class TxAdvice {
//注入数据源对象
private DataSource dataSource;
public void setDataSource(DataSource dataSource){
this.dataSource = dataSource;
}
public Object transactionManager(ProceedingJoinPoint pjp) throws Throwable {
//开启事务
PlatformTransactionManager ptm = new DataSourceTransactionManager(dataSource);
//事务定义
DefaultTransactionDefinition td = new DefaultTransactionDefinition();
//事务状态
TransactionStatus ts = ptm.getTransaction(td);
Object ret = pjp.proceed(pjp.getArgs());
//提交事务
ptm.commit(ts);
return ret;
}
}
将这些 操作事务的代码横向抽取到AOP的通知类中,
只抽取共性的代码,操作数据的代码不抽取,
这里的 dataSource 就要在这个通知类中声明
原先在service实现类的dataSource声明就不用了
在通知类中 在方法参数里传入 ProceedingJoinPoint 的对象
这个才是真正用来实现 AOP 功能的
Object ret = pjp.proceed(pjp.getArgs());
用这个方法写到提交事务代码的上一行,是做环绕通知的。
这个方法设置了返回值,这就的获取环绕通知的返回值,
在提交事务代码的将 获取环绕通知的返回值 return
pjp.getArgs()这个参数是防止之后在 ProceedingJoinPoint 底层的参数发生变化写出来的获取ProceedingJoinPoint对象的参数。
接下来在spring配置文件里去将AOP通知类注配上
这才是将通知类注入到spring配置文件里的
记得将dataSource 资源对象 也注入到通知类配置中
因为 现在已经将它抽取到通知类里了
原来在service实现类的dataSource 配置,就得删除了
<bean id="txAdvice" class="com.itheima.aop.TxAdvice">
<property name="dataSource" ref="dataSource"/>
</bean>
使用AOP 要在配置文件约束里写上AOP的名称空间
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd"
这是对aop的配置,要先在XML文件头里写出aop的空间名称
再去配置AOP
<aop:config>
<aop:pointcut id="pt" expression="execution(* *..transfer(..))"/>
<aop:aspect ref="txAdvice">
<aop:around method="transactionManager" pointcut-ref="pt"/>
</aop:aspect>
</aop:config>
aop:pointcut这是在配置切入点
expression="execution(* *…transfer(…)) 这是在配置切入点的方法
aop:aspect这是在配置通知
ref=“txAdvice” 这是在将注入到配置文件的AOP通知类传到AOP的配置中,然后
aop:around 是在指定这个通知的类型。method=“transactionManager” 指定使用通知类中那个方法做 环境通知
pointcut-ref=“pt” 这是在指定切入点在哪里
pt 是上面aop配置中 配置切入点的 id 表名切入点就是这个切入方法
这样 通过主方法 运行后
去数据库刷新对应的数据表查看 有没有变化