1. 程式人生 > >Spring何時為使用事務註解的bean建立代理 ?

Spring何時為使用事務註解的bean建立代理 ?

本文基於Springboot 2.1.0 JPA 應用分析總結。

  1. 應用啟動過程中Spring AOP自動配置機制AopAutoConfiguration執行

    僅在註解 @EnableAspectJAutoProxy 類存在於classpath並且 spring.aop 沒有明確設定為 false 時應用
    可以認為等價於主動使用註解 @EnableAspectJAutoProxy

    1. 註解@EnableAspectJAutoProxy匯入了類AspectJAutoProxyRegistrar

      AspectJAutoProxyRegistrar

      是一個ImportBeanDefinitionRegistrar

    2. AspectJAutoProxyRegistrar向容器註冊一個AnnotationAwareAspectJAutoProxyCreator,

      長類名 : org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
      這是一個BeanPostProcessor,它會在每個bean例項建立時檢查該bean是否需要建立代理,需要的話
      就建立相應的代理。

  2. 應用啟動過程中自動配置機制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

  3. 某個帶有事務註解屬性的服務元件bean(帶註解@Component)首次被使用時例項化
    1. 因為AnnotationAwareAspectJAutoProxyCreator是一個BeanPostProcessor,所以它在每個bean例項化時會針對該bean執行,所以在帶有事務註解屬性的服務元件bean被例項化時,它也被應用;
    2. 服務元件bean如果在類或者方法級別使用了事務註解@Transactional,則它會被AnnotationAwareAspectJAutoProxyCreator認為是需要建立代理(用於進行事務處理),否則不需要建立代理 ;
    3. 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 解析註解式事務屬性