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 ProxyConfigimplements 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();//生成代理的ClassLoaderprivate transient ClassLoader proxyClassLoader;private Object proxy;
}

2.1.3 TransactionProxyFactoryBean

代理工厂bean,用于简化的声明性事务处理。

public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBeanimplements 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 exceptioncompleteTransactionAfterThrowing(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();}}
}

转载于:https://blog.51cto.com/dba10g/1927762

spring事务管理 TransactionProxyFactoryBean源码分析相关推荐

  1. @Transactional的用法详解及Transactional事务无效的源码分析

    数据库事务正确执行的四要素 1.原子性 事务是不可分割的最小的工作单元,事务内的操作要么全做,要么全不做,不能只做一部分. 2.一致性 事务执行前数据库的数据按照逻辑处于正确的状态,事务执行后数据库的 ...

  2. mybatis第十话 - mybaits整个事务流程的源码分析

    1.故事前因 在分析mybatis源码时一直带的疑问,一直以为事务是在SqlSessionTemplate#SqlSessionInterceptor#invoke完成的,直到断点才发现并不简单! 在 ...

  3. 阿里开源一站式分布式事务框架seata源码分析(AT模式下TM与RM分析)

    序言: 对于阿里开源分布式事务框架seata的详细了解可以参考官网,这里不会详细介绍.本章只会介绍seata中AT模式的源码分析(对阿seata有一定了解或者成功完成过demo). seata中一个事 ...

  4. eureka 之前的服务如何关闭_干货分享 | 服务注册中心Spring Cloud Eureka部分源码分析...

    友情提示:全文13000多文字,预计阅读时间10-15分钟 Spring Cloud Eureka作为常用的服务注册中心,我们有必要去了解其内在实现机制,这样出现问题的时候我们可以快速去定位问题.当我 ...

  5. spring+dbcp连接池源码分析

    Spring对数据库连接池的支持 常见的数据库连接池有c3p0,dbcp以及druid,这里使用的是dbcp. 前文中使用DataSourceUtils获取和释放connection,代码如下: // ...

  6. spring boot 2.0 源码分析(二)

    在上一章学习了spring boot 2.0启动的大概流程以后,今天我们来深挖一下SpringApplication实例变量的run函数. 先把这段run函数的代码贴出来: /*** Run the ...

  7. spring cloud集成 consul源码分析

    1.简介 1.1 Consul is a tool for service discovery and configuration. Consul is distributed, highly ava ...

  8. spring boot 2.0 源码分析(三)

    通过上一章的源码分析,我们知道了spring boot里面的listeners到底是什么(META-INF/spring.factories定义的资源的实例),以及它是创建和启动的,今天我们继续深入分 ...

  9. Spring Security CSRF防御源码分析

    一.CSRF简介 1.CSRF是什么? CSRF(Cross-site request forgery),也被称为:one click attack/session riding,中文名称:跨站请求伪 ...

最新文章

  1. 报名 | 刘鹰教授:草根创新力:中国经济快速发展的秘诀
  2. C++智能指针(设计和使用)
  3. JavaScript实现十种经典排序算法(js排序算法)
  4. MFC中下拉条(组合框)combo box的使用图文教程
  5. THttprio连接WebService的内存泄漏问题
  6. 函数定义、函数参数、跨脚本调用函数
  7. matlab聚类算法,科学网—matlab-聚类算法笔记 - 孙月芳的博文
  8. python3.5安装scrapy_Python3.5下安装测试Scrapy
  9. GWT,GWT-Ext(SmartGWT),GXT(Ext GWT)常见任务
  10. 计算机 学术论文写作,计算机辅助学术论文写作系统的研制策略与方法.pdf
  11. flash activex java_Flash Activex NPAPI PPAPI 各种网页插件完整安装包下载地址
  12. WPS Office 简明教程
  13. 超市仓库商品盘点作业流程,仓库如何进行盘点,仓库盘点流程?仓库盘点好方法?
  14. mybatis中获取当前时间_MySQL NOW和SYSDATE函数:获取当前时间日期
  15. Leetcode笔记 每日一题 824. 山羊拉丁文 (22.04.21)
  16. Flash制作雾效果
  17. win10添加网络打印机_大神教你设置 win10系统安装打印机及驱动的详细方案 -win10使用教程...
  18. AndroidID、IMEI、OAID获取
  19. [无人机学习]无人机学习概论
  20. 中控门禁控制器接玻璃移动门

热门文章

  1. 线程池模式比较-------ICE线程池模型------L/F领导者跟随者模式
  2. CHM文件不能正确显示
  3. 2017202110104-高级软件工程第二次作业个人项目之-四则运算生成程序
  4. [Docker系列·8] Docker远程接口
  5. 检查一棵二叉树是否为二叉查找树
  6. [C++] C++风格的强制类型转换探讨
  7. 如何访问自定义键值的二维数组
  8. 详细介绍Oracle DBA工作职责
  9. 求解第K个斐波那契质数
  10. 如何删除VS2015中的OpenCV的配置