SpringBoot 註解事務聲明式事務

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

  springboot 對新人來講可能上手比springmvc要快,可是對於各位從springmvc轉戰到springboot的話,有些地方還須要適應下,尤爲是xml配置。我我的是比較喜歡註解➕xml是由於看着方便,查找方便,清晰明瞭。可是xml徹底能夠使用註解代替,今天就扒一扒springboot中事務使用註解的玩法。java

  springboot的事務也主要分爲兩大類,一是xml聲明式事務,二是註解事務,註解事務也能夠實現相似聲明式事務的方法,關於註解聲明式事務,目前網上搜索不到合適的資料,因此在這裏,我將本身查找和總結的幾個方法寫到這裏,你們共同探討spring

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

  • springboot 之 xml事務

      能夠使用 @ImportResource("classpath:transaction.xml") 引入該xml的配置,xml的配置以下express

  

<?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

  • springboot 之 註解事務

   註解事務講解以前,須要先了解下spring建立代理的幾個類,在spring內部,是經過BeanPostProcessor來完成自動建立代理工做的。BeanPostProcessor接口的實現只是在ApplicationContext初始化的時候纔會自動加載,而普通的BeanFactory只能經過編程的方式調用之。根據  匹配規則的不一樣大體分爲三種類別:mvc

    a、匹配Bean的名稱自動建立匹配到的Bean的代理,實現類BeanNameAutoProxyCreatorui

    

<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註解自動建立代理,實現類AnnotationAwareAspectJAutoProxyCreatorgoogle

<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

  

  接下來開講註解開啓事務的方法:

       一、Transactional註解事務

   須要在進行事物管理的方法上添加註解@Transactional,或者偷懶的話直接在類上面添加該註解,使得全部的方法都進行事物的管理,可是依然須要在須要事務管理的類上都添加,工做量比較大,這裏只是簡單說下,具體的能夠google或者bing

       二、註解聲明式事務

  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 

相關文章
相關標籤/搜索