Spring何時為使用事務註解的bean建立代理 ?
本文基於
Springboot 2.1.0
JPA
應用分析總結。
- 應用啟動過程中
Spring AOP
自動配置機制AopAutoConfiguration
執行僅在註解
@EnableAspectJAutoProxy
類存在於classpath
並且spring.aop
沒有明確設定為false
時應用
可以認為等價於主動使用註解@EnableAspectJAutoProxy
- 註解
@EnableAspectJAutoProxy
匯入了類AspectJAutoProxyRegistrar
AspectJAutoProxyRegistrar
ImportBeanDefinitionRegistrar
, AspectJAutoProxyRegistrar
向容器註冊一個AnnotationAwareAspectJAutoProxyCreator
,長類名 :
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
這是一個BeanPostProcessor
,它會在每個bean
例項建立時檢查該bean
是否需要建立代理,需要的話
就建立相應的代理。
- 註解
- 應用啟動過程中自動配置機制
TransactionAutoConfiguration
執行TransactionAutoConfiguration
使用了註解@EnableTransactionManagement
- 註解
@EnableTransactionManagement
匯入TransactionManagementConfigurationSelector
TransactionManagementConfigurationSelector
根據引數和包引用狀態決定引入 :ProxyTransactionManagementConfiguration
PROXY
)或者AspectJJtaTransactionManagementConfiguration
(ASPECTJ
,使用JTA
) 或者AspectJTransactionManagementConfiguration
(ASPECTJ
,不使用JTA
)
ProxyTransactionManagementConfiguration
是較常見的一種情況,這裡我們以此為例繼續分析。ProxyTransactionManagementConfiguration
配置類定義bean
:AnnotationTransactionAttributeSource
AnnotationTransactionAttributeSource
用於分析理解事務註解屬性@Transactional
的語義ProxyTransactionManagementConfiguration
配置類定義bean
:TransactionInterceptor
屬性
transactionAttributeSource
:bean AnnotationTransactionAttributeSource
ProxyTransactionManagementConfiguration
配置類定義bean
:BeanFactoryTransactionAttributeSourceAdvisor
型別 :
BeanFactoryTransactionAttributeSourceAdvisor
, 名稱:transactionAdvisor
屬性advice
:bean TransactionInterceptor
屬性transactionAttributeSource
:bean AnnotationTransactionAttributeSource
- 註解
- 某個帶有事務註解屬性的服務元件
bean
(帶註解@Component
)首次被使用時例項化- 因為
AnnotationAwareAspectJAutoProxyCreator
是一個BeanPostProcessor
,所以它在每個bean
例項化時會針對該bean
執行,所以在帶有事務註解屬性的服務元件bean
被例項化時,它也被應用; - 服務元件
bean
如果在類或者方法級別使用了事務註解@Transactional
,則它會被AnnotationAwareAspectJAutoProxyCreator
認為是需要建立代理(用於進行事務處理),否則不需要建立代理 ; AnnotationAwareAspectJAutoProxyCreator
認為某個服務元件bean
需要建立代理物件時,為其建立代理。
具體程式碼參考AnnotationAwareAspectJAutoProxyCreator
基類AbstractAutoProxyCreator
:
// 介面 BeanPostProcessor 定義的方法 @Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice. // 使用了事務註解的bean上的事務註解@Transactional會被發現, // 進行發現 bean BeanFactoryTransactionAttributeSourceAdvisor 到 specificInterceptors // 具體的發現邏輯可以參考工具類方法 : AopUtils#findAdvisorsThatCanApply Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); // 如果 specificInterceptors 不為空,說明需要有 advise 需要被應用到該bean,所以需要建立相應的代理 // 對應以應用 advise 。 // 這裡 DO_NOT_PROXY 其實是 null if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); // 建立代理 // 原bean物件 : bean // 代理物件 : proxy Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
- 因為
相關文章
Spring Transaction 5.1.2 原始碼分析 : AnnotationTransactionAttributeSource 解析註解式事務屬性