在源碼筆記(一)中,咱們留下了幾個問題:java
今天這篇文章將要談一談第一個問題:Spring Boot是怎麼掃描到咱們的bean裏面有 Transactional 這個註解,而且把 InfrastructureAdvisorAutoProxyCreator 這個 BeanPostProcessor註冊到bean的信息裏面去的spring
在筆記一里面咱們提到,在生成cglib proxy的過程當中,會在 AbstractAutowireCapableBeanFactory裏面調用 getBeanPostProcessors方法,這個方法返回的是一個叫beanPostProcessors的成員變量,經過搜索咱們發現,AbstractAutowireCapableBeanFactory 的父類 AbstractBeanFactory有一個addBeanPostProcessor的方法,這個方法會把咱們須要跟蹤的InfrastructureAdvisorAutoProxyCreator加到beanPostProcessors這個list中。經過斷點,咱們能夠看到如今已經找到了InfrastructureAdvisorAutoProxyCreator被加到list中,左邊紅色的方框是調用棧,能夠看到代碼調用的順序。 post
經過上面的調用棧,能夠找到 PostProcessorRegistrationDelegate裏面有一個這樣的方法: registerBeanPostProcessors(ConfigurableListableBeanFactory,AbstractApplicationContext),方法裏面有這樣一段代碼:String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
複製代碼
經過debug看到這個postProcessorNames變量的值以下圖,紅色框出來的是InfrastructureAdvisorAutoProxyCreator這個bean的名稱。 閱讀代碼咱們知道postProcessorNames來源於getBeanNamesForType,咱們有必要跟蹤進去,看看這個getBeanNamesForType作了什麼。this
進入到 getBeanNamesForType方法以後,咱們很快就發如今 DefaultListableBeanFactory裏面有一個 beanDefinitionNames的變量,從它的值裏面咱們能夠找到 internalAutoProxyCreator,咱們須要知道這個beanName是何時被加到 beanDefinitionNames裏面去的。在 DefaultListableBeanFactory裏面有一個 registerBeanDefinition的方法,咱們打上斷點,加上條件命中,進行觀察。左側是調用棧,有了這個咱們就能很方便的知道這個 internalAutoProxyCreator是怎麼來的。 跟着調用棧看了一會,發現這些地方只是把解析 Transactional註解的類註冊到了 DefaultListableBeanFactory裏面,並無涉及到如何的解析註解,彷佛方向錯了。回到InfrastructureAdvisorAutoProxyCreator,咱們看看是否是它在處理bean的時候解析了Transactional註解。它的父類AbstractAutoProxyCreator的方法wrapIfNecessary中有如下一段代碼:spa
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
複製代碼
跳轉到AbstractAdvisorAutoProxyCreator的方法getAdvicesAndAdvisorsForBean,其中有這樣一段代碼:debug
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
複製代碼
跳轉到findEligibleAdvisors,其中有一段代碼:code
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
複製代碼
進到findAdvisorsThatCanApply方法,看到如下代碼:cdn
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
複製代碼
跟着程序執行的順序,最後走到了AopUtils的方法canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions),方法中有一段代碼blog
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
複製代碼
進到methodMatcher.matches,看到下面這段代碼:ci
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
複製代碼
接着進入tas.getTransactionAttribute最終會來到類AbstractFallbackTransactionAttributeSource,在它的getTransactionAttribute方法中,咱們重點看一下下面這行代碼:
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
複製代碼
進到方法的裏面,執行到下面代碼:
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
複製代碼
findTransactionAttribute 方法由AbstractFallbackTransactionAttributeSource的子類AnnotationTransactionAttributeSource 實現,繼續跟蹤到了determineTransactionAttribute方法,能夠看到這個方法的代碼是這樣的:
if (ae.getAnnotations().length > 0) {
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);
if (attr != null) {
return attr;
}
}
}
return null;
複製代碼
終於開始判斷方法上面註解的個數,這可能意味着咱們快要找到spring是在哪兒解析Transactional註解了。咱們接着往下執行,進到了SpringTransactionAnnotationParser類中,它的方法parseTransactionAnnotation有這麼一段代碼:
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, Transactional.class);
複製代碼
這一段就是用來解析咱們transactional註解的,至此咱們已經找到了spring是在什麼地方解析bean裏面的transactional註解的。
本期解決了筆記(一)留下的兩個問題中一個,接下來會花一些時間來跟蹤一下cglib proxy對帶有Transactional註解的方法作了什麼。
插播一段廣告,阿里巴巴長期招聘,有須要內推的朋友能夠加脈脈私聊,或者簡歷發到linlan.zcj@alibaba-inc.com