Spring 源码(七)Spring 事务源码解析

注册后置处理器开启对事务的支持

@EnableTransactionManagement

@EnableTransactionManagement注解的主要作用是开启对事务的支持,源码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

    boolean proxyTargetClass() default false;

    AdviceMode mode() default AdviceMode.PROXY;

    int order() default Ordered.LOWEST_PRECEDENCE;

}

这里最核心的是TransactionManagementConfigurationSelector类,这个类主要的作用是通过ImportSelector注册了AutoProxyRegistrarProxyTransactionManagementConfiguration2个组件,源码如下:

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

    @Override
    protected String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
            case PROXY:
                // 注册 InfrastructureAdvisorAutoProxyCreator 后置处理器和事务管理器组件
                return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
            case ASPECTJ:
                return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
            default:
                return null;
        }
    }
}

AutoProxyRegistrar

AutoProxyRegistrar 的主要作用是将InfrastructureAdvisorAutoProxyCreator后置处理器注册到容器,注册这个后置处理器和上一篇Spring AOP注册AnnotationAwareAspectJAutoProxyCreator后置处理器一样,这里就不在重复说明了。InfrastructureAdvisorAutoProxyCreator 他是实现了BeanPostProcessor 接口的后置处理器,所以所有 Bean 的初始化都会调用其 postProcessAfterInitialization 方法,这个方法的实现是在其父类AbstractAutoProxyCreator类中。

ProxyTransactionManagementConfiguration

我们通过ProxyTransactionManagementConfiguration来注册事务管理器组件,这个类本身也是一个配置类。在这个配置类中我们将会注册一下三个组件:

  • BeanFactoryTransactionAttributeSourceAdvisor:事务增强器,包含了切面组件 TransactionInterceptor和标签解析器TransactionAttributeSource
  • TransactionAttributeSource:@Transaction注解标签解析器
  • TransactionInterceptor:保存了事务属性信息,事务管理器;它本身也是一个方法拦截器,在invoke方法中进行了事务的处理。

创建代理Bean

上面我们说了所以所有 Bean 的初始化都会调用其 AbstractAutoProxyCreator#postProcessAfterInitialization 方法来完成Bean的增强,我们跟进去可以看到这段代码:

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

可以看到生代理对象是在wrapIfNecessary(bean, beanName, cacheKey);方法中完成的,源码如下:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    
    // 如果存在建言那么久创建代理类
    // 获取拦截链
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 使用拦截链创建代理对象,对原有的Bean进行增强
        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;
}

找到拦截链的的核心方法是 BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans方法

findAdvisorBeans:67, BeanFactoryAdvisorRetrievalHelper (org.springframework.aop.framework.autoproxy)
findCandidateAdvisors:102, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
findEligibleAdvisors:88, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
getAdvicesAndAdvisorsForBean:70, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
wrapIfNecessary:346, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
postProcessAfterInitialization:298, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
applyBeanPostProcessorsAfterInitialization:423, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
initializeBean:1638, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:555, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:483, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
getObject:312, AbstractBeanFactory$1 (org.springframework.beans.factory.support)
getSingleton:230, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:308, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:197, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:761, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:867, AbstractApplicationContext (org.springframework.context.support)
refresh:543, AbstractApplicationContext (org.springframework.context.support)
<init>:84, AnnotationConfigApplicationContext (org.springframework.context.annotation)

源码如下:

public List<Advisor> findAdvisorBeans() {
    // Determine list of advisor bean names, if not cached already.
    String[] advisorNames = null;
    synchronized (this) {
        advisorNames = this.cachedAdvisorBeanNames;
        if (advisorNames == null) {
            // 获取所有增强器的名称
            advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    this.beanFactory, Advisor.class, true, false);
            this.cachedAdvisorBeanNames = advisorNames;
        }
    }
    if (advisorNames.length == 0) {
        return new LinkedList<Advisor>();
    }

    List<Advisor> advisors = new LinkedList<Advisor>();
    for (String name : advisorNames) {
        if (isEligibleBean(name)) {
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Skipping currently created advisor '" + name + "'");
                }
            }
            else {
                try {
                    // 根据名称增强器
                    advisors.add(this.beanFactory.getBean(name, Advisor.class));
                }
                ...
            }
        }
    }
    // 返回拦截链
    return advisors;
}

创建代理Bean的核心流程:

  1. 单例Bean初始化完成后执行后置处理器 AbstractAutoProxyCreator#postProcessAfterInitialization 方法
  2. 在容器中找Advisor类型的所有增强器名称,这就会将与事务相关的增强器BeanFactoryTransactionAttributeSourceAdvisor找出来
  3. 根据增强器名称获取对应的实例,并生成拦截链
  4. 判断代理类型
  5. 根据不同的代理类型和拦截链创建代理对象

执行业务方法进行拦截

前面AOP说过不管理是JdkDynamicAopProxy还是CglibAopProxy代理,他们的执行最终都会去调用MethodInterceptor.invoke()方法,而我们事务对应的方法拦截器是TransactionInterceptor类。也就是说我们对事务的增强起始是在TransactionInterceptorinvoke方法中。源码如下:

@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {
    ...
    return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
        @Override
        public Object proceedWithInvocation() throws Throwable {
            return invocation.proceed();
        }
    });
}

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

    // 获取事务属性
    final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
    // 获取事务管理器
    final PlatformTransactionManager tm = determineTransactionManager(txAttr);
    // 构造方法唯一标示
    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

    // 声明式事务
    if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
        // 创建事务
        TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
        Object retVal = null;
        try {
            // 执行被增强的方法
            retVal = invocation.proceedWithInvocation();
        }
        catch (Throwable ex) {
            // 异常回滚
            completeTransactionAfterThrowing(txInfo, ex);
            throw ex;
        }
        finally {
            // 清除信息
            cleanupTransactionInfo(txInfo);
        }
        // 提交事务
        commitTransactionAfterReturning(txInfo);
        return retVal;
    }
    // 编程式事务
    ...
}

从上面我们的源码可以看出,一个事务处理的标准流程:

  1. createTransactionIfNecessary 创建一个事务
  2. invocation.proceedWithInvocation(); 执行业务方法
  3. completeTransactionAfterThrowing(txInfo, ex); 如果遇到异常,事务回滚
  4. commitTransactionAfterReturning(txInfo); 如果没有异常就提交事务

在创建,回滚和提交事务方法中还有的很多对嵌套事务的逻辑,比如事务的传递性,事务回滚的条件判断等,这里就不说了,有兴趣自己去跟下源码。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,045评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,114评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,120评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,902评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,828评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,132评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,590评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,258评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,408评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,335评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,385评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,068评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,660评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,747评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,967评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,406评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,970评论 2 341

推荐阅读更多精彩内容