spring事务管理 TransactionProxyFactoryBean源码分析

J2EE,当然离不开事务,事务又当然少不了Spring声明式事务。spring声明式事务,很多码农门,应该和笔者一样,停留在使用上,及仅仅了解点原理。如:Spring事务管理原理“代理+AOP”,再深入了解就不太清楚了。一直对声明式事务实现特别感兴趣,今天抽时间,剖析一下下。

1.准备

BeanFactory,及对象生成周期

AOP代理对象生成过程

1.1.BeanFactory 及生命周期

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树结构中创建而来。生成的代理对象也是如此。

1.2 周期lifecycle

1. BeanNameAware‘s setBeanName

2. BeanClassLoaderAware‘s setBeanClassLoader

3. BeanFactoryAware‘s setBeanFactory

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 代理对象生成

1.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 生成序列图

需要关注:

1.生成代理时机:在afterPropertiesSet中,(对应10. InitializingBean‘s afterPropertiesSet)

2.委派给AopProxy具体实现类生成代理对象。

1.3 AOP 拦截器实现(具体发生在每次函数调用过程中)

Advisor规则应用过程,发生在具体方法调用过程中,此时代理对象已经生成了。

主要工作:

  1. 维护Advisor链
  2. 匹配过程,主要通过Pointcut中的ClassFiter,和MethodMatcher完成。

2.TransactionProxyFactoryBean 对象剖析

2.1 类图

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类图

2.2.2 序列图

事务模板入口

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();
      }
   }
}
时间: 2024-11-05 03:59:59

spring事务管理 TransactionProxyFactoryBean源码分析的相关文章

Mybatis整合Spring实现事务管理的源码分析

一:前言 没有完整看完,但是看到了一些关键的地方,这里做个记录,过程会有点乱,以后逐渐补充最终归档为完整流程:相信看过框架源码的都知道过程中无法完全确定是怎样的流程,毕竟不可能全部都去测试一遍 ,但是看的过程中灵感的显现很重要(就是直觉知道接下来的步骤是什么应该是什么之类的,但是这个自觉是猜的而非蒙的,即过程里是有往会递推看到了一些关键点的而不是抛色子来确定是哪个子类) ,因此自己写的时候也无法将看的过程里产生的想法写得很细,过程也有点跳,如果大家有疑问最好自己去验证(方式就是搜索然后看哪里调用

Spring中Bean命名源码分析

Spring中Bean命名源码分析 一.案例代码 首先是demo的整体结构 其次是各个部分的代码,代码本身比较简单,不是我们关注的重点 配置类 /** * @Author Helius * @Create 2019-10-25-20:16 */ @Configuration @ComponentScan(basePackages = {"service"}) public class SpringConfiguration { } 接口的实现类 public interface Use

Spring MVC初始化部分源码分析

首先定位到org.springframework.context.support.AbstractApplicationContext中的refresh()方法: public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh

spring boot 2.0 源码分析(三)

通过上一章的源码分析,我们知道了spring boot里面的listeners到底是什么(META-INF/spring.factories定义的资源的实例),以及它是创建和启动的,今天我们继续深入分析一下SpringApplication实例变量中的run函数中的其他内容.还是先把run函数的代码贴出来: /** * Run the Spring application, creating and refreshing a new * {@link ApplicationContext}. *

Spring AOP介绍及源码分析

一.AOP介绍 举个例子来说明一下吧!现在系统中有很多的业务方法,如上传产品信息.修改产品信息.发布公司库等:现在需要对这些方法的执行做性能监控,看每个业务方法的执行时间:在不改变原业务代码的基础上,也许我们会这么做: Offer接口: Offer实现: Offer代理: 我们要通过下面的方式来使用: 上面的例子的输出为: 上面的例子中,OfferProxy实现了IOffer,而所有的业务实现均委托给其成员offer:可以想像,这应该就是最简单的AOP的实现了:但这种方式会存在一个问题:如果有非

spring boot 2.0 源码分析(五)

在上一篇文章中我们详细分析了spring boot是如何准备上下文环境的,今天我们来看一下run函数剩余的内容.还是先把run函数贴出来: /** * Run the Spring application, creating and refreshing a new * {@link ApplicationContext}. * @param args the application arguments (usually passed from a Java main method) * @re

spring事务@Transactional的源码

/* * Copyright 2002-2015 the original author or authors.//=============== * 2002 - 2015年版权所有作者或作者 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obta

Spring整合MyBatis(二)源码分析

在Spring配置Mybatis的文件中我们可以看到如下代码: <!-- 扫描dao --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="org.tarena.note.dao"> </property> MapperScannerConfig

Spring bean定义解析源码分析

在上一篇Spring IOC容器启动简介中在ClassPathXmlApplicationContext的基础粗略的分析了IOC容器的启动过程,对一些比较复杂的步骤没有详细的说明,从本篇开始对其中的一些比较复杂的步骤进行分析.本篇对基于ClassPathXmlApplicationContext的IOC容器的bean定义的解析与加载过程进行分析.bean定义解析加载的简单时序图如下: bean定义的解析通过XmlBeanDefinitionReader来完成,在解析前先做一些准备工作:1.设置环