springboot 對新人來說可能上手比springmvc要快,但是對于各位從springmvc轉戰到springboot的話,有些地方還需要適應下,尤其是xml配置。我個人是比較喜歡注解?xml是因為看著方便,查找方便,清晰明了。但是xml完全可以使用注解代替,今天就扒一扒springboot中事務使用注解的玩法。
springboot的事務也主要分為兩大類,一是xml聲明式事務,二是注解事務,注解事務也可以實現類似聲明式事務的方法,關于注解聲明式事務,目前網上搜索不到合適的資料,所以在這里,我將自己查找和總結的幾個方法寫到這里,大家共同探討
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" ?> <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 啟動類如下:
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
接下來開講注解開啟事務的方法:
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 注解事務聲明式事務的方式,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
原文鏈接:http://www.cnblogs.com/guozp/p/7446477.html