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();
      }
   }
}
相关文章
相关标签/搜索