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的配置如下
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="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">
<beanid="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<propertyname="dataSource"ref="dataSource"></property>
</bean>
<tx:adviceid="cftxAdvice"transaction-manager="txManager">
<tx:attributes>
<tx:methodname="query*"propagation="SUPPORTS"read-only="true"></tx:method>
<tx:methodname="get*"propagation="SUPPORTS"read-only="true"></tx:method>
<tx:methodname="select*"propagation="SUPPORTS"read-only="true"></tx:method>
<tx:methodname="*"propagation="REQUIRED"rollback-for="Exception"></tx:method>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcutid="allManagerMethod"expression="execution(*com.exmaple.fm..service.*.*(..))"/>
<aop:advisoradvice-ref="txAdvice"pointcut-ref="allManagerMethod"order="0"/>
</aop:config>
</beans>
springboot启动类如下:
packagecom.example.fm;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importorg.springframework.context.annotation.ImportResource;
@ImportResource("classpath:transaction.xml")
@SpringBootApplication
publicclassApplication{
publicstaticvoidmain(String[]args){
SpringApplication.run(Application.class,args);
}
}
启动后即可开启事务,不过项目里导入了xml配置,如果不想导入xml配置,可以使用注解的方式。
- springboot之注解事务
注解事务讲解之前,需要先了解下spring创建代理的几个类,在spring内部,是通过BeanPostProcessor来完成自动创建代理工作的。BeanPostProcessor接口的实现只是在ApplicationContext初始化的时候才会自动加载,而普通的BeanFactory只能通过编程的方式调用之。根据匹配规则的不同大致分为三种类别:
a、匹配Bean的名称自动创建匹配到的Bean的代理,实现类BeanNameAutoProxyCreator
<beanid="testInterceptor"class="com.example.service.config.testInerceptor”></bean>
<beanid="profileAutoProxyCreator"class="org.springframework.aop.framework.
autoproxy.BeanNameAutoProxyProxyCreator">
<bean>
<propertyname="beanNames">
<list>
<value>*Service</value>
</list>
</property>
<propertyname="interceptorNames">
<value>testInterceptor</value>
</property>
</bean>
b、根据Bean中的AspectJ注解自动创建代理,实现类AnnotationAwareAspectJAutoProxyCreator
<aop:aspectj-autoproxyproxy-target-class="true"/>
<beanid="annotationAwareAspectJAutoProxyCreatorTest"class="com.example.service.AnnotationAwareAspectJAutoProxyCreatorTest"/>
<aop:config>
<aop:aspectref="annotationAwareAspectJAutoProxyCreatorTest">
<aop:aroundmethod="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事务都可以生效
packagecom.exmple.service.fm9.config;
importjava.util.Collections;
importjava.util.HashMap;
importjava.util.Map;
importorg.aspectj.lang.annotation.Aspect;
importorg.springframework.aop.Advisor;
importorg.springframework.aop.aspectj.AspectJExpressionPointcut;
importorg.springframework.aop.support.DefaultPointcutAdvisor;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.stereotype.Component;
importorg.springframework.transaction.PlatformTransactionManager;
importorg.springframework.transaction.TransactionDefinition;
importorg.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
importorg.springframework.transaction.interceptor.RollbackRuleAttribute;
importorg.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
importorg.springframework.transaction.interceptor.TransactionAttribute;
importorg.springframework.transaction.interceptor.TransactionInterceptor;
/**
*Createdbyguozpon2017/8/28.
*/
@Aspect
//@Component事务依然生效
@Configuration
publicclassTxAdviceInterceptor{
privatestaticfinalintTX_METHOD_TIMEOUT=5;
privatestaticfinalStringAOP_POINTCUT_EXPRESSION="execution(*com.alibaba.fm9..service.*.*(..))";
@Autowired
privatePlatformTransactionManagertransactionManager;
@Bean
publicTransactionInterceptortxAdvice(){
NameMatchTransactionAttributeSourcesource=newNameMatchTransactionAttributeSource();
/*只读事务,不做更新操作*/
RuleBasedTransactionAttributereadOnlyTx=newRuleBasedTransactionAttribute();
readOnlyTx.setReadOnly(true);
readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
/*当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务*/
RuleBasedTransactionAttributerequiredTx=newRuleBasedTransactionAttribute();
requiredTx.setRollbackRules(
Collections.singletonList(newRollbackRuleAttribute(Exception.class)));
requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
requiredTx.setTimeout(TX_METHOD_TIMEOUT);
Map<String,TransactionAttribute>txMap=newHashMap<>();
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);
TransactionInterceptortxAdvice=newTransactionInterceptor(transactionManager,source);
returntxAdvice;
}
@Bean
publicAdvisortxAdviceAdvisor(){
AspectJExpressionPointcutpointcut=newAspectJExpressionPointcut();
pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
returnnewDefaultPointcutAdvisor(pointcut,txAdvice());
//returnnewDefaultPointcutAdvisor(pointcut,txAdvice);
}
}
b.方式1,这里使用Component或Configuration事务都可以生效
packagecom.exmple.service.fm9.config;
importjava.util.Collections;
importjava.util.HashMap;
importjava.util.Map;
importorg.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.stereotype.Component;
importorg.springframework.transaction.PlatformTransactionManager;
importorg.springframework.transaction.TransactionDefinition;
importorg.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
importorg.springframework.transaction.interceptor.RollbackRuleAttribute;
importorg.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
importorg.springframework.transaction.interceptor.TransactionAttribute;
importorg.springframework.transaction.interceptor.TransactionAttributeSource;
importorg.springframework.transaction.interceptor.TransactionInterceptor;
/**
*Createdbyguozpon2017/8/29.
*/
//@Component事务依然生效
@Configuration
publicclassTxAnoConfig{
/*事务拦截类型*/
@Bean("txSource")
publicTransactionAttributeSourcetransactionAttributeSource(){
NameMatchTransactionAttributeSourcesource=newNameMatchTransactionAttributeSource();
/*只读事务,不做更新操作*/
RuleBasedTransactionAttributereadOnlyTx=newRuleBasedTransactionAttribute();
readOnlyTx.setReadOnly(true);
readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
/*当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务*/
//RuleBasedTransactionAttributerequiredTx=newRuleBasedTransactionAttribute();
//requiredTx.setRollbackRules(
//Collections.singletonList(newRollbackRuleAttribute(Exception.class)));
//requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
RuleBasedTransactionAttributerequiredTx=newRuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED,
Collections.singletonList(newRollbackRuleAttribute(Exception.class)));
requiredTx.setTimeout(5);
Map<String,TransactionAttribute>txMap=newHashMap<>();
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);
returnsource;
}
/**切面拦截规则参数会自动从容器中注入*/
@Bean
publicAspectJExpressionPointcutAdvisorpointcutAdvisor(TransactionInterceptortxInterceptor){
AspectJExpressionPointcutAdvisorpointcutAdvisor=newAspectJExpressionPointcutAdvisor();
pointcutAdvisor.setAdvice(txInterceptor);
pointcutAdvisor.setExpression("execution(*com.alibaba.fm9..service.*.*(..))");
returnpointcutAdvisor;
}
/*事务拦截器*/
@Bean("txInterceptor")
TransactionInterceptorgetTransactionInterceptor(PlatformTransactionManagertx){
returnnewTransactionInterceptor(tx,transactionAttributeSource());
}
}
c.方式1,这里使用Component或Configuration事务都可以生效
packagecom.exmple.service.fm9.config;
importjava.util.Properties;
importorg.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.jdbc.datasource.DataSourceTransactionManager;
importorg.springframework.stereotype.Component;
importorg.springframework.transaction.interceptor.TransactionInterceptor;
/**
*Createdbyguozpon2017/8/28.
*
*/
//@Component
@Configuration
publicclassTxConfigBeanName{
@Autowired
privateDataSourceTransactionManagertransactionManager;
//创建事务通知
@Bean(name="txAdvice")
publicTransactionInterceptorgetAdvisor()throwsException{
Propertiesproperties=newProperties();
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");
TransactionInterceptortsi=newTransactionInterceptor(transactionManager,properties);
returntsi;
}
@Bean
publicBeanNameAutoProxyCreatortxProxy(){
BeanNameAutoProxyCreatorcreator=newBeanNameAutoProxyCreator();
creator.setInterceptorNames("txAdvice");
creator.setBeanNames("*Service","*ServiceImpl");
creator.setProxyTargetClass(true);
returncreator;
}
}
d.方式1,这里使用Component或Configuration并不是所有事务都可以生效,例如Configuration的时候如果打开注释部分的而且不把代码都移动到defaultPointcutAdvisor(),事物会失效,具体原因暂时不明,如果各位有明白的,可以指点我下。
初始使用:
packagecom.alibaba.fm9.config;
importjava.util.Properties;
importjavax.sql.DataSource;
importorg.springframework.aop.aspectj.AspectJExpressionPointcut;
importorg.springframework.aop.support.DefaultPointcutAdvisor;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.jdbc.datasource.DataSourceTransactionManager;
importorg.springframework.stereotype.Component;
importorg.springframework.transaction.interceptor.TransactionInterceptor;
/**
*Createdbyguozpon2017/8/28.??
*/
@Component
//@Configuration事务失败
publicclassTxOtherConfigDefault{
@Autowired
privateDataSourcedataSource;
//@Bean
//@ConditionalOnMissingBean
publicPlatformTransactionManagerannotationDrivenTransactionManager(){
returnnewDataSourceTransactionManager(dataSource);
}*/
@Autowired
privateDataSourceTransactionManagertransactionManager;
@Bean
publicTransactionInterceptortransactionInterceptor(){
Propertiesattributes=newProperties();
attributes.setProperty("get*","PROPAGATION_REQUIRED");
attributes.setProperty("add*","PROPAGATION_REQUIRED");
attributes.setProperty("update*","PROPAGATION_REQUIRED");
attributes.setProperty("delete*","PROPAGATION_REQUIRED");
TransactionInterceptortxAdvice=newTransactionInterceptor(transactionManager,attributes);
returntxAdvice;
}
@Bean
publicAspectJExpressionPointcutaspectJExpressionPointcut(){
AspectJExpressionPointcutpointcut=newAspectJExpressionPointcut();
StringtransactionExecution="execution(*com.alibaba.fm9..service.*.*(..))";
pointcut.setExpression(transactionExecution);
returnpointcut;
}
@Bean
publicDefaultPointcutAdvisordefaultPointcutAdvisor(){
DefaultPointcutAdvisoradvisor=newDefaultPointcutAdvisor();
advisor.setPointcut(aspectJExpressionPointcut());
advisor.setAdvice(transactionInterceptor());
returnadvisor;
}
}
后修改如下:
ackagecom.alibaba.fm9.config;
importjava.util.Properties;
importjavax.sql.DataSource;
importorg.springframework.aop.aspectj.AspectJExpressionPointcut;
importorg.springframework.aop.support.DefaultPointcutAdvisor;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.jdbc.datasource.DataSourceTransactionManager;
importorg.springframework.stereotype.Component;
importorg.springframework.transaction.PlatformTransactionManager;
importorg.springframework.transaction.interceptor.TransactionInterceptor;
/**
*Createdbyguozpon2017/8/28.
*???????
*/
@Configuration//事务失效,都移动到一个方法不失效
//@Component//事务可行,不用都移动到一个方法
publicclassTxOtherConfigDefaultBean{
publicstaticfinalStringtransactionExecution="execution(*com.alibaba.fm9..service.*.*(..))";
@Autowired
privatePlatformTransactionManagertransactionManager;
//@Bean
//@ConditionalOnMissingBean
//publicPlatformTransactionManagertransactionManager(){
//returnnewDataSourceTransactionManager(dataSource);
//}
@Bean
publicTransactionInterceptortransactionInterceptor(){
Propertiesattributes=newProperties();
attributes.setProperty("get*","PROPAGATION_REQUIRED,-Exception");
attributes.setProperty("add*","PROPAGATION_REQUIRED,-Exception");
attributes.setProperty("update*","PROPAGATION_REQUIRED,-Exception");
attributes.setProperty("delete*","PROPAGATION_REQUIRED,-Exception");
//TransactionInterceptortxAdvice=newTransactionInterceptor(transactionManager(),attributes);
TransactionInterceptortxAdvice=newTransactionInterceptor(transactionManager,attributes);
returntxAdvice;
}
//@Bean
//publicAspectJExpressionPointcutaspectJExpressionPointcut(){
//AspectJExpressionPointcutpointcut=newAspectJExpressionPointcut();
//pointcut.setExpression(transactionExecution);
//returnpointcut;
//}
@Bean
publicDefaultPointcutAdvisordefaultPointcutAdvisor(){
//AspectJExpressionPointcutpointcut=newAspectJExpressionPointcut();
//pointcut.setExpression(transactionExecution);
//DefaultPointcutAdvisoradvisor=newDefaultPointcutAdvisor();
//advisor.setPointcut(pointcut);
//advisor.setAdvice(transactionInterceptor());
AspectJExpressionPointcutpointcut=newAspectJExpressionPointcut();
pointcut.setExpression(transactionExecution);
DefaultPointcutAdvisoradvisor=newDefaultPointcutAdvisor();
advisor.setPointcut(pointcut);
Propertiesattributes=newProperties();
attributes.setProperty("get*","PROPAGATION_REQUIRED,-Exception");
attributes.setProperty("add*","PROPAGATION_REQUIRED,-Exception");
attributes.setProperty("update*","PROPAGATION_REQUIRED,-Exception");
attributes.setProperty("delete*","PROPAGATION_REQUIRED,-Exception");
TransactionInterceptortxAdvice=newTransactionInterceptor(transactionManager,attributes);
advisor.setAdvice(txAdvice);
returnadvisor;
}
}
简单来说,springboot使用上述注解的几种方式开启事物,可以达到和xml中声明的同样效果,但是却告别了xml,使你的代码远离配置文件。
如果有错误的地方,望各位指正。如有其它问题,可以联系
文章来源:http://www.cnblogs.com/guozp/articles/7446477.html
本文内容总结:
原文链接:https://www.cnblogs.com/guozp/p/7446477.html