摘要:使用注解方式簡單模擬事務(wù)樣例說明數(shù)據(jù)源采用采用持久化采用事務(wù)注解環(huán)境搭建依賴提供的模塊鏈接驅(qū)動包配置類聲明式事務(wù)配置類,其中一定要開啟。
使用注解方式簡單模擬事務(wù)樣例 說明
數(shù)據(jù)源采用c3p0
采用JdbcTemplate持久化
采用Spring事務(wù)注解
環(huán)境搭建 POM依賴配置類c3p0 c3p0 0.9.1.2 org.springframework spring-jdbc 4.3.12.RELEASE mysql mysql-connector-java 5.1.44 runtime org.springframework spring-aspects 4.3.12.RELEASE
/** * description:聲明式事務(wù)配置類,其中@EnableTransactionManagement * 一定要開啟。 * @author 70KG */ @Configuration @ComponentScan("com.nmys.story.springCore.springaop.tx_sample") @EnableTransactionManagement // -- 開啟基于注解的事務(wù)管理 public class TxConfig { // -- 配置數(shù)據(jù)源 @Bean public DataSource dataSource() throws Exception { ComboPooledDataSource pool = new ComboPooledDataSource(); pool.setUser("root"); pool.setPassword("root"); pool.setDriverClass("com.mysql.jdbc.Driver"); pool.setJdbcUrl("jdbc:mysql://localhost:3306/usthe?useSSL=false"); return pool; } // -- 加入模板 @Bean public JdbcTemplate jdbcTemplate() throws Exception { JdbcTemplate template = new JdbcTemplate(dataSource()); return template; } // -- 配置事務(wù)管理器,它才是用來提交回滾事務(wù)的主導(dǎo)者 @Bean public DataSourceTransactionManager txManager() throws Exception { DataSourceTransactionManager tx = new DataSourceTransactionManager(dataSource()); return tx; } }業(yè)務(wù)類
/** * description * @author 70KG */ @Service public class TxService { @Autowired private TxDao txDao; public void insertLog(){ txDao.insertSth(); } }
/** * description * @author 70KG */ @Repository public class TxDao { @Autowired private JdbcTemplate jdbcTemplate; // @Transactional僅表明它是一個事務(wù)方法,開啟事務(wù)僅有注解是不夠的,還需要配置事務(wù)管理器 @Transactional public void insertSth() { String sql = "INSERT into sys_log (username) VALUES(?);"; jdbcTemplate.update(sql, "lisi"); System.out.println("------>插入成功"); int i = 10/0; } }測試類
/** * description * @author 70KG */ public class Test01 { public static void main(String[] args) { AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(TxConfig.class); TxService bean = app.getBean(TxService.class); bean.insertLog(); } }測試結(jié)果
測試結(jié)果肯定是能正常運(yùn)行的,下面試著跟一下源碼。
源碼分析當(dāng)容器開始啟動運(yùn)行的時(shí)候就會找到@EnableTransactionManagement注解
進(jìn)入注解,發(fā)現(xiàn)它使用@Import(TransactionManagementConfigurationSelector.class)向容器中注入了這個類
跟進(jìn)TransactionManagementConfigurationSelector,發(fā)現(xiàn)它最終實(shí)現(xiàn)的是ImportSelector接口,這個接口可以向IOC容器中以Bean的全類名的方式注入Bean。
源碼如下,AdviceMode在注解@EnableTransactionManagement默認(rèn)就是PROXY,可見它向容器中注入了兩個類,分別是AutoProxyRegistrar和ProxyTransactionManagementConfiguration。
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelectorAutoProxyRegistrar{ @Override protected String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { case PROXY: return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME}; default: return null; } } }
AutoProxyRegistrar翻譯過來:自動代理注冊器。進(jìn)入AutoProxyRegistrar類,截取部分源碼,如下:
@Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean candidateFound = false; SetannoTypes = importingClassMetadata.getAnnotationTypes(); for (String annoType : annoTypes) { AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType); 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) { // -- 前面的代碼主要是獲取注解類型,注解信息等等。 // -- 主要是這個地方,如果必要的話,就向容器中注冊一個自動代理創(chuàng)建器。 AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry); if ((Boolean) proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); return; } } } } ...........
進(jìn)入registerAutoProxyCreatorIfNecessary(registry),AopConfigUtils類中,源碼如下:
@Nullable private static BeanDefinition registerOrEscalateApcAsRequired(Class> cls, BeanDefinitionRegistry registry, @Nullable Object source) { // -- 斷言 Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); // 先判斷有沒有org.springframework.aop.config.internalAutoProxyCreator // 首次進(jìn)來,肯定沒有 if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); if (!cls.getName().equals(apcDefinition.getBeanClassName())) { int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } return null; } // -- 將cls也就是InfrastructureAdvisorAutoProxyCreator包裝成RootBeanDefinition RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); // -- 將beanDefinition注冊到IOC容器中,Bean的 // -- 名字就叫org.springframework.aop.config.internalAutoProxyCreator registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; }
向容器中注入了InfrastructureAdvisorAutoProxyCreator,進(jìn)入此類,發(fā)現(xiàn)父類是AbstractAdvisorAutoProxyCreator,AbstractAdvisorAutoProxyCreator的父類是AbstractAutoProxyCreator,AbstractAutoProxyCreator中的方法,創(chuàng)建并返回了代理類,如下:
/** * Create a proxy with the configured interceptors if the bean is * identified as one to proxy by the subclass. * @see #getAdvicesAndAdvisorsForBean */ @Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
給容器中注入InfrastructureAdvisorAutoProxyCreator的主要作用就是,利用后置處理器機(jī)制在對象創(chuàng)建以后,對對象進(jìn)行包裝,返回一個代理對象(增強(qiáng)器),代理對象執(zhí)行方法,利用攔截器鏈進(jìn)行調(diào)用。
ProxyTransactionManagementConfiguration進(jìn)入ProxyTransactionManagementConfiguration,部分源碼如下:
// -- 向容器中注入名字為TRANSACTION_ADVISOR_BEAN_NAME的切面 @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); // -- 向切面中注入注解解析器,專門來解析事務(wù)注解的 advisor.setTransactionAttributeSource(transactionAttributeSource()); // -- 向切面中注入事務(wù)的攔截器,專門來攔截方法,包括事務(wù)的提交以及回滾操作 advisor.setAdvice(transactionInterceptor()); if (this.enableTx != null) { advisor.setOrder(this.enableTx.getNumber("order")); } return advisor; }
進(jìn)入transactionAttributeSource()注解解析器,源碼如下:
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) { this.publicMethodsOnly = publicMethodsOnly; this.annotationParsers = new LinkedHashSet<>(2); // -- Spring注解的解析器 this.annotationParsers.add(new SpringTransactionAnnotationParser()); if (jta12Present) { // -- jta的解析器 this.annotationParsers.add(new JtaTransactionAnnotationParser()); } if (ejb3Present) { // -- ejb的解析器 this.annotationParsers.add(new Ejb3TransactionAnnotationParser()); } }
進(jìn)入SpringTransactionAnnotationParser(),部分源碼如下:
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) { RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute(); Propagation propagation = attributes.getEnum("propagation"); rbta.setPropagationBehavior(propagation.value()); Isolation isolation = attributes.getEnum("isolation"); rbta.setIsolationLevel(isolation.value()); rbta.setTimeout(attributes.getNumber("timeout").intValue()); rbta.setReadOnly(attributes.getBoolean("readOnly")); rbta.setQualifier(attributes.getString("value")); ArrayListrollBackRules = new ArrayList<>(); Class>[] rbf = attributes.getClassArray("rollbackFor"); for (Class> rbRule : rbf) {
會發(fā)現(xiàn)@Transactional中的各種屬性都在這里,這樣,注解解析器就分析完了
再來看事務(wù)的攔截器,分析事務(wù)是如何回滾和提交的,進(jìn)入transactionInterceptor()
@Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionInterceptor transactionInterceptor() { // -- 事務(wù)的攔截器 TransactionInterceptor interceptor = new TransactionInterceptor(); interceptor.setTransactionAttributeSource(transactionAttributeSource()); if (this.txManager != null) { // -- 將事務(wù)管理器設(shè)置進(jìn)去,為了事務(wù)的提交和回滾操作 interceptor.setTransactionManager(this.txManager); } return interceptor; }
TransactionInterceptor 是一個實(shí)現(xiàn)了MethodInterceptor接口的類,標(biāo)志著TransactionInterceptor是一個方法攔截器,進(jìn)入它的invoke()方法
@Override @Nullable public Object invoke(final MethodInvocation invocation) throws Throwable { // Work out the target class: may be {@code null}. // The TransactionAttributeSource should be passed the target class // as well as the method, which may be from an interface. Class> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // Adapt to TransactionAspectSupport"s invokeWithinTransaction... return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); }
進(jìn)入invokeWithinTransaction()
@Nullable protected Object invokeWithinTransaction(Method method, @Nullable Class> targetClass, final InvocationCallback invocation) throws Throwable { // If the transaction attribute is null, the method is non-transactional. TransactionAttributeSource tas = getTransactionAttributeSource(); // -- 拿到事務(wù)注解信息包括事務(wù)的qualifier和rollback信息 final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null); // -- 獲取事務(wù)管理器 final PlatformTransactionManager tm = determineTransactionManager(txAttr); // -- 事務(wù)連接點(diǎn)的定義信息 final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // 創(chuàng)建并開啟事務(wù) TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal = null; try { // This is an around advice: Invoke the next interceptor in the chain. // This will normally result in a target object being invoked. // -- 調(diào)用目標(biāo)方法 retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { // target invocation exception // -- 出現(xiàn)異常了,獲取事務(wù)管理器,進(jìn)行事務(wù)的回滾 completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { cleanupTransactionInfo(txInfo); } // -- 未出現(xiàn)異常,也獲取事務(wù)管理器則進(jìn)行事務(wù)的提交 commitTransactionAfterReturning(txInfo); return retVal; } .........總結(jié)
Spring事務(wù)源碼梳理
通過注解@EnableTransactionManagement中的@Import(TransactionManagementConfigurationSelector.class)給容器中導(dǎo)入了兩個組件,分別是:AutoProxyRegistrar和ProxyTransactionManagementConfiguration
AutoProxyRegistrar:它是一個后置處理器,給容器中注冊一個InfrastructureAdvisorAutoProxyCreator,InfrastructureAdvisorAutoProxyCreator利用后置處理器機(jī)制在對象創(chuàng)建以后,對對象進(jìn)行包裝,返回一個代理對象(增強(qiáng)器),代理對象執(zhí)行方法,利用攔截器鏈進(jìn)行調(diào)用。
ProxyTransactionManagementConfiguration:給容器中注冊事務(wù)增強(qiáng)器
事務(wù)增強(qiáng)器要用事務(wù)注解信息:AnnotationTransactionAttributeSource來解析事務(wù)注解
事務(wù)攔截器中:transactionInterceptor(),它是一個TransactionInterceptor(保存了事務(wù)屬性信息和事務(wù)管理器),而TransactionInterceptor是一個MethodInterceptor,在目標(biāo)方法執(zhí)行的時(shí)候,執(zhí)行攔截器鏈,事務(wù)攔截器(首先獲取事務(wù)相關(guān)的屬性,再獲取PlatformTransactionManager,如果沒有指定任何transactionManager,最終會從容器中按照類型獲取一個PlatformTransactionManager,最后執(zhí)行目標(biāo)方法,如果異常,便獲取到事務(wù)管理器進(jìn)行回滾,如果正常,同樣拿到事務(wù)管理器提交事務(wù)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/73200.html
摘要:編程式事務(wù)指的是通過編碼方式實(shí)現(xiàn)事務(wù)聲明式事務(wù)基于將具體業(yè)務(wù)邏輯與事務(wù)處理解耦。聲明式事務(wù)管理使業(yè)務(wù)代碼邏輯不受污染因此在實(shí)際使用中聲明式事務(wù)用的比較多。聲明式事務(wù)有兩種方式,一種是在配置文件中做相關(guān)的事務(wù)規(guī)則聲明,另一種是基于注解的方式。 事務(wù)管理是應(yīng)用系統(tǒng)開發(fā)中必不可少的一部分。Spring 為事務(wù)管理提供了豐富的功能支持。Spring 事務(wù)管理分為編碼式和聲明式的兩種方式。編程式...
摘要:事務(wù)管理學(xué)習(xí)總結(jié)時(shí)間年月日星期二說明本文部分內(nèi)容均來自慕課網(wǎng)。一致性一致性指事務(wù)前后數(shù)據(jù)的完整性必須保持一致。聲明式事務(wù)管理基于的方式很少使用需要為每個進(jìn)行事務(wù)管理的類,配置一個進(jìn)行增強(qiáng)。 《Spring事務(wù)管理》學(xué)習(xí)總結(jié) 時(shí)間:2017年2月7日星期二說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com/教學(xué)示例源碼:https://github.com...
摘要:事務(wù)管理結(jié)構(gòu)事務(wù)管理有個左右,其中最核心的有個,分別是。事務(wù)管理主要結(jié)構(gòu)如下三個核心接口源碼解析接口是用于定義一個事務(wù),它定義了事務(wù)管理的五大屬性,在上一篇文章中有詳細(xì)介紹。只需要裝配一個實(shí)體管理工廠接口的任意實(shí)現(xiàn)。 1.Spring事務(wù)管理API結(jié)構(gòu) ??Spring事務(wù)管理API有100個左右,其中最核心的API有3個,分別是TransactionDefinition、 ??Pla...
閱讀 3424·2021-11-25 09:43
閱讀 2307·2021-09-06 15:02
閱讀 3548·2021-08-18 10:21
閱讀 3347·2019-08-30 15:55
閱讀 2354·2019-08-29 17:06
閱讀 3539·2019-08-29 16:59
閱讀 971·2019-08-29 13:47
閱讀 2769·2019-08-26 13:24