spring事務管理 TransactionProxyFactoryBean源碼分析

J2EE,固然離不開事務,事務又固然少不了Spring聲明式事務。spring聲明式事務,不少碼農門,應該和筆者同樣,停留在使用上,及僅僅瞭解點原理。如:Spring事務管理原理「代理+AOP」,再深刻了解就不太清楚了。一直對聲明式事務實現特別感興趣,今天抽時間,剖析一下下。java

1.準備web

 BeanFactory,及對象生成周期
spring

 AOP代理對象生成過程app

1.1.BeanFactory 及生命週期框架

wKioL1kfpOiTVam3AABnnWZlYe8482.png

Factory class name 做用
ListableBeanFactory 枚舉全部的bean實例
HierarchicalBeanFactory 維護工廠父子關係
ConfigurableBeanFactory 配置BeanFactory
AutowireCapableBeanFactory 維護ean屬性注入和依賴關係維護
ConfigurableListableBeanFactory BeanFacotry配置清單,指定忽略接口
SingletonBeanRegistry 維護單例關係
FactoryBeanRegistrySupport 針對FactoryBean,維護單例關係
AbstractBeanFactory ConfigurableBeanFactory SPI.
AbstractAutowireCapableBeanFactory 提供create bean默認實現
DefaultListableBeanFactory 一個基於bean定義對象的完整的bean工廠;默認


總之,spring容器中涉及的對象,都是經過上面的BeanFactory樹結構中建立而來。生成的代理對象也是如此。ide

1.2 週期lifecycle函數

 1. BeanNameAware's setBeanNamepost

 2. BeanClassLoaderAware's setBeanClassLoader優化

 3. BeanFactoryAware's setBeanFactorythis

 4. ResourceLoaderAware's setResourceLoader (only applicable when running in an application context)

 5. ApplicationEventPublisherAware's setApplicationEventPublisher (only applicable when running in an application context)

 6. MessageSourceAware's setMessageSource (only applicable when running in an application context)

 7. ApplicationContextAware's setApplicationContext (only applicable when running in an application context)

 8. ServletContextAware's setServletContext (only applicable when running in a web application context)

 9. postProcessBeforeInitialization methods of BeanPostProcessors

 10. InitializingBean's afterPropertiesSet

 11. a custom init-method definition

 12. postProcessAfterInitialization methods of BeanPostProcessors

beanfactory shutdown

 1. DisposableBean's destroy

 2. a custom destroy-method definition


其中生成代理對象,僅僅是上面(1-12)步驟中的一步而已。

1.2 AOP 代理對象生成

wKiom1kfrwbzwsKTAAC8hHWcXSY195.png1.2.1 TargetClassAware

用於將目標類暴露在代理後面的最小界面。

1.2.2 Advised

AOP代理配置接口

public interface Advised extends TargetClassAware {
	/**是否凍結了「Advised」配置,在這種狀況下,沒法進行任何建議更改。*/
	boolean isFrozen();
	/** 代理完整的目標類而不是指定的接口?*/
	boolean isProxyTargetClass();
	/**返回由AOP代理代理的接口  */
	Class<?>[] getProxiedInterfaces();
	/**肯定給定的接口是否被代理。 */
	boolean isInterfaceProxied(Class<?> intf);

	/** 更改此Advised對象使用的TargetSource。 */
	void setTargetSource(TargetSource targetSource);
	TargetSource getTargetSource();

	/**是否能夠被AOP框架做爲ThreadLocal暴露,經過AopContext。 */
	void setExposeProxy(boolean exposeProxy);
	boolean isExposeProxy();

	/**設置此代理配置是否通過預篩選,以便它僅包含適用的advisors (與此代理的目標類匹配)。 */
	void setPreFiltered(boolean preFiltered);
	boolean isPreFiltered();

	/**返回適用於此代理的Advisor。*/
	Advisor[] getAdvisors();
	void addAdvisor(Advisor advisor) throws AopConfigException;
	void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
	boolean removeAdvisor(Advisor advisor);
	void removeAdvisor(int index) throws AopConfigException;
	int indexOf(Advisor advisor);
	boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;

	/**將給定的AOP advice 添加到advice(interceptor)鏈的尾部。這將包含在一個DefaultPointcutAdvisor中,該切點老是適用,*/
	void addAdvice(Advice advice) throws AopConfigException;
	void addAdvice(int pos, Advice advice) throws AopConfigException;
	boolean removeAdvice(Advice advice);
	int indexOf(Advice advice);
	String toProxyConfigString();
}

1.2.3 AdvisedSupport

AOP代理配置管理器的基類

public class AdvisedSupport extends ProxyConfig implements Advised {
	/** Package-protected to allow direct access for efficiency */
	TargetSource targetSource = EMPTY_TARGET_SOURCE;

	/** Advisors是否已針對特定目標類過濾 */
	private boolean preFiltered = false;

	/** The AdvisorChainFactory to use */
	AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();

	/** Cache with Method as key and advisor chain List as value */
	private transient Map<MethodCacheKey, List<Object>> methodCache;

	/**
	 * 接口由代理實現。 在List中保存註冊順序,建立具備指定順序接口的JDK代理。
	 */
	private List<Class> interfaces = new ArrayList<Class>();

	/**Advisor名單 若是添加了一個Advise,它將被包裝在一個Advisor中,而後被添加到此列表中。
	 */
	private List<Advisor> advisors = new LinkedList<Advisor>();

	/**
	 * Array updated on changes to the advisors list, which is easier
	 * to manipulate internally.
	 */
	private Advisor[] advisorArray = new Advisor[0];
	}

}

1.2.4 ProxyCreatorSupport

proxy factory的基類

public class ProxyCreatorSupport extends AdvisedSupport {
	//容許在不改變核心框架的狀況下選擇不一樣的策略。
	private AopProxyFactory aopProxyFactory;

	private List<AdvisedSupportListener> listeners = new LinkedList<AdvisedSupportListener>();

	/** Set to true when the first AOP proxy has been created */
	private boolean active = false;

	}


1.2.5 生成序列圖

wKiom1kfuF2RF6iUAAApML7U09w943.png須要關注:

1.生成代理時機:在afterPropertiesSet中,(對應10. InitializingBean's afterPropertiesSet)

2.委派給AopProxy具體實現類生成代理對象。


1.3 AOP 攔截器實現(具體發生在每次函數調用過程當中)

wKiom1kfuSzhNsJTAABIX6da5x4397.png


Advisor規則應用過程,發生在具體方法調用過程當中,此時代理對象已經生成了。

主要工做:

  1. 維護Advisor鏈

  2. 匹配過程,主要經過Pointcut中的ClassFiter,和MethodMatcher完成。


2.TransactionProxyFactoryBean 對象剖析


2.1 類圖


wKioL1kfrp7BG0uOAACVz-yE49w945.png

2.1.1 ProxyConfig

方便的用於建立代理的超類配置,以確保全部代理建立者具備一致的屬性。

public class ProxyConfig implements Serializable {

	/**
	*   設置是否直接代理目標類,而不是僅代理特定的接口。 默認值爲「false」。
	*	將其設置爲「true」以強制對TargetSource的暴露目標類進行代理。 
	*	若是該目標類是接口,將爲給定的接口建立一個JDK代理。 
	*   若是該目標類是任何其餘類,將爲給定的類建立一個CGLIB代理。
	*/
	private boolean proxyTargetClass = false;
	/**
	*設置代理是否應該執行積極的優化。 「aggressive optimizations」的確切含義在代理之間有所不一樣,但一般有一些權衡。 默認值爲「false」。
	*例如,優化一般意味着建議更改在代理建立後不會生效。 
	*所以,默認狀況下禁用優化。 若是其餘設置排除優化,則能夠忽略「true」的優化值:例如,若是「publicProxy」設置爲「true」,而且與優化不兼容。
	*/
	private boolean optimize = false;
	/**
	*設置是否應該阻止經過此配置建立的代理被轉換爲Advised,以查詢代理狀態。
	*默認爲「false」,這意味着任何AOP代理能夠轉換爲Advised。
	*/
	boolean opaque = false;
	/**
	是否能夠被AOP框架做爲ThreadLocal暴露,經過AopContext。默認false,以免沒必要要的額外攔截
	*/
	boolean exposeProxy = false;
	/**
	* 設置此配置是否應該被凍結。當配置被凍結時,不會改變任何advice。 這對於優化是有用的,
	*/
	private boolean frozen = false;
}

2.1.2 AbstractSingletonProxyFactoryBean

方便的FactoryBean類型的超類,產生單例範圍的代理對象。

public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
      implements FactoryBean<Object>, BeanClassLoaderAware, InitializingBean {
      
 	//目標對象
	private Object target;
	//被代理的一組接口
	private Class<?>[] proxyInterfaces;
	//在隱式」事務「攔截器以前設置要應用的interceptors (or advisors) 
	private Object[] preInterceptors;
	//在隱式」事務「攔截器後設置要應用的interceptors (or advisors) 
	private Object[] postInterceptors;
	

	//Specify the AdvisorAdapterRegistry to use. Default is the global AdvisorAdapterRegistry.
	private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
	//生成代理的ClassLoader
	private transient ClassLoader proxyClassLoader;

	private Object proxy;     
}

2.1.3 TransactionProxyFactoryBean

代理工廠bean,用於簡化的聲明性事務處理。

public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBean
      implements BeanFactoryAware {
	//設置事務管理器。 這將執行實際的事務管理:這個類只是一種調用它的方式。
	private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
	////設置一個pointcut,即根據傳遞的方法和屬性能夠致使TransactionInterceptor的條件調用的bean。 注意:老是調用其餘攔截器。
	private Pointcut pointcut;

	//將方法名稱的屬性設置爲鍵和事務屬性描述符(經過TransactionAttributeEditor解析)
	public void setTransactionAttributes(Properties transactionAttributes) {
		this.transactionInterceptor.setTransactionAttributes(transactionAttributes);
	}	
	//設置用於查找事務屬性的事務屬性源。 若是指定一個String屬性值,PropertyEditor將從該值建立一個MethodMapTransactionAttributeSource。
	public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
		this.transactionInterceptor.setTransactionAttributeSource(transactionAttributeSource);
	}      
}

2.1.4 使用配置

   <bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
      abstract="true">
    <property name="transactionManager" ref="transactionManager"/>
    <property name="transactionAttributes">
      <props>
        <prop key="insert*">PROPAGATION_REQUIRED</prop>
        <prop key="update*">PROPAGATION_REQUIRED</prop>
        <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
      </props>
    </property>
  </bean>
 
  <bean id="myProxy" parent="baseTransactionProxy">
    <property name="target" ref="myTarget"/>
  </bean>
 
  <bean id="yourProxy" parent="baseTransactionProxy">
    <property name="target" ref="yourTarget"/>
  </bean>

2.2 TransactionProxyFactoryBean分析

2.2.1類圖

wKiom1kfw1CQP6u9AABdiqD_NFw288.png

2.2.2 序列圖

wKiom1kfy1zSTceGAABQDGFZdak396.png

事務模板入口

org.springframework.transaction.interceptor.TransactionInterceptor

public Object invoke(@NotNull MethodInvocation invocation)

public Object invoke(final MethodInvocation invocation) throws Throwable {
   // Work out the target class: may be {@code null}.
   // The TransactionAttributeSource should be passed the target class
   // as well as the method, which may be from an interface.
   Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

   // Adapt to TransactionAspectSupport's invokeWithinTransaction...
   return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
      public Object proceedWithInvocation() throws Throwable {
         return invocation.proceed();
      }
   });
}

事務管理模板

protected Object invokeWithinTransaction(Method method, Class targetClass, final InvocationCallback invocation)
      throws Throwable {

   // If the transaction attribute is null, the method is non-transactional.
   final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
   final PlatformTransactionManager tm = determineTransactionManager(txAttr);
   final String joinpointIdentification = methodIdentification(method, targetClass);

   if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
      // Standard transaction demarcation with getTransaction and commit/rollback calls.
      TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
      Object retVal = null;
      try {
         // This is an around advice: Invoke the next interceptor in the chain.
         // This will normally result in a target object being invoked.
         retVal = invocation.proceedWithInvocation();//調用實際業務
      }
      catch (Throwable ex) {
         // target invocation exception
         completeTransactionAfterThrowing(txInfo, ex);
         throw ex;
      }
      finally {
         cleanupTransactionInfo(txInfo);
      }
      commitTransactionAfterReturning(txInfo);
      return retVal;
   }

   else {
      // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
      try {
         Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
               new TransactionCallback<Object>() {
                  public Object doInTransaction(TransactionStatus status) {
                     TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
                     try {
                        return invocation.proceedWithInvocation();
                     }
                     catch (Throwable ex) {
                        if (txAttr.rollbackOn(ex)) {
                           // A RuntimeException: will lead to a rollback.
                           if (ex instanceof RuntimeException) {
                              throw (RuntimeException) ex;
                           }
                           else {
                              throw new ThrowableHolderException(ex);
                           }
                        }
                        else {
                           // A normal return value: will lead to a commit.
                           return new ThrowableHolder(ex);
                        }
                     }
                     finally {
                        cleanupTransactionInfo(txInfo);
                     }
                  }
               });

         // Check result: It might indicate a Throwable to rethrow.
         if (result instanceof ThrowableHolder) {
            throw ((ThrowableHolder) result).getThrowable();
         }
         else {
            return result;
         }
      }
      catch (ThrowableHolderException ex) {
         throw ex.getCause();
      }
   }
}
相關文章
相關標籤/搜索