1. 什么是声明式事务控制
- Spring 的声明式事务顾名思义就是采用声明的方式来处理事务。这里所说的声明,就是指在配置文件中声明,用在 Spring 配置文件中声明式的处理事务来代替代码式的处理事务。
- 声明式事务处理的作用
- 事务管理不侵入开发的组件。具体来说,业务逻辑对象就不会意识到正在事务管理之中,事实上也应该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策划的话,也只需要在定义文件中重新配置即可
- 在不需要事务管理的时候,只要在设定文件上修改一下,即可移去事务管理服务,无需改变代码重新编译,这样维护起来极其方便
- 注意:Spring 声明式事务控制底层就是AOP。
2. 声明式事务控制的实现
-
声明式事务控制明确事项:
谁是切点?
谁是通知?
配置切面?
- 案例演示:转账的形式
public class Account {
private String name;
private double money;
}
public interface AccountDao {
public void out(String outMan,double money);
public void in(String inMan,double money);
}
public class AccountDaoImpl implements AccountDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void out(String outMan, double money) {
jdbcTemplate.update("update account set money=money-? where name=?",money,outMan);
}
public void in(String inMan, double money) {
jdbcTemplate.update("update account set money=money+? where name=?",money,inMan);
}
}
public interface AccountService {
public void transfer(String outMan,String inMan,double money);
}
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void transfer(String outMan, String inMan, double money) {
accountDao.out(outMan,money);
// int i = 1/0;
accountDao.in(inMan,money);
}
}
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="accountDao" class="com.xdr630.dao.impl.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<bean id="accountService" class="com.xdr630.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
-
在account表中,两者的钱都是500
- 测试:tom 转账 50 给 lucy
public class AccountController {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService accountService = app.getBean(AccountService.class);
accountService.transfer("tom", "lucy", 50);
}
}
-
如果在转账的时候程序出现异常,不加事物控制的情况如下:
-
此时就会发现,账号少了50不知道去哪了
- 这种情况就需要引入事物管理了
-
引入
tx
命名空间 - 配置事务增强
<!--配置平台管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--通知 事物增强器-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--设置事物属性的信息-->
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
- 配置事务 AOP 织入
<!--配置事物aop的织入-->
<aop:config>
<aop:pointcut id="myPointcut" expression="execution(* com.xdr630.service.impl.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut"></aop:advisor>
</aop:config>
- 测试事务控制转账业务代码
- 可以看到,代码异常后,事物要么成功,要么失败
3. 切点方法的事务参数的配置
- 其中,
<tx:method>
代表切点方法的事务参数的配置,例如:
<tx:method name="transfer" isolation="REPEATABLE_READ"
propagation="REQUIRED" timeout="-1" read-only="false"/>
name:切点方法名称
isolation:事务的隔离级别
propogation:事务的传播行为
timeout:超时时间
read-only:是否只读
4. 知识要点
- 声明式事务控制的配置要点
平台事务管理器配置
事务通知的配置
事务aop织入的配置