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

全部文章

http://www.javashuo.com/article/p-uvudtich-bm.htmlhtml

 

正文

上一篇文章中,咱們簡單瞭解了aop的處理過程。代理加強以前,先生成Advisor,而後利用cglib或者jdk動態代理把能夠應用到當前Bean的Advisor加強到Bean上。spring

springboot的事務,也是基於aop實現。那麼咱們就須要把事務相關的配置生成Advisor,而後同樣地加強到Bean上。springboot

 

生成Advisor

首先,咱們先找到事務的自動配置類TransactionAutoConfigurationide

@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的咱們都知道,這個意味着開啓事務管理。咱們打開這個註解this

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

跟其它@Enable ** 形式的註解同樣,經過@Import註解導入了一個類,跟進TransactionManagementConfigurationSelector看看spa

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的優先級低。3d

 

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類圖code

這裏就是生成了一個Advisor,並做爲Bean存在於BeanFactory當中。orm

 

加強到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上,從而實現事務的代理加強。

相關文章
相關標籤/搜索