Spring提供了非常強大的Transactional註解,下面這篇文章想從原始碼的角度來看一下Transactional這個註解是如何工作的。
1.Spring AOP
Transactional註解的實現依賴於AOP技術,AOP是面向切面程式設計(Aspect-oriented programming)的縮寫,是一種不同於物件導向程式設計(Object-oriented programming)的技術。它的好處有很多,其中的一個好處就是:在不改變現有程式碼的基礎上,增加新的行為。網上關於AOP的文章還是比較多的,可以自行搜尋閱讀。
2.程式碼demo
為了能夠弄清楚Transactional註解是如何工作的,需要一個簡單的例子來追蹤程式碼執行的過程。可以參考官方的例子。Spring Boot現在非常的智慧,你幾乎不需要怎麼配置就能使用Transactional這個註解,引述官方文件裡面的一段話:
Your application has actually zero configuration. Spring Boot will detect spring-jdbc on the classpath and h2 and will create a DataSource and a JdbcTemplate for you automatically. Because such infrastructure is now available and you have no dedicated configuration, a DataSourceTransactionManager will also be created for you: this is the component that intercepts the @Transactional annotated method
至於如何做到如此少的配置的,可以參考一些關於Spring Boot Stater的文章。
3.初探:Transactional 註解到底做了什麼
想要探究這個註解如何工作,剛開始都是無從下手的。那就用最笨的辦法,宣告一個bean,在這個bean的某一個方法上面加上 @Transactional 註解,然後呼叫這個方法,看看發生了什麼。
Object o = context.getBean("ttb");
if (o instanceof TransactionTestBean) {
TransactionTestBean tmp = (TransactionTestBean) o;
String s = tmp.transactionTest();
System.out.println(s);
}
複製程式碼
通過debug,發現這個叫ttb(不要在意名字)的bean變成了下面這個樣子:
可以看到這個bean已經是由AOP幫我處理之後的bean了,那這個bean是什麼時候生成的以及怎麼就變成了我們現在看到的樣子的呢?依稀記得有一個DefaultListableBeanFactory的類,它負責bean的建立,在這個類下搜了一下doCreateBean,找到了它的父類 AbstractAutowireCapableBeanFactory,打上斷點,看會不會停下來。果然命中了斷點,但是看到的beanName可能是這樣的,不過沒關係,我們直接繼續,直到找到我們的bean為止。4.跟蹤
通過斷點,最終我們定位到cglib的處理是在方法applyBeanPostProcessorsAfterInitialization裡面完成的,這個方法的程式碼大概是長這個樣子的。
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
複製程式碼
可以看到這個getBeanPostProcessors裡面有很多的BeanPostProcessor,其中有一個叫做InfrastructureAdvisorAutoProxyCreator的,在它執行完postProcessAfterInitialization之後,我們的bean就變成了cglib的形式了,通過進一步的跟蹤,發現在AbstractAutoProxyCreator類下,有一個createProxy的方法,順著呼叫的關係最後找到了在org.springframework.aop.framework包下有一個CglibAopProxy的類,類裡面的getProxy方法,終於找到了和這篇文章內容有點相似的程式碼了,建立bean的過程初步跟蹤完成。
5.小結
這篇文章只是初略的記錄了spring如何建立帶有 @Transactional註解的bean的,很多細節的跳過了(比如剛才那個InfrastructureAdvisorAutoProxyCreator是如何來的),後續的文章會呈現這些細節以及Transactional生成的proxy在呼叫業務程式碼之前做了什麼。
打個廣告,阿里巴巴集團長期接受簡歷,有需要內推的朋友可以將簡歷傳送到 linlan.zcj@alibaba-inc.com。