• SpringBoot 注解事务声明式事务


      文章来源: http://www.cnblogs.com/guozp/articles/7446477.html 

      springboot 对新人来说可能上手比springmvc要快,但是对于各位从springmvc转战到springboot的话,有些地方还需要适应下,尤其是xml配置。我个人是比较喜欢注解➕xml是因为看着方便,查找方便,清晰明了。但是xml完全可以使用注解代替,今天就扒一扒springboot中事务使用注解的玩法。

      springboot的事务也主要分为两大类,一是xml声明式事务,二是注解事务,注解事务也可以实现类似声明式事务的方法,关于注解声明式事务,目前网上搜索不到合适的资料,所以在这里,我将自己查找和总结的几个方法写到这里,大家共同探讨

        文章来源: http://www.cnblogs.com/guozp/articles/7446477.html 

    • springboot 之 xml事务

          可以使用 @ImportResource("classpath:transaction.xml") 引入该xml的配置,xml的配置如下

      

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd">
            
        <bean id="txManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" ></property>
        </bean>
        <tx:advice id="cftxAdvice" transaction-manager="txManager">
            <tx:attributes>
                <tx:method name="query*" propagation="SUPPORTS" read-only="true" ></tx:method>
                <tx:method name="get*" propagation="SUPPORTS" read-only="true" ></tx:method>
                <tx:method name="select*" propagation="SUPPORTS" read-only="true" ></tx:method>
                <tx:method name="*" propagation="REQUIRED" rollback-for="Exception" ></tx:method>
            </tx:attributes>
        </tx:advice>
         <aop:config>
            <aop:pointcut id="allManagerMethod" expression="execution (* com.exmaple.fm..service.*.*(..))" />
            <aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod" order="0" />
        </aop:config>
    
    </beans>

    springboot 启动类如下:

      

    package com.example.fm;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.ImportResource;
    
    @ImportResource("classpath:transaction.xml")
    @SpringBootApplication
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    
    }
    

      启动后即可开启事务,不过项目里导入了xml配置,如果不想导入xml配置,可以使用注解的方式。

    • springboot 之 注解事务

       注解事务讲解之前,需要先了解下spring创建代理的几个类,在spring内部,是通过BeanPostProcessor来完成自动创建代理工作的。BeanPostProcessor接口的实现只是在ApplicationContext初始化的时候才会自动加载,而普通的BeanFactory只能通过编程的方式调用之。根据  匹配规则的不同大致分为三种类别:

        a、匹配Bean的名称自动创建匹配到的Bean的代理,实现类BeanNameAutoProxyCreator

        

    <bean id="testInterceptor" class="com.example.service.config.testInerceptor”></bean>
    
    <bean id="profileAutoProxyCreator" class="org.springframework.aop.framework.
    autoproxy.BeanNameAutoProxyProxyCreator">
    <bean>
    <property name="beanNames">
    <list>
    <value>*Service</value>
    </list>
    </property>
    <property name="interceptorNames">
    <value> testInterceptor </value>
    </property>
    </bean>

        b、根据Bean中的AspectJ注解自动创建代理,实现类AnnotationAwareAspectJAutoProxyCreator

    <aop:aspectj-autoproxy proxy-target-class="true"/>
    
    <bean id="annotationAwareAspectJAutoProxyCreatorTest" class="com.example.service.AnnotationAwareAspectJAutoProxyCreatorTest"/>
    <aop:config>
        <aop:aspect ref="annotationAwareAspectJAutoProxyCreatorTest">
            <aop:around method="process" pointcut="execution (* com.example.service.fm..*.*(..))"/>
        </aop:aspect>
    </aop:config>

        c、根据Advisor的匹配机制自动创建代理,会对容器中所有的Advisor进行扫描,自动将这些切面应用到匹配的Bean中,实现类DefaultAdvisorAutoProxyCreator

      

      接下来开讲注解开启事务的方法:

           1、Transactional注解事务

       需要在进行事物管理的方法上添加注解@Transactional,或者偷懒的话直接在类上面添加该注解,使得所有的方法都进行事物的管理,但是依然需要在需要事务管理的类上都添加,工作量比较大,这里只是简单说下,具体的可以google或者bing

           2、注解声明式事务

      Component或Configuration中bean的区别,有时间我会专门写一篇来讲解下

      a.方式1,这里使用Component或Configuration事务都可以生效

       

    package com.exmple.service.fm9.config;
    
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.Map;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.springframework.aop.Advisor;
    import org.springframework.aop.aspectj.AspectJExpressionPointcut;
    import org.springframework.aop.support.DefaultPointcutAdvisor;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.stereotype.Component;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.TransactionDefinition;
    import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
    import org.springframework.transaction.interceptor.RollbackRuleAttribute;
    import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
    import org.springframework.transaction.interceptor.TransactionAttribute;
    import org.springframework.transaction.interceptor.TransactionInterceptor;
    
    /**
     * Created by guozp on 2017/8/28.
     */
    @Aspect
    //@Component 事务依然生效
    @Configuration
    public class TxAdviceInterceptor {
    
        private static final int TX_METHOD_TIMEOUT = 5;
        private static final String AOP_POINTCUT_EXPRESSION = "execution (* com.alibaba.fm9..service.*.*(..))";
    
        @Autowired
        private PlatformTransactionManager transactionManager;
    
        @Bean
        public TransactionInterceptor txAdvice() {
            NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
             /*只读事务,不做更新操作*/
            RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
            readOnlyTx.setReadOnly(true);
            readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED );
            /*当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务*/
            RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();
            requiredTx.setRollbackRules(
                Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
            requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
            requiredTx.setTimeout(TX_METHOD_TIMEOUT);
            Map<String, TransactionAttribute> txMap = new HashMap<>();
            txMap.put("add*", requiredTx);
            txMap.put("save*", requiredTx);
            txMap.put("insert*", requiredTx);
            txMap.put("update*", requiredTx);
            txMap.put("delete*", requiredTx);
            txMap.put("get*", readOnlyTx);
            txMap.put("query*", readOnlyTx);
            source.setNameMap( txMap );
            TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, source);
            return txAdvice;
        }
    
        @Bean
        public Advisor txAdviceAdvisor() {
            AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
            pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
            return new DefaultPointcutAdvisor(pointcut, txAdvice());
            //return new DefaultPointcutAdvisor(pointcut, txAdvice);
        }
    }
    

      

     b.方式1,这里使用Component或Configuration事务都可以生效

    package com.exmple.service.fm9.config;
    
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.Map;
    
    import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.stereotype.Component;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.TransactionDefinition;
    import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
    import org.springframework.transaction.interceptor.RollbackRuleAttribute;
    import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
    import org.springframework.transaction.interceptor.TransactionAttribute;
    import org.springframework.transaction.interceptor.TransactionAttributeSource;
    import org.springframework.transaction.interceptor.TransactionInterceptor;
    
    /**
     * Created by guozp on 2017/8/29.
     */
    //@Component 事务依然生效
    @Configuration
    public class TxAnoConfig {
        /*事务拦截类型*/
        @Bean("txSource")
        public TransactionAttributeSource transactionAttributeSource(){
            NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
             /*只读事务,不做更新操作*/
            RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
            readOnlyTx.setReadOnly(true);
            readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED );
            /*当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务*/
            //RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();
            //requiredTx.setRollbackRules(
            //    Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
            //requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
            RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED,
                Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
            requiredTx.setTimeout(5);
            Map<String, TransactionAttribute> txMap = new HashMap<>();
            txMap.put("add*", requiredTx);
            txMap.put("save*", requiredTx);
            txMap.put("insert*", requiredTx);
            txMap.put("update*", requiredTx);
            txMap.put("delete*", requiredTx);
            txMap.put("get*", readOnlyTx);
            txMap.put("query*", readOnlyTx);
            source.setNameMap( txMap );
    
            return source;
        }
    
        /**切面拦截规则 参数会自动从容器中注入*/
        @Bean
        public AspectJExpressionPointcutAdvisor pointcutAdvisor(TransactionInterceptor txInterceptor){
            AspectJExpressionPointcutAdvisor pointcutAdvisor = new AspectJExpressionPointcutAdvisor();
            pointcutAdvisor.setAdvice(txInterceptor);
            pointcutAdvisor.setExpression("execution (* com.alibaba.fm9..service.*.*(..))");
            return pointcutAdvisor;
        }
    
        /*事务拦截器*/
        @Bean("txInterceptor")
        TransactionInterceptor getTransactionInterceptor(PlatformTransactionManager tx){
            return new TransactionInterceptor(tx , transactionAttributeSource()) ;
        }
    }
    

      

     c.方式1,这里使用Component或Configuration事务都可以生效

    package com.exmple.service.fm9.config;
    
    import java.util.Properties;
    
    
    import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    import org.springframework.stereotype.Component;
    import org.springframework.transaction.interceptor.TransactionInterceptor;
    
    /**
     * Created by guozp on 2017/8/28.
     *
     */
    //@Component
    @Configuration
    public class TxConfigBeanName {
    
        @Autowired
        private DataSourceTransactionManager transactionManager;
    
        // 创建事务通知
    
        @Bean(name = "txAdvice")
        public TransactionInterceptor getAdvisor() throws Exception {
    
            Properties properties = new Properties();
            properties.setProperty("get*", "PROPAGATION_REQUIRED,-Exception,readOnly");
            properties.setProperty("add*", "PROPAGATION_REQUIRED,-Exception,readOnly");
            properties.setProperty("save*", "PROPAGATION_REQUIRED,-Exception,readOnly");
            properties.setProperty("update*", "PROPAGATION_REQUIRED,-Exception,readOnly");
            properties.setProperty("delete*", "PROPAGATION_REQUIRED,-Exception,readOnly");
    
            TransactionInterceptor tsi = new TransactionInterceptor(transactionManager,properties);
            return tsi;
    
        }
    
        @Bean
        public BeanNameAutoProxyCreator txProxy() {
            BeanNameAutoProxyCreator creator = new BeanNameAutoProxyCreator();
            creator.setInterceptorNames("txAdvice");
            creator.setBeanNames("*Service", "*ServiceImpl");
            creator.setProxyTargetClass(true);
            return creator;
        }
    }
    

      

     d.方式1,这里使用Component或Configuration并不是所有事务都可以生效,例如Configuration的时候如果打开注释部分的而且不把代码都移动到 defaultPointcutAdvisor(),事物会失效,具体原因暂时不明,如果各位有明白的,可以指点我下。

    初始使用:

    package com.alibaba.fm9.config;
    
    import java.util.Properties;
    
    import javax.sql.DataSource;
    
    import org.springframework.aop.aspectj.AspectJExpressionPointcut;
    import org.springframework.aop.support.DefaultPointcutAdvisor;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    import org.springframework.stereotype.Component;
    import org.springframework.transaction.interceptor.TransactionInterceptor;
    
    /**
     * Created by guozp on 2017/8/28.  ??
     */
    @Component
    //@Configuration  事务失败
    public class TxOtherConfigDefault {
    
       @Autowired
        private DataSource dataSource;
    
        //@Bean
        //@ConditionalOnMissingBean
        public PlatformTransactionManager annotationDrivenTransactionManager() {
            return new DataSourceTransactionManager(dataSource);
        }*/
    
       @Autowired
       private DataSourceTransactionManager transactionManager;
    
    
        @Bean
        public TransactionInterceptor transactionInterceptor() {
            Properties attributes = new Properties();
            attributes.setProperty("get*", "PROPAGATION_REQUIRED");
            attributes.setProperty("add*", "PROPAGATION_REQUIRED");
            attributes.setProperty("update*", "PROPAGATION_REQUIRED");
            attributes.setProperty("delete*", "PROPAGATION_REQUIRED");
            TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, attributes);
            return txAdvice;
        }
    
    
        @Bean
        public AspectJExpressionPointcut aspectJExpressionPointcut(){
            AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
            String transactionExecution = "execution (* com.alibaba.fm9..service.*.*(..))";
            pointcut.setExpression(transactionExecution);
            return pointcut;
        }
    
        @Bean
        public DefaultPointcutAdvisor defaultPointcutAdvisor(){
            DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
            advisor.setPointcut(aspectJExpressionPointcut());
            advisor.setAdvice(transactionInterceptor());
            return advisor;
        }
    }
    

      

    后修改如下:

    ackage com.alibaba.fm9.config;
    
    import java.util.Properties;
    
    import javax.sql.DataSource;
    
    import org.springframework.aop.aspectj.AspectJExpressionPointcut;
    import org.springframework.aop.support.DefaultPointcutAdvisor;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    import org.springframework.stereotype.Component;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.interceptor.TransactionInterceptor;
    
    /**
     * Created by guozp on 2017/8/28.
     *                       ???????
     */
    @Configuration //事务失效,都移动到一个方法不失效
    //@Component // 事务可行,不用都移动到一个方法
    public class TxOtherConfigDefaultBean {
    
        public static final String transactionExecution = "execution (* com.alibaba.fm9..service.*.*(..))";
    
        @Autowired
        private PlatformTransactionManager transactionManager;
    
        //@Bean
        //@ConditionalOnMissingBean
        //public PlatformTransactionManager transactionManager() {
        //    return new DataSourceTransactionManager(dataSource);
        //}
    
    
        @Bean
        public TransactionInterceptor transactionInterceptor() {
            Properties attributes = new Properties();
            attributes.setProperty("get*", "PROPAGATION_REQUIRED,-Exception");
            attributes.setProperty("add*", "PROPAGATION_REQUIRED,-Exception");
            attributes.setProperty("update*", "PROPAGATION_REQUIRED,-Exception");
            attributes.setProperty("delete*", "PROPAGATION_REQUIRED,-Exception");
            //TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager(), attributes);
            TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, attributes);
            return txAdvice;
        }
    
    
        //@Bean
        //public AspectJExpressionPointcut aspectJExpressionPointcut(){
        //    AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        //    pointcut.setExpression(transactionExecution);
        //    return pointcut;
        //}
    
        @Bean
        public DefaultPointcutAdvisor defaultPointcutAdvisor(){
            //AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
            //pointcut.setExpression(transactionExecution);
            //DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
            //advisor.setPointcut(pointcut);
            //advisor.setAdvice(transactionInterceptor());
            AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
            pointcut.setExpression(transactionExecution);
            DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
            advisor.setPointcut(pointcut);
            Properties attributes = new Properties();
            attributes.setProperty("get*", "PROPAGATION_REQUIRED,-Exception");
            attributes.setProperty("add*", "PROPAGATION_REQUIRED,-Exception");
            attributes.setProperty("update*", "PROPAGATION_REQUIRED,-Exception");
            attributes.setProperty("delete*", "PROPAGATION_REQUIRED,-Exception");
            TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, attributes);
            advisor.setAdvice(txAdvice);
            return advisor;
        }
    }
    

        

      简单来说,springboot使用上述注解的几种方式开启事物,可以达到和xml中声明的同样效果,但是却告别了xml,使你的代码远离配置文件。

        如果有错误的地方,望各位指正。如有其它问题,可以联系

       文章来源: http://www.cnblogs.com/guozp/articles/7446477.html 

      

  • 相关阅读:
    如何在Google Map中处理大量标记(ASP.NET)(转)
    MapXtreme在asp.net中的使用之加载地图(转)
    Oracle数据类型与.NET中的对应关系(转)
    GIS-开发例程、源代码、MapXtreme、Map (转)
    Win7 64位系统上配置使用32位的Eclipse(转)
    视频会议十大开源项目排行(转)
    RTMP流媒体播放过程(转)
    python中如何将生成等差数列和等比数列
    python中type dtype astype 的用法
    python类库numpy中常见函数的用法
  • 原文地址:https://www.cnblogs.com/guozp/p/7446477.html
Copyright © 2020-2023  润新知