声明式事务:
环境搭建:
1、导入相关依赖
数据源、数据库驱动、Spring-jdbc模块
2、配置数据源、JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据
3、给方法上标注@Transactional标识当前方法是一个事务方法;
4、@EnableTransactionManagement 开启基于注解的事务管理功能;
5、配置事务管理器来控制事务;
@Bean
public PlatformTransactionManager platformTransactionManager()
原理:
1、@EnableTransactionManagement
利用TransactionManagementConfigurationSelector给容器中导入组件
导入两个组件
AutoProxyRegistrar
ProxyTransactionManagementConfiguration
2、AutoProxyRegistrar:
给容器中注册一个InfrastructureAdvisorAutoProxyCreator 组件;
InfrastructureAdvisorAutoProxyCreator:?
利用后置处理器记住在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;
3、ProxyTransactionManagementConfiguration 做了什么?
3.1 给容器中注册事务增强器
3.1.1 事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事物
3.1.2 事务拦截器:
TransactionInterceptor:保存了事务属性信息,事务管理器;
它是一个MethodInterceptor;
在目标方法执行的时候;
执行拦截器链;
事务拦截器:
a) 先获取事务相关的属性
b) 再获取PlatformTransactionManager,如果实现没有添加指定任何TransactionManager
最终会从容器中按照类型获取一个PlatformTransactionManager
c) 执行目标方法
如果异常,获取到事务管理器,利用事务管理器回滚操作;
如果正常,利用事务管理器,提交事务
package com.spring.tx;
import java.beans.PropertyVetoException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.StringValueResolver;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
* 声明式事务:
*
* 环境搭建:
* 1、导入相关依赖
* 数据源、数据库驱动、Spring-jdbc模块
* 2、配置数据源、JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据
* 3、给方法上标注@Transactional标识当前方法是一个事务方法;
* 4、@EnableTransactionManagement 开启基于注解的事务管理功能;
* 5、配置事务管理器来控制事务;
* @Bean
* public PlatformTransactionManager platformTransactionManager()
*
* 原理:
* 1、@EnableTransactionManagement
* 利用TransactionManagementConfigurationSelector给容器中导入组件
* 导入两个组件
* AutoProxyRegistrar
* ProxyTransactionManagementConfiguration
* 2、AutoProxyRegistrar:
* 给容器中注册一个InfrastructureAdvisorAutoProxyCreator 组件;
* InfrastructureAdvisorAutoProxyCreator:?
* 利用后置处理器记住在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;
*
* 3、ProxyTransactionManagementConfiguration 做了什么?
* 3.1 给容器中注册事务增强器
* 3.1.1 事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事物
* 3.1.2 事务拦截器:
* TransactionInterceptor:保存了事务属性信息,事务管理器;
* 它是一个MethodInterceptor;
* 在目标方法执行的时候;
* 执行拦截器链;
* 事务拦截器:
* a) 先获取事务相关的属性
* b) 再获取PlatformTransactionManager,如果实现没有添加指定任何TransactionManager
* 最终会从容器中按照类型获取一个PlatformTransactionManager
* c) 执行目标方法
* 如果异常,获取到事务管理器,利用事务管理器回滚操作;
* 如果正常,利用事务管理器,提交事务
*/
@EnableTransactionManagement
@ComponentScan("com.spring.tx")
@PropertySource("classpath:/dbconfig.properties")
@Configuration
public class TxConfig implements EmbeddedValueResolverAware{
@Value("${db.user}")
private String user;
@Value("${db.password}")
private String password;
private String driverClass;
@Bean
public DataSource dataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setDriverClass(driverClass);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate() throws Exception {
//Spring 对@configuration类会特殊处理;给容器中加组件的方法,多次调用都只是从容器中找组件
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource()) ;
return jdbcTemplate;
}
//在容器中注册事务管理器
@Bean
public PlatformTransactionManager platformTransactionManager() throws Exception {
PlatformTransactionManager manager = new DataSourceTransactionManager(dataSource());
return manager;
}
public void setEmbeddedValueResolver(StringValueResolver resolver) {
String driverClass = resolver.resolveStringValue("${db.driverClass}");
this.driverClass = driverClass;
}
}
package com.spring.tx;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void insert() {
String sql = "insert into user(name,age) values(?,?)";
String username = UUID.randomUUID().toString().substring(0, 5);
jdbcTemplate.update(sql,username,20);
}
}
package com.spring.tx;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Autowired
private UserDao dao ;
@Transactional
public void insert() {
dao.insert();
System.out.println(">>>>>>>>>>>插入完成<<<<<<<<<<<");
System.out.println(10/0);
}
}
package com.spring.test;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.spring.tx.TxConfig;
import com.spring.tx.UserService;
public class IOCTestOfTx {
@Test
public void test() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TxConfig.class);
UserService userService = applicationContext.getBean(UserService.class);
userService.insert();
applicationContext.close();
}
}
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">