springboot啟動流程(十二)springboot事務自動配置


所有文章

https://www.cnblogs.com/lay2017/p/11478237.html

 

正文

上一篇文章中,我們簡單了解了aop的處理過程。代理增強之前,先生成Advisor,然后利用cglib或者jdk動態代理把可以應用到當前Bean的Advisor增強到Bean上。

springboot的事務,也是基於aop實現。那么我們就需要把事務相關的配置生成Advisor,然后一樣地增強到Bean上。

 

生成Advisor

首先,我們先找到事務的自動配置類TransactionAutoConfiguration

@Configuration
@ConditionalOnClass(PlatformTransactionManager.class)
@AutoConfigureAfter({ JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
        DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class })
@EnableConfigurationProperties(TransactionProperties.class)
public class TransactionAutoConfiguration {
    // 省略

    @Configuration
    @ConditionalOnBean(PlatformTransactionManager.class)
    @ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
    public static class EnableTransactionManagementConfiguration {

        // 省略

        @Configuration
        @EnableTransactionManagement(proxyTargetClass = true)
        @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
        public static class CglibAutoProxyConfiguration {

        }

    }

}

這里,我們注意到@EnableTransactionManagement這個注解。熟悉spring的我們都知道,這個意味着開啟事務管理。我們打開這個注解

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

跟其它@Enable ** 形式的注解一樣,通過@Import注解導入了一個類,跟進TransactionManagementConfigurationSelector看看

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

    @Override
    protected String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
            // 默認是proxy
            case PROXY:
                return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
            case ASPECTJ:
                return new String[] {determineTransactionAspectClass()};
            default:
                return null;
        }
    }

    //

}

這里將會導入兩個類AutoProxyRegistrar和ProxyTransactionManagementConfiguration,前者是處理代理,后者是處理事務配置的。上一篇講述aop的時候我們說過,創建代理將會通過AnnotationAwareAspectJAutoProxyCreator來處理,所以這里的AutoProxyRegistrar比AnnotationAwareAspectJAutoProxyCreator的優先級低。

 

ProxyTransactionManagementConfiguration是處理事務配置的,我們跟進它

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

    @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(transactionAttributeSource());
        advisor.setAdvice(transactionInterceptor());
        if (this.enableTx != null) {
            advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
        }
        return advisor;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource();
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionInterceptor transactionInterceptor() {
        TransactionInterceptor interceptor = new TransactionInterceptor();
        interceptor.setTransactionAttributeSource(transactionAttributeSource());
        if (this.txManager != null) {
            interceptor.setTransactionManager(this.txManager);
        }
        return interceptor;
    }

}

正如我們開篇說的,事務是基於aop的,會去生成Advisor。我們看到transactionAdvisor將會返回一個BeanFactoryTransactionAttributeSourceAdvisor。我們看看它的uml類圖

這里就是生成了一個Advisor,並作為Bean存在於BeanFactory當中。

 

增強到Bean

我們打開AbstractAutoProxyCreator的wrapIfNecessary方法

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    //

    // 獲取可以增強到當前Bean的Advisor
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 創建代理
        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;
}

getAdvicesAndAdvisorsForBean將會獲取到事務生成的Advisor,然后createProxy將會進行代理增強,cglib或者jdk動態代理的方式。

 

跟進AbstractAdvisorAutoProxyCreator的findEligibleAdvisors方法

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 找到Bean工廠里所有Advisor
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 獲取可以增強到當前Bean的Advisor    
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

跟進findAdvisorsThatCanApply看看怎么判斷是否可以增強

protected List<Advisor> findAdvisorsThatCanApply(
        List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

    ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    try {
        // 找到可以增強的Advisor
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    }
    finally {
        ProxyCreationContext.setCurrentProxiedBeanName(null);
    }
}

繼續跟進findAdvisorsThatCanApply

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
    //

    List<Advisor> eligibleAdvisors = new ArrayList<>();

    //

    for (Advisor candidate : candidateAdvisors) {
        //
        if (canApply(candidate, clazz, hasIntroductions)) {
            eligibleAdvisors.add(candidate);
        }
    }
    
    return eligibleAdvisors;
}

判斷邏輯落在了canApply方法上,跟進它

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
    if (advisor instanceof IntroductionAdvisor) {
        return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
    }
    // 進入這里分支
    else if (advisor instanceof PointcutAdvisor) {
        PointcutAdvisor pca = (PointcutAdvisor) advisor;
        return canApply(pca.getPointcut(), targetClass, hasIntroductions);
    }
    else {
        return true;
    }
}

這里的canApply將會判斷PointcutAdvisor是否能增強到targetClass上,繼續跟進canApply

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
    //

    MethodMatcher methodMatcher = pc.getMethodMatcher();
    //

    IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
    if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
        introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
    }

    Set<Class<?>> classes = new LinkedHashSet<>();
    if (!Proxy.isProxyClass(targetClass)) {
        classes.add(ClassUtils.getUserClass(targetClass));
    }
    classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

    for (Class<?> clazz : classes) {
        // 獲取所有方法
        Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
        for (Method method : methods) {
            // 判斷是否能夠應用在方法上
            if (introductionAwareMethodMatcher != null ?
                    introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                    methodMatcher.matches(method, targetClass)) {
                return true;
            }
        }
    }

    return false;
}

 

總結

本文簡單過了一下事務的自動配置到代理增強。事務基於自動配置機制和aop,自動配置機制將會生成Advisor,然后通過代理增強到Bean上,從而實現事務的代理增強。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM