事務是什么围俘?了解事務的原理嗎簿寂?說下Spring的事務原理常遂,能自己實現(xiàn)Spring事務原理嗎克胳?先自我檢測下這些知識掌握了嗎漠另。那么接下來一起看下與Spring相關的事務
概念
事務具有ACID特性笆搓。
是指作為單個邏輯工作單元執(zhí)行的一系列操作砚作,要么完全地執(zhí)行葫录,要么完全地不執(zhí)行米同。
Spring事務的底層依賴MySQL的事務少孝,代碼層面上利用AOP實現(xiàn)稍走。MySQL的事務有隔離級別的概念婿脸,只有InnoDB有事務柄驻,并且實現(xiàn)方式是利用undo log和redo log抑钟。
AOP方面野哭,有連接點,切點蛔溃,增強揪利,目標疟位,織入绍撞。參考Spring AOP入門章贞,Spring則是在代碼層面執(zhí)行事務的時候使用TransactionInceptor進行攔截鸭限,然后處理败京。
系統(tǒng)解析Spring事務原理文章:
代碼
- 在AopConfigUtils可以看到具體會生成什么類型的AutoProxyCreator赡麦,這幾個都是beanPostProcessor帕识,在Bean創(chuàng)建之后對Bean的實例進行自定義處理泛粹。如果使用了@EnableTransactionManagement,經(jīng)過一些配置這次生成的是InfrastructureAdvisorAutoProxyCreator渡冻,具體如何生成這個類的點進去@EnableTransactionManagement里面即可戚扳。
EnableTransactionManagement
-> @Import(TransactionManagementConfigurationSelector.class)
-> return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
-> AutoProxyRegistrar.registerBeanDefinitions中
-> 創(chuàng)建InfrastructureAdvisorAutoProxyCreator
-
在Bean的生命周期中,Bean創(chuàng)建完成調(diào)用創(chuàng)建InfrastructureAdvisorAutoProxyCreator.postProcessAfterInitialization方法族吻。
另外AbstractAutowireCapableBeanFactory.initializeBean方法也值得一看
獲取Bean的Advice帽借,如果有Advice(增強的話),創(chuàng)建bean的動態(tài)代理超歌。創(chuàng)建動態(tài)代理都是Spring AOP做的事情了砍艾,根據(jù)設置就是創(chuàng)建JDK動態(tài)代理和CGLib代理了,我們項目默認都是使用CGLib動態(tài)代理(proxyTargetClass=true即可),只說下CGlib的動態(tài)代理,主要利用了Enhancer類
? 這里有Enhacer用法Cglib的使用方法(1)--Enhancer
?
? 攔截接口intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)有我們根據(jù)條件進行是否要攔截的數(shù)據(jù),根據(jù)參數(shù)就可以判斷。
?
-
可以跟進去DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice方法中看
PointcutAdvisor為BeanFactoryTransactionAttributeSourceAdvisor MethodMatcher為TransactionAttributeSourcePointcut
得到的攔截器為事務攔截器惜犀,既然是事務攔截器莉御,那么可以跟上之前的分析了琅关。
- 我們接著看為什么獲取的攔截器是MethodInterceptor新症。在MethodMatcher.match中有AdvisorAdapter
而Advice是advisor中的侯繁,advisor是BeanFactoryTransactionAttributeSourceAdvisor
- 一種在TransactionProxyFactoryBean中默認的TransactionIntercetor
- 在默認的@EnableTransactionManagement注解中粹懒,將BeanFactoryTransactionAttributeSourceAdvisor的advice設置為TransactionIntercetor弓颈,這一步的注解生效搬瑰,我們第一步就已經(jīng)講過了翼悴。
- 方法是如何匹配的,TransactionAttributeSourcePointcut中matches方法沾谜,調(diào)用TransactionAttributeSource屬性判斷是否有method的屬性
然后調(diào)用computeTransactionAttribute(method, targetClass)荆秦,判斷是否有事務屬性
AbstractFallbackTransactionAttributeSource.computeTransactionAttribute
--> AnnotationTransactionAttributeSource.determineTransactionAttribute 獲取方法屬性
--> 獲取到TransactionAttribute瓤介,然后返回
- 到現(xiàn)在我們基本上解釋了,Spring的事務攔截器是如何生效的,攔截器什么時候設置的填抬,事務方法是如何匹配的。
事務不生效
- private方法不會生效揍堰,JDK中必須是接口式塌,接口中不可能有private方法链沼,而私有方法子類無法方法括勺,也不會生效
- CGLib代理的時候,final方法不會生效,拋NullPointException
- protect方法的話错负,默認是只允許public方法油航。
最后一個就是在當前的bean中非事務方法調(diào)用事務方法為什么不生效函筋?
public int save(String name, int age) throws Exception {
insert(name, age);
return 1;
}
@Transactional
public void insert(String name, int age){
jdbcTemplate.update("insert into user(id,name,age)values(1,'"+name+"',"+age+")");
jdbcTemplate.update("insert into user(id,name,age)values(2,'"+name+"',"+age+")");
jdbcTemplate.update("insert into user(id,name,age)values(1,'"+name+"',"+age+")");
}
答:
經(jīng)過最終驗證欲芹,得出如下結(jié)論:
如果先調(diào)用的save方法牵囤,在進行方法攔截的時候,方法攔截器首先獲取當前動態(tài)代理的對象所代理的原始對象滞伟。
比如FirstApp生成的動態(tài)代理名稱為FirstApp$CGlibxxx揭鳞,這個時候通過getTarget獲取的對象即為FirstApp的實例。
接下來如果判斷當前的方法比如save方法沒有Advice(增強)梆奈,則直接調(diào)用原對象的方法野崇,即這個時候調(diào)用的是FirstApp.save方法。而不是FirstApp$CGLibxxx的save方法亩钟∨依妫可以跟代碼。
最后
Spring事務這塊清酥,如果認真看我寫的文章扶镀,相信你會收獲不少