SpringBoot 声明式事务

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/caox_90/article/details/79708034

springboot的事务也主要分为两大类,一是xml声明式事务,二是注解事务.

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version= "1.0" encoding= "UTF-8" ?>
   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 启动类如下:

?
1
2
3
4
5
6
7
8
9
10
11
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
<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

?
1
2
3
4
5
6
7
<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

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

扫描二维码关注公众号,回复: 5616511 查看本文章

       1、Transactional注解事务

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

       2、注解声明式事务

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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事务都可以生效

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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事务都可以生效

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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(),事物会失效,具体原因暂时不明,如果各位有明白的,可以指点我下。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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,使你的代码远离配置文件。

总结

以上所述是小编给大家介绍的SpringBoot 注解事务声明式事务的方式,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!


猜你喜欢

转载自blog.csdn.net/caox_90/article/details/79708034