成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Spring源碼分析:聲明式事務(wù)梳理

liaosilzu2007 / 1023人閱讀

摘要:使用注解方式簡單模擬事務(wù)樣例說明數(shù)據(jù)源采用采用持久化采用事務(wù)注解環(huán)境搭建依賴提供的模塊鏈接驅(qū)動包配置類聲明式事務(wù)配置類,其中一定要開啟。

使用注解方式簡單模擬事務(wù)
樣例 說明

數(shù)據(jù)源采用c3p0

采用JdbcTemplate持久化

采用Spring事務(wù)注解

環(huán)境搭建 POM依賴

    c3p0
    c3p0
    0.9.1.2



    org.springframework
    spring-jdbc
    4.3.12.RELEASE



    mysql
    mysql-connector-java
    5.1.44
    runtime



    org.springframework
    spring-aspects
    4.3.12.RELEASE
配置類
/**
 * description:聲明式事務(wù)配置類,其中@EnableTransactionManagement
 * 一定要開啟。
 * @author 70KG
 */
@Configuration
@ComponentScan("com.nmys.story.springCore.springaop.tx_sample")
@EnableTransactionManagement // -- 開啟基于注解的事務(wù)管理
public class TxConfig {

    // -- 配置數(shù)據(jù)源
    @Bean
    public DataSource dataSource() throws Exception {
        ComboPooledDataSource pool = new ComboPooledDataSource();
        pool.setUser("root");
        pool.setPassword("root");
        pool.setDriverClass("com.mysql.jdbc.Driver");
        pool.setJdbcUrl("jdbc:mysql://localhost:3306/usthe?useSSL=false");
        return pool;
    }

    // -- 加入模板
    @Bean
    public JdbcTemplate jdbcTemplate() throws Exception {
        JdbcTemplate template = new JdbcTemplate(dataSource());
        return template;
    }

    // -- 配置事務(wù)管理器,它才是用來提交回滾事務(wù)的主導(dǎo)者
    @Bean
    public DataSourceTransactionManager txManager() throws Exception {
        DataSourceTransactionManager tx = new DataSourceTransactionManager(dataSource());
        return tx;
    }

}
業(yè)務(wù)類
/**
 * description
 * @author 70KG
 */
@Service
public class TxService {

    @Autowired
    private TxDao txDao;

    public void insertLog(){
        txDao.insertSth();
    }

}

/**
 * description
 * @author 70KG
 */
@Repository
public class TxDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    // @Transactional僅表明它是一個事務(wù)方法,開啟事務(wù)僅有注解是不夠的,還需要配置事務(wù)管理器
    @Transactional
    public void insertSth() {
        String sql = "INSERT into sys_log (username) VALUES(?);";
        jdbcTemplate.update(sql, "lisi");
        System.out.println("------>插入成功");
        int i = 10/0;
    }
}
測試類
/**
 * description
 * @author 70KG
 */
public class Test01 {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(TxConfig.class);
        TxService bean = app.getBean(TxService.class);
        bean.insertLog();
    }

}
測試結(jié)果

測試結(jié)果肯定是能正常運(yùn)行的,下面試著跟一下源碼。

源碼分析

當(dāng)容器開始啟動運(yùn)行的時(shí)候就會找到@EnableTransactionManagement注解

進(jìn)入注解,發(fā)現(xiàn)它使用@Import(TransactionManagementConfigurationSelector.class)向容器中注入了這個類

跟進(jìn)TransactionManagementConfigurationSelector,發(fā)現(xiàn)它最終實(shí)現(xiàn)的是ImportSelector接口,這個接口可以向IOC容器中以Bean的全類名的方式注入Bean。

源碼如下,AdviceMode在注解@EnableTransactionManagement默認(rèn)就是PROXY,可見它向容器中注入了兩個類,分別是AutoProxyRegistrar和ProxyTransactionManagementConfiguration。

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector {
    @Override
    protected String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
            case PROXY:
                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翻譯過來:自動代理注冊器。進(jìn)入AutoProxyRegistrar類,截取部分源碼,如下:

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    boolean candidateFound = false;
    Set annoTypes = importingClassMetadata.getAnnotationTypes();
    for (String annoType : annoTypes) {
        AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
        if (candidate == null) {
            continue;
        }
        Object mode = candidate.get("mode");
        Object proxyTargetClass = candidate.get("proxyTargetClass");
        if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
                Boolean.class == proxyTargetClass.getClass()) {
            candidateFound = true;
            if (mode == AdviceMode.PROXY) {
                // -- 前面的代碼主要是獲取注解類型,注解信息等等。
                // -- 主要是這個地方,如果必要的話,就向容器中注冊一個自動代理創(chuàng)建器。
                AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                if ((Boolean) proxyTargetClass) {
                    AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                    return;
                }
            }
        }
    }
    ...........

進(jìn)入registerAutoProxyCreatorIfNecessary(registry),AopConfigUtils類中,源碼如下:

@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class cls, BeanDefinitionRegistry registry,
        @Nullable Object source) {
    // -- 斷言
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    // 先判斷有沒有org.springframework.aop.config.internalAutoProxyCreator
    // 首次進(jìn)來,肯定沒有
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        return null;
    }
    // -- 將cls也就是InfrastructureAdvisorAutoProxyCreator包裝成RootBeanDefinition
    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    // -- 將beanDefinition注冊到IOC容器中,Bean的
    // -- 名字就叫org.springframework.aop.config.internalAutoProxyCreator
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

向容器中注入了InfrastructureAdvisorAutoProxyCreator,進(jìn)入此類,發(fā)現(xiàn)父類是AbstractAdvisorAutoProxyCreator,AbstractAdvisorAutoProxyCreator的父類是AbstractAutoProxyCreator,AbstractAutoProxyCreator中的方法,創(chuàng)建并返回了代理類,如下:

/**
 * Create a proxy with the configured interceptors if the bean is
 * identified as one to proxy by the subclass.
 * @see #getAdvicesAndAdvisorsForBean
 */
@Override
public Object postProcessAfterInitialization(@Nullable 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;
}

給容器中注入InfrastructureAdvisorAutoProxyCreator的主要作用就是,利用后置處理器機(jī)制在對象創(chuàng)建以后,對對象進(jìn)行包裝,返回一個代理對象(增強(qiáng)器),代理對象執(zhí)行方法,利用攔截器鏈進(jìn)行調(diào)用。

ProxyTransactionManagementConfiguration

進(jìn)入ProxyTransactionManagementConfiguration,部分源碼如下:

// -- 向容器中注入名字為TRANSACTION_ADVISOR_BEAN_NAME的切面
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
    BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        // -- 向切面中注入注解解析器,專門來解析事務(wù)注解的
    advisor.setTransactionAttributeSource(transactionAttributeSource());
        // -- 向切面中注入事務(wù)的攔截器,專門來攔截方法,包括事務(wù)的提交以及回滾操作
    advisor.setAdvice(transactionInterceptor());
    if (this.enableTx != null) {
        advisor.setOrder(this.enableTx.getNumber("order"));
    }
    return advisor;
}

進(jìn)入transactionAttributeSource()注解解析器,源碼如下:

public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
    this.publicMethodsOnly = publicMethodsOnly;
    this.annotationParsers = new LinkedHashSet<>(2);
        // -- Spring注解的解析器
    this.annotationParsers.add(new SpringTransactionAnnotationParser());
    if (jta12Present) {
                // -- jta的解析器
        this.annotationParsers.add(new JtaTransactionAnnotationParser());
    }
    if (ejb3Present) {
                // -- ejb的解析器
        this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
    }
}

進(jìn)入SpringTransactionAnnotationParser(),部分源碼如下:

protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
    RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
    Propagation propagation = attributes.getEnum("propagation");
    rbta.setPropagationBehavior(propagation.value());
    Isolation isolation = attributes.getEnum("isolation");
    rbta.setIsolationLevel(isolation.value());
    rbta.setTimeout(attributes.getNumber("timeout").intValue());
    rbta.setReadOnly(attributes.getBoolean("readOnly"));
    rbta.setQualifier(attributes.getString("value"));
    ArrayList rollBackRules = new ArrayList<>();
    Class[] rbf = attributes.getClassArray("rollbackFor");
    for (Class rbRule : rbf) {

會發(fā)現(xiàn)@Transactional中的各種屬性都在這里,這樣,注解解析器就分析完了

再來看事務(wù)的攔截器,分析事務(wù)是如何回滾和提交的,進(jìn)入transactionInterceptor()

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor() {
        // -- 事務(wù)的攔截器
    TransactionInterceptor interceptor = new TransactionInterceptor();
    interceptor.setTransactionAttributeSource(transactionAttributeSource());
    if (this.txManager != null) {
                // -- 將事務(wù)管理器設(shè)置進(jìn)去,為了事務(wù)的提交和回滾操作
        interceptor.setTransactionManager(this.txManager);
    }
    return interceptor;
}

TransactionInterceptor 是一個實(shí)現(xiàn)了MethodInterceptor接口的類,標(biāo)志著TransactionInterceptor是一個方法攔截器,進(jìn)入它的invoke()方法

@Override
@Nullable
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, invocation::proceed);
}

進(jìn)入invokeWithinTransaction()

@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class targetClass,
        final InvocationCallback invocation) throws Throwable {
    // If the transaction attribute is null, the method is non-transactional.
    TransactionAttributeSource tas = getTransactionAttributeSource();
        // -- 拿到事務(wù)注解信息包括事務(wù)的qualifier和rollback信息
    final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
        // -- 獲取事務(wù)管理器
    final PlatformTransactionManager tm = determineTransactionManager(txAttr);
        // -- 事務(wù)連接點(diǎn)的定義信息
    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
    if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
        // 創(chuàng)建并開啟事務(wù)
        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.
                        // -- 調(diào)用目標(biāo)方法
            retVal = invocation.proceedWithInvocation();
        }
        catch (Throwable ex) {
            // target invocation exception
                        // -- 出現(xiàn)異常了,獲取事務(wù)管理器,進(jìn)行事務(wù)的回滾
            completeTransactionAfterThrowing(txInfo, ex);
            throw ex;
        }
        finally {
            cleanupTransactionInfo(txInfo);
        }
                // -- 未出現(xiàn)異常,也獲取事務(wù)管理器則進(jìn)行事務(wù)的提交
        commitTransactionAfterReturning(txInfo);
        return retVal;
    }
    .........
總結(jié)
Spring事務(wù)源碼梳理

通過注解@EnableTransactionManagement中的@Import(TransactionManagementConfigurationSelector.class)給容器中導(dǎo)入了兩個組件,分別是:AutoProxyRegistrar和ProxyTransactionManagementConfiguration

AutoProxyRegistrar:它是一個后置處理器,給容器中注冊一個InfrastructureAdvisorAutoProxyCreator,InfrastructureAdvisorAutoProxyCreator利用后置處理器機(jī)制在對象創(chuàng)建以后,對對象進(jìn)行包裝,返回一個代理對象(增強(qiáng)器),代理對象執(zhí)行方法,利用攔截器鏈進(jìn)行調(diào)用。

ProxyTransactionManagementConfiguration:給容器中注冊事務(wù)增強(qiáng)器

事務(wù)增強(qiáng)器要用事務(wù)注解信息:AnnotationTransactionAttributeSource來解析事務(wù)注解

事務(wù)攔截器中:transactionInterceptor(),它是一個TransactionInterceptor(保存了事務(wù)屬性信息和事務(wù)管理器),而TransactionInterceptor是一個MethodInterceptor,在目標(biāo)方法執(zhí)行的時(shí)候,執(zhí)行攔截器鏈,事務(wù)攔截器(首先獲取事務(wù)相關(guān)的屬性,再獲取PlatformTransactionManager,如果沒有指定任何transactionManager,最終會從容器中按照類型獲取一個PlatformTransactionManager,最后執(zhí)行目標(biāo)方法,如果異常,便獲取到事務(wù)管理器進(jìn)行回滾,如果正常,同樣拿到事務(wù)管理器提交事務(wù)。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/73200.html

相關(guān)文章

  • Spring知識——事務(wù)解析

    摘要:編程式事務(wù)指的是通過編碼方式實(shí)現(xiàn)事務(wù)聲明式事務(wù)基于將具體業(yè)務(wù)邏輯與事務(wù)處理解耦。聲明式事務(wù)管理使業(yè)務(wù)代碼邏輯不受污染因此在實(shí)際使用中聲明式事務(wù)用的比較多。聲明式事務(wù)有兩種方式,一種是在配置文件中做相關(guān)的事務(wù)規(guī)則聲明,另一種是基于注解的方式。 事務(wù)管理是應(yīng)用系統(tǒng)開發(fā)中必不可少的一部分。Spring 為事務(wù)管理提供了豐富的功能支持。Spring 事務(wù)管理分為編碼式和聲明式的兩種方式。編程式...

    tuomao 評論0 收藏0
  • 慕課網(wǎng)_《Spring事務(wù)管理》學(xué)習(xí)總結(jié)

    摘要:事務(wù)管理學(xué)習(xí)總結(jié)時(shí)間年月日星期二說明本文部分內(nèi)容均來自慕課網(wǎng)。一致性一致性指事務(wù)前后數(shù)據(jù)的完整性必須保持一致。聲明式事務(wù)管理基于的方式很少使用需要為每個進(jìn)行事務(wù)管理的類,配置一個進(jìn)行增強(qiáng)。 《Spring事務(wù)管理》學(xué)習(xí)總結(jié) 時(shí)間:2017年2月7日星期二說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com/教學(xué)示例源碼:https://github.com...

    Airy 評論0 收藏0
  • Spring聲明事務(wù)管理之二:核心接口API

    摘要:事務(wù)管理結(jié)構(gòu)事務(wù)管理有個左右,其中最核心的有個,分別是。事務(wù)管理主要結(jié)構(gòu)如下三個核心接口源碼解析接口是用于定義一個事務(wù),它定義了事務(wù)管理的五大屬性,在上一篇文章中有詳細(xì)介紹。只需要裝配一個實(shí)體管理工廠接口的任意實(shí)現(xiàn)。 1.Spring事務(wù)管理API結(jié)構(gòu) ??Spring事務(wù)管理API有100個左右,其中最核心的API有3個,分別是TransactionDefinition、 ??Pla...

    lykops 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<