10、声明式事务
admin
2023-08-15 20:42:07
0

一、基础回顾 1、导入相关的依赖

org.springframework spring-jdbc 4.3.0.RELEASE c3p0 c3p0 0.9.1.2 mysql mysql-connector-java 5.1.44

2、进行相关的配置操作
  • 配置数据源
  • JdbcTemplate操作数据
  • @EnableTransactionManagement 开启基于注解的事务管理功能
  • 配置事务管理器来控制事务
@EnableTransactionManagement @ComponentScan("com.qiu.tx") @Configuration public class TxConfig {//数据源 @Bean public DataSource dataSource() throws Exception{ ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser("root"); dataSource.setPassword("123456"); dataSource.setDriverClass("com.mysql.jdbc.Driver"); 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 transactionManager() throws Exception{ return new DataSourceTransactionManager(dataSource()); }}

3、给方法上标注 @Transactional 表示当前方法是一个事务方法
  • UserDao
@Repository public class UserDao {@Autowired private JdbcTemplate jdbcTemplate; public void insert(){ String sql = "INSERT INTO `tbl_user`(username,age) VALUES(?,?)"; String username = UUID.randomUUID().toString().substring(0, 5); jdbcTemplate.update(sql, username,19); }}

  • UserService
@Service public class UserService { @Autowired private UserDao userDao; @Transactional public void insertUser(){ userDao.insert(); //otherDao.other(); xxx System.out.println("插入完成..."); //失败则回滚否则成功插入数据库 int i = 10/0; } }

二、原理
  • 前面知道了@EnableXXX注解主要作用是导入相应的功能类,因此从这个注解入手
1、@EnableTransactionManagement
//开始spring事物管理 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented //给容器导入TransactionManagementConfigurationSelector @Import(TransactionManagementConfigurationSelector.class) public @interface EnableTransactionManagement { //默认java的jdk代理方式 boolean proxyTargetClass() default false; //默认事物以代理方式进行 AdviceMode mode() default AdviceMode.PROXY; int order() default Ordered.LOWEST_PRECEDENCE; }

2、TransactionManagementConfigurationSelector类
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector { @Override protected String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { case PROXY: //默认导入AutoProxyRegistrar和ProxyTransactionManagementConfiguration两个组件 return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: //如果是ASPECTJ则导入其他 return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME}; default: return null; } }}

2.1AutoProxyRegistrar
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {private final Log logger = LogFactory.getLog(getClass()); //根据给定的注解注册相应的bean @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean candidateFound = false; Set annoTypes = importingClassMetadata.getAnnotationTypes(); for (String annoType : annoTypes) { AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType); Object mode = candidate.get("mode"); Object proxyTargetClass = candidate.get("proxyTargetClass"); if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) { candidateFound = true; if (mode == AdviceMode.PROXY) { //给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 后置处理器组件 //InfrastructureAdvisorAutoProxyCreator 利用后置处理器机制在对象创建以后,包装对象, //返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用; AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry); if ((Boolean) proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); return; } } } } if (!candidateFound) { String name = getClass().getSimpleName(); logger.warn(String.format("%s was imported but no annotations were found " + "having both 'mode' and 'proxyTargetClass' attributes of type " + "AdviceMode and boolean respectively. This means that auto proxy " + "creator registration and configuration may not have occured as " + "intended, and components may not be proxied as expected. Check to " + "ensure that %s has been @Import'ed on the same class where these " + "annotations are declared; otherwise remove the import of %s " + "altogether.", name, name, name)); } }}

2.2ProxyTransactionManagementConfiguration
  • 是一个配置类,主要给容器中注册事务增强器
@Configuration public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { //1、事务增强器要用事务注解的信息, @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); advisor.setTransactionAttributeSource(transactionAttributeSource()); advisor.setAdvice(transactionInterceptor()); advisor.setOrder(this.enableTx.getNumber("order")); return advisor; } //2.利用AnnotationTransactionAttributeSource解析事务注解 @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionAttributeSource transactionAttributeSource() { return new AnnotationTransactionAttributeSource(); } //3.事务拦截器保存了事务属性信息,事务管理器等信息 @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionInterceptor transactionInterceptor() { TransactionInterceptor interceptor = new TransactionInterceptor(); interceptor.setTransactionAttributeSource(transactionAttributeSource()); if (this.txManager != null) { interceptor.setTransactionManager(this.txManager); } return interceptor; } }

  • 事务拦截器工作原理
【10、声明式事务】1、在目标方法执行的时候,执行拦截器链,对事物进行拦截
2、先获取事务相关的属性
3、再获取PlatformTransactionManager,如果事先没有添加指定任何transactionmanger,最终会从容器中按照类型获取一个PlatformTransactionManager;
4、执行目标方法。如果异常,获取到事务管理器,利用事务管理回滚操作,如果正常,利用事务管理器,提交事务。

相关内容

热门资讯

a... 本文目录导航: abaqus振动照应剖析中处罚力的加载方法 abaqus反...
a... 本文目录导航: abaqus资料可以不设置参数吗 abaqus外面没有自带...
A... 本文目录导航: ANSYS Workbench中二维平面剖析的设置。 an...
h... 本文目录导航: hfss19.2允许win11吗 微带如何假负载 ...
a... 本文目录导航: ansys模流剖析用哪个模块 Ansys_workbenc...
v... 本文目录导航: 在ansys中,建好几何模型后,随意变动一下视图,旋转、加大、增加,Fit...
A... 本文目录导航: Ansys软件可以收费试用吗? ansys有哪些软件 ...
a... 本文目录导航: abaqus中如何同时关上两个cae文件? abaqus找...
a... 本文目录导航: ansys流体剖析迭代次数可以中止嘛 Ansys Flot...
这... 本文目录导航: 哪位大佬有 Fluent14.5流场剖析从入门到知晓,这种百度网盘资源的链...
经... 双击D2进入System Coupling的设置,在Solution上右击选用Clear Gener...
a... 本文目录导航: ansys软件引见 ansys有哪些软件 ...
a... 本文目录导航: abaqus系列技巧18:聊聊abaqus云图外面的魔术加大镜--缩放倍数...
a... 本文目录导航: abaqus中网格不可绘制 abaqus结果可视化某个部件...
a... 本文目录导航: abaqus结果可视化某个部件云图只显示网格接壤处的? a...
驳... 本文目录导航: ABAQUS中假设选择施加的载荷类型为pressure,对应的载荷单位应该...
a... 本文目录导航: abaqus2020旋转不了物体 怎样判别abaqus转的...
在... 本文目录导航: 在abaqus中如何删除一个单元 ABAQUS怎样删除网格...
它... 本文目录导航: abaqus为什么叫abaqus,它是那些词的简称么?全称是什么呢? ...
披着“现货订购”外衣的非法期货...   近期,甘肃西北商品交易市场有限公司旗下的“铂银掘金APP”引发大量投资者集中维权。该平台打着“低...