中国住房和城乡建设网网站,哪里可以申请免费域名,制作网页链接,多用户商城购物系统EnableTransactionManagement工作原理
开启Spring事务本质上就是增加了一个Advisor#xff0c;在使用EnableTransactionManagement注解来开启Spring事务时#xff0c;该注解代理的功能就是向Spring容器中添加了两个Bean
Import(TransactionManagementConfigurationSelector…EnableTransactionManagement工作原理
开启Spring事务本质上就是增加了一个Advisor在使用EnableTransactionManagement注解来开启Spring事务时该注解代理的功能就是向Spring容器中添加了两个Bean
Import(TransactionManagementConfigurationSelector.class)
public interface EnableTransactionManagement { ... }/*** Selects which implementation of {link AbstractTransactionManagementConfiguration}* should be used based on the value of {link EnableTransactionManagement#mode} on the* importing {code Configuration} class.** author Chris Beams* author Juergen Hoeller* since 3.1* see EnableTransactionManagement* see ProxyTransactionManagementConfiguration* see TransactionManagementConfigUtils#TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME* see TransactionManagementConfigUtils#JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME*/
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelectorEnableTransactionManagement {/*** Returns {link ProxyTransactionManagementConfiguration} or* {code AspectJ(Jta)TransactionManagementConfiguration} for {code PROXY}* and {code ASPECTJ} values of {link EnableTransactionManagement#mode()},* respectively.*/Overrideprotected String[] selectImports(AdviceMode adviceMode) {switch (adviceMode) {case PROXY:// 默认是PROXYreturn new String[] {AutoProxyRegistrar.class.getName(),ProxyTransactionManagementConfiguration.class.getName()};case ASPECTJ:// 表示不用动态代理技术用ASPECTJ技术一般用不到return new String[] {determineTransactionAspectClass()};default:return null;}}private String determineTransactionAspectClass() {return (ClassUtils.isPresent(javax.transaction.Transactional, getClass().getClassLoader()) ?TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);}}
1、AutoProxyRegistrar
向Spring容器中注册了一个InfrastructureAdvisorAutoProxyCreator的Bean
InfrastructureAdvisorAutoProxyCreator 继承了AbstractAdvisorAutoProxyCreator
主要作用开启自动代理
在初始化后寻找Advisor类型的Bean并检查当前Bean是否有匹配的Advisor是否需要动态代理创建代理对象
/*** Registers an auto proxy creator against the current {link BeanDefinitionRegistry}* as appropriate based on an {code Enable*} annotation having {code mode} and* {code proxyTargetClass} attributes set to the correct values.** author Chris Beams* since 3.1* see org.springframework.cache.annotation.EnableCaching* see org.springframework.transaction.annotation.EnableTransactionManagement*/
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {private final Log logger LogFactory.getLog(getClass());/*** Register, escalate, and configure the standard auto proxy creator (APC) against the* given registry. Works by finding the nearest annotation declared on the importing* {code Configuration} class that has both {code mode} and {code proxyTargetClass}* attributes. If {code mode} is set to {code PROXY}, the APC is registered; if* {code proxyTargetClass} is set to {code true}, then the APC is forced to use* subclass (CGLIB) proxying.* pSeveral {code Enable*} annotations expose both {code mode} and* {code proxyTargetClass} attributes. It is important to note that most of these* capabilities end up sharing a {linkplain AopConfigUtils#AUTO_PROXY_CREATOR_BEAN_NAME* single APC}. For this reason, this implementation doesnt care exactly which* annotation it finds -- as long as it exposes the right {code mode} and* {code proxyTargetClass} attributes, the APC can be registered and configured all* the same.*/Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {boolean candidateFound false;SetString annTypes importingClassMetadata.getAnnotationTypes();for (String annType : annTypes) {AnnotationAttributes candidate AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);if (candidate null) {continue;}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才可以Bean进行AOPAopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);if ((Boolean) proxyTargetClass) {// 设置InfrastructureAdvisorAutoProxyCreator的proxyTargetClass为trueAopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);return;}}}}if (!candidateFound logger.isInfoEnabled()) {String name getClass().getSimpleName();logger.info(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 occurred as intended, and components may not be proxied as expected. Check to ensure that %s has been Imported on the same class where these annotations are declared; otherwise remove the import of %s altogether., name, name, name));}}}// AopConfigUtils#registerAutoProxyCreatorIfNecessary
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {return registerAutoProxyCreatorIfNecessary(registry, null);
}// AopConfigUtils#registerAutoProxyCreatorIfNecessary
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Nullable Object source) {return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}// AopConfigUtils#forceAutoProxyCreatorToUseClassProxying
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {// AUTO_PROXY_CREATOR_BEAN_NAME org.springframework.aop.config.internalAutoProxyCreatorif (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {BeanDefinition definition registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);definition.getPropertyValues().add(proxyTargetClass, Boolean.TRUE);}
}
2、ProxyTransactionManagementConfiguration
是一个配置类内部定义了三个Bean BeanFactoryTransactionAttributeSourceAdvisor一个Advisor AnnotationTransactionAttributeSource相当于BeanFactoryTransactionAttributeSourceAdvisor中的Pointcut判断某个类或者方法上面是否存在Transactional注解注意这里并没有解析 TransactionInterceptor相当于BeanFactoryTransactionAttributeSourceAdvisor中的 Advice当某个类中存在Transactional注解就会产生一个代理对象作为Bean在执行代理对象的某个方法时会进入到TransactionInterceptor的invoke()方法中
invoke()方法里面就会创建数据库连接、关闭自动提交、事务提交和回滚等
/*** {code Configuration} class that registers the Spring infrastructure beans* necessary to enable proxy-based annotation-driven transaction management.** author Chris Beams* author Sebastien Deleuze* since 3.1* see EnableTransactionManagement* see TransactionManagementConfigurationSelector*/
Configuration(proxyBeanMethods false)
Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {Bean(name TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)Role(BeanDefinition.ROLE_INFRASTRUCTURE)public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {BeanFactoryTransactionAttributeSourceAdvisor advisor new BeanFactoryTransactionAttributeSourceAdvisor();advisor.setTransactionAttributeSource(transactionAttributeSource);advisor.setAdvice(transactionInterceptor);if (this.enableTx ! null) {advisor.setOrder(this.enableTx.IntegergetNumber(order));}return advisor;}BeanRole(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionAttributeSource transactionAttributeSource() {// AnnotationTransactionAttributeSource中定义了一个Pointcut// 并且AnnotationTransactionAttributeSource可以用来解析Transactional注解并得到一个RuleBasedTransactionAttribute对象return new AnnotationTransactionAttributeSource();}BeanRole(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {TransactionInterceptor interceptor new TransactionInterceptor();interceptor.setTransactionAttributeSource(transactionAttributeSource);if (this.txManager ! null) {interceptor.setTransactionManager(this.txManager);}return interceptor;}} Spring事务基本执行原理
InfrastructureAdvisorAutoProxyCreator也是一个BeanPostProcessor最终实现SmartInstantiationAwareBeanPostProcessor在Bean的生命周期初始化后步骤时会去判断是否需要创建代理对象
判断依据当前Bean和BeanFactoryTransactionAttributeSourceAdvisor匹配简单点就是当前Bean的类或者方法上面有没有Transactional注解有就匹配
在代理对象执行某个方法时会再次判断当前执行方法和BeanFactoryTransactionAttributeSourceAdvisor是否匹配如果匹配则执行该Advisor中的TransactionInterceptor的invoke()方法执行流程
再次判断是考虑到一个类中可能有多个方法有的方法有Transactional注解有的没有
1、利用所配置的PlatformTransactionManager事务管理器新建一个数据库连接注意TransactionManager有限制的必须是PlatformTransactionManager然后会生成一个joinpointIdentification作为事务的名字
2、修改数据库连接的autocommit为false
3、执行MethodInvocation.proceed()方法简单理解就是执行业务方法其中就会执行sql
4、如果没有抛异常则提交执行完finally中的方法后再进行提交
5、如果抛了异常则回滚执行完finally中的方法后再抛出异常 Spring事务传播机制
开发过程中经常会出现一个方法调用另外一个方法那么就涉及到了多种场景。比如多个方法需要在同一个事务中执行每个方法要在单独的事务中执行有的方法需要事务有的不需要事务还有很多更复杂情况。Spring为了支持各种场景也就有了Spring事务传播机制
场景分析假设a()方法在事务执行中调用b()方法需要开启一个新事务执行
1、首先代理对象执行a()方法前先利用事务管理器新建一个数据库连接a
2、将数据库连接a的autocommit改为false
3、把数据库连接a设置到ThreadLocal中
4、执行a()方法中的sql
5、执行a()方法过程中调用了b()方法注意用代理对象调用b()方法
a代理对象执行b()方法前判断出来了当前线程中已经存在一个数据库连接a了表示当前线程其实已经拥有一个Spring事务了则进行挂起
b挂起就是把ThreadLocal中的数据库连接a从ThreadLocal中移除并放入一个挂起资源对象中就是事务同步管理器TransactionSynchronizationManager
c挂起完成后再次利用事务管理器新建一个数据库连接b
d将数据库连接b的autocommit改为false
e把数据库连接b设置到ThreadLocal中
f执行b()方法中的sql
gb()方法正常执行完则从ThreadLocal中拿到数据库连接b进行提交
h提交之后会恢复所挂起的数据库连接a这里的恢复其实只是把在挂起资源对象中所保存的数据库连接a再次设置到ThreadLocal中
6、a()方法正常执行完则从ThreadLocal中拿到数据库连接a进行提交
过程核心在执行某个方法时判断当前是否已经存在一个事务就是判断当前线程的ThreadLocal中是否存在一个数据库连接对象如果存在则表示已经存在一个事务了。