SpringBoot 注解事務(wù)聲明式事務(wù)的方式
springboot 對新人來說可能上手比springmvc要快,但是對于各位從springmvc轉(zhuǎn)戰(zhàn)到springboot的話,有些地方還需要適應(yīng)下,尤其是xml配置。我個人是比較喜歡注解➕xml是因為看著方便,查找方便,清晰明了。但是xml完全可以使用注解代替,今天就扒一扒springboot中事務(wù)使用注解的玩法。
springboot的事務(wù)也主要分為兩大類,一是xml聲明式事務(wù),二是注解事務(wù),注解事務(wù)也可以實現(xiàn)類似聲明式事務(wù)的方法,關(guān)于注解聲明式事務(wù),目前網(wǎng)上搜索不到合適的資料,所以在這里,我將自己查找和總結(jié)的幾個方法寫到這里,大家共同探討
springboot 之 xml事務(wù)
可以使用 @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);
}
}
啟動后即可開啟事務(wù),不過項目里導(dǎo)入了xml配置,如果不想導(dǎo)入xml配置,可以使用注解的方式。
springboot 之 注解事務(wù)
注解事務(wù)講解之前,需要先了解下spring創(chuàng)建代理的幾個類,在spring內(nèi)部,是通過BeanPostProcessor來完成自動創(chuàng)建代理工作的。BeanPostProcessor接口的實現(xiàn)只是在ApplicationContext初始化的時候才會自動加載,而普通的BeanFactory只能通過編程的方式調(diào)用之。根據(jù) 匹配規(guī)則的不同大致分為三種類別:
a、匹配Bean的名稱自動創(chuàng)建匹配到的Bean的代理,實現(xiàn)類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、根據(jù)Bean中的AspectJ注解自動創(chuàng)建代理,實現(xiàn)類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、根據(jù)Advisor的匹配機制自動創(chuàng)建代理,會對容器中所有的Advisor進行掃描,自動將這些切面應(yīng)用到匹配的Bean中,實現(xiàn)類DefaultAdvisorAutoProxyCreator
接下來開講注解開啟事務(wù)的方法:
1、Transactional注解事務(wù)
需要在進行事物管理的方法上添加注解@Transactional,或者偷懶的話直接在類上面添加該注解,使得所有的方法都進行事物的管理,但是依然需要在需要事務(wù)管理的類上都添加,工作量比較大,這里只是簡單說下,具體的可以google或者bing
2、注解聲明式事務(wù)
Component或Configuration中bean的區(qū)別,有時間我會專門寫一篇來講解下
a.方式1,這里使用Component或Configuration事務(wù)都可以生效
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 事務(wù)依然生效
@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();
/*只讀事務(wù),不做更新操作*/
RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
readOnlyTx.setReadOnly(true);
readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED );
/*當前存在事務(wù)就使用當前事務(wù),當前不存在事務(wù)就創(chuàng)建一個新的事務(wù)*/
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事務(wù)都可以生效
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 事務(wù)依然生效
@Configuration
public class TxAnoConfig {
/*事務(wù)攔截類型*/
@Bean("txSource")
public TransactionAttributeSource transactionAttributeSource(){
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
/*只讀事務(wù),不做更新操作*/
RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
readOnlyTx.setReadOnly(true);
readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED );
/*當前存在事務(wù)就使用當前事務(wù),當前不存在事務(wù)就創(chuàng)建一個新的事務(wù)*/
//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;
}
/**切面攔截規(guī)則 參數(shù)會自動從容器中注入*/
@Bean
public AspectJExpressionPointcutAdvisor pointcutAdvisor(TransactionInterceptor txInterceptor){
AspectJExpressionPointcutAdvisor pointcutAdvisor = new AspectJExpressionPointcutAdvisor();
pointcutAdvisor.setAdvice(txInterceptor);
pointcutAdvisor.setExpression("execution (* com.alibaba.fm9..service.*.*(..))");
return pointcutAdvisor;
}
/*事務(wù)攔截器*/
@Bean("txInterceptor")
TransactionInterceptor getTransactionInterceptor(PlatformTransactionManager tx){
return new TransactionInterceptor(tx , transactionAttributeSource()) ;
}
}
c.方式1,這里使用Component或Configuration事務(wù)都可以生效
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;
// 創(chuàng)建事務(wù)通知
@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并不是所有事務(wù)都可以生效,例如Configuration的時候如果打開注釋部分的而且不把代碼都移動到 defaultPointcutAdvisor(),事物會失效,具體原因暫時不明,如果各位有明白的,可以指點我下。
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 //事務(wù)失效,都移動到一個方法不失效
//@Component // 事務(wù)可行,不用都移動到一個方法
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,使你的代碼遠離配置文件。
總結(jié)
以上所述是小編給大家介紹的SpringBoot 注解事務(wù)聲明式事務(wù)的方式,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
- springboot @ConditionalOnMissingBean注解的作用詳解
- springboot2中使用@JsonFormat注解不生效的解決
- SpringBoot中@Pattern注解對時間格式校驗方式
- springboot FeignClient注解及參數(shù)
- SpringBoot中@ConfigurationProperties注解的使用與源碼詳解
- SpringBoot2.0整合SpringCloud Finchley @hystrixcommand注解找不到解決方案
- 親測SpringBoot參數(shù)傳遞及@RequestBody注解---踩過的坑及解決
- 詳解SpringBoot 快速整合Mybatis(去XML化+注解進階)
- SpringBoot單元測試中@SpyBean使用小結(jié)
相關(guān)文章
Spring、SpringMvc和SpringBoot的區(qū)別及說明
Spring框架提供了全面的Java開發(fā)解決方案,核心包括IOC和AOP,SpringMvc作為其中的WEB層開發(fā)框架,通過復(fù)雜的XML配置管理前端視圖和后臺邏輯,SpringBoot則簡化了配置,專注于微服務(wù)接口開發(fā),支持嵌入式服務(wù)器,提高了開發(fā)效率2024-10-10
java計算兩個日期之前的天數(shù)實例(排除節(jié)假日和周末)
下面小編就為大家?guī)硪黄猨ava計算兩個日期之前的天數(shù)實例(排除節(jié)假日和周末)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07
Spring集成MyBatis和PageHelper分頁插件整合過程詳解
Spring?整合?MyBatis?是將?MyBatis?數(shù)據(jù)訪問框架與?Spring?框架進行集成,以實現(xiàn)更便捷的開發(fā)和管理,在集成過程中,Spring?提供了許多特性和功能,如依賴注入、聲明式事務(wù)管理、AOP?等,這篇文章主要介紹了Spring集成MyBatis和PageHelper分頁插件整合,需要的朋友可以參考下2023-08-08
SpringBoot項目中自定義Banner的技術(shù)指南
在 Spring Boot 項目中,當應(yīng)用啟動時會顯示默認的 Spring 標志和版本信息,定制化的啟動 Banner 不僅可以美化應(yīng)用,甚至可以提供一些關(guān)鍵信息,本文將介紹如何在 Spring Boot 項目中自定義啟動 Banner,需要的朋友可以參考下2025-03-03

