中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring中怎么實現聲明式事務和編程式事務

發布時間:2021-06-18 15:32:31 來源:億速云 閱讀:154 作者:Leah 欄目:大數據

本篇文章為大家展示了Spring中怎么實現聲明式事務和編程式事務,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

聲明式事務和編程式事務

聲明式事務是基于代理實現的。最小的力度是方法級。 編程式事務是基于事務模版來做的,具有較高的侵略性,不建議使用。

編程式事務管理

基于底層 API 的編程式事務管理

根據PlatformTransactionManager、TransactionDefinition 和 TransactionStatus 三個核心接口,我們完全可以通過編程的方式來進行事務管理。示例代碼如清單4所示:

public class BankServiceImpl implements BankService {

private BankDao bankDao;

// 事務定義
private TransactionDefinition txDefinition;

// 事務管理器
private PlatformTransactionManager txManager;
......
public boolean transfer(Long fromId, Long toId, double amount) {

// 事務的狀態
TransactionStatus txStatus = txManager.getTransaction(txDefinition);
boolean result = false;
try {
result = bankDao.transfer(fromId, toId, amount);
txManager.commit(txStatus);
} catch (Exception e) {
result = false;
txManager.rollback(txStatus);
System.out.println("Transfer Error!");
}
return result;
}
}

清單5. 基于底層API的事務管理示例配置文件 <bean id="bankService" class="footmark.spring.core.tx.programmatic.origin.BankServiceImpl"> <property name="bankDao" ref="bankDao"/> <property name="txManager" ref="transactionManager"/> <property name="txDefinition"> <bean class="org.springframework.transaction.support.DefaultTransactionDefinition"> <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/> </bean> </property> </bean>

基于 TransactionTemplate 的編程式事務管理

public class BankServiceImpl implements BankService {
private BankDao bankDao;
private TransactionTemplate transactionTemplate;
......
public boolean transfer(final Long fromId, final Long toId, final double amount) {

		return (Boolean) transactionTemplate.execute(new TransactionCallback(){
			public Object doInTransaction(TransactionStatus status) {
				Object result;
				try {
					result = bankDao.transfer(fromId, toId, amount);
				} catch (Exception e) {
					status.setRollbackOnly();
					result = false;
					System.out.println("Transfer Error!");
				}
				return result;
			}
		});
	}
}

相應的XML配置如下:

清單 7. 基于 TransactionTemplate 的事務管理示例配置文件 <bean id="bankService" class="footmark.spring.core.tx.programmatic.template.BankServiceImpl"> <property name="bankDao" ref="bankDao"/> <property name="transactionTemplate" ref="transactionTemplate"/> </bean>

聲明式事務管理

基于 TransactionInter... 的聲明式事務管理

清單 8. 基于 TransactionInterceptor 的事務管理示例配置文件 <beans...> ...... <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager"/> <property name="transactionAttributes"> <props> <prop key="transfer">PROPAGATION_REQUIRED</prop> </props> </property> </bean> <bean id="bankServiceTarget" class="footmark.spring.core.tx.declare.origin.BankServiceImpl"> <property name="bankDao" ref="bankDao"/> </bean> <bean id="bankService" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="bankServiceTarget"/> <property name="interceptorNames"> <list> <idref bean="transactionInterceptor"/> </list> </property> </bean> ...... </beans>

基于 TransactionProxy... 的聲明式事務管理

清單9. 基于 TransactionProxyFactoryBean 的事務管理示例配置文件 <beans......> ...... <bean id="bankServiceTarget" class="footmark.spring.core.tx.declare.classic.BankServiceImpl"> <property name="bankDao" ref="bankDao"/> </bean> <bean id="bankService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="target" ref="bankServiceTarget"/> <property name="transactionManager" ref="transactionManager"/> <property name="transactionAttributes"> <props> <prop key="transfer">PROPAGATION_REQUIRED</prop> </props> </property> </bean> ...... </beans>

基于 <tx> 命名空間的聲明式事務管理

清單10. 基于 <tx> 的事務管理示例配置文件 <beans......> ...... <bean id="bankService" class="footmark.spring.core.tx.declare.namespace.BankServiceImpl"> <property name="bankDao" ref="bankDao"/> </bean> <tx:advice id="bankAdvice" transaction-manager="transactionManager"> tx:attributes <tx:method name="transfer" propagation="REQUIRED"/> </tx:attributes> </tx:advice>

aop:config <aop:pointcut id="bankPointcut" expression="execution(* *.transfer(..))"/> <aop:advisor advice-ref="bankAdvice" pointcut-ref="bankPointcut"/> </aop:config> ...... </beans> 如果默認的事務屬性就能滿足要求,那么代碼簡化為如清單 11 所示:

清單 11. 簡化后的基于 <tx> 的事務管理示例配置文件 <beans......> ...... <bean id="bankService" class="footmark.spring.core.tx.declare.namespace.BankServiceImpl"> <property name="bankDao" ref="bankDao"/> </bean> <tx:advice id="bankAdvice" transaction-manager="transactionManager"> aop:config <aop:pointcut id="bankPointcut" expression="execution(**.transfer(..))"/> <aop:advisor advice-ref="bankAdvice" pointcut-ref="bankPointcut"/> </aop:config> ...... </beans> 由于使用了切點表達式,我們就不需要針對每一個業務類創建一個代理對象了。另外,如果配置的事務管理器 Bean 的名字取值為“transactionManager”,則我們可以省略 tx:advice 的 transaction-manager 屬性,因為該屬性的默認值即為“transactionManager”。

基于 @Transactional 的聲明式事務管理

除了基于命名空間的事務配置方式,Spring 2.x 還引入了基于 Annotation 的方式,具體主要涉及@Transactional 標注。@Transactional 可以作用于接口、接口方法、類以及類方法上。當作用于類上時,該類的所有 public 方法將都具有該類型的事務屬性,同時,我們也可以在方法級別使用該標注來覆蓋類級別的定義。如清單12所示:

清單12. 基于 @Transactional 的事務管理示例配置文件 @Transactional(propagation = Propagation.REQUIRED) public boolean transfer(Long fromId, Long toId, double amount) { return bankDao.transfer(fromId, toId, amount); } Spring 使用 BeanPostProcessor 來處理 Bean 中的標注,因此我們需要在配置文件中作如下聲明來激活該后處理 Bean,如清單13所示:

清單13. 啟用后處理Bean的配置 <tx:annotation-driven transaction-manager="transactionManager"/> 與前面相似,transaction-manager 屬性的默認值是 transactionManager,如果事務管理器 Bean 的名字即為該值,則可以省略該屬性。

雖然 @Transactional 注解可以作用于接口、接口方法、類以及類方法上,但是 Spring 小組建議不要在接口或者接口方法上使用該注解,因為這只有在使用基于接口的代理時它才會生效。另外, @Transactional 注解應該只被應用到 public 方法上,這是由 Spring AOP 的本質決定的。如果你在 protected、private 或者默認可見性的方法上使用 @Transactional 注解,這將被忽略,也不會拋出任何異常。

基于 <tx> 命名空間和基于 @Transactional 的事務聲明方式各有優缺點。基于 <tx> 的方式,其優點是與切點表達式結合,功能強大。利用切點表達式,一個配置可以匹配多個方法,而基于 @Transactional 的方式必須在每一個需要使用事務的方法或者類上用 @Transactional 標注,盡管可能大多數事務的規則是一致的,但是對 @Transactional 而言,也無法重用,必須逐個指定。另一方面,基于 @Transactional 的方式使用起來非常簡單明了,沒有學習成本。開發人員可以根據需要,任選其中一種使用,甚至也可以根據需要混合使用這兩種方式。

如果不是對遺留代碼進行維護,則不建議再使用基于 TransactionInterceptor 以及基于TransactionProxyFactoryBean 的聲明式事務管理方式,但是,學習這兩種方式非常有利于對底層實現的理解。

雖然上面共列舉了四種聲明式事務管理方式,但是這樣的劃分只是為了便于理解,其實后臺的實現方式是一樣的,只是用戶使用的方式不同而已。

總結

  • 基于 TransactionDefinition、PlatformTransactionManager、TransactionStatus 編程式事務管理是 Spring 提供的最原始的方式,通常我們不會這么寫,但是了解這種方式對理解 Spring 事務管理的本質有很大作用。

  • 基于 TransactionTemplate 的編程式事務管理是對上一種方式的封裝,使得編碼更簡單、清晰。

  • 基于 TransactionInterceptor 的聲明式事務是 Spring 聲明式事務的基礎,通常也不建議使用這種方式,但是與前面一樣,了解這種方式對理解 Spring 聲明式事務有很大作用。

  • 基于 TransactionProxyFactoryBean 的聲明式事務是上中方式的改進版本,簡化的配置文件的書寫,這是 Spring 早期推薦的聲明式事務管理方式,但是在 Spring 2.0 中已經不推薦了。

  • 基于 <tx> 和 <aop> 命名空間的聲明式事務管理是目前推薦的方式,其最大特點是與 Spring AOP 結合緊密,可以充分利用切點表達式的強大支持,使得管理事務更加靈活。

  • 基于 @Transactional 的方式將聲明式事務管理簡化到了極致。開發人員只需在配置文件中加上一行啟用相關后處理 Bean 的配置,然后在需要實施事務管理的方法或者類上使用 @Transactional 指定事務規則即可實現事務管理,而且功能也不必其他方式遜色。

上述內容就是Spring中怎么實現聲明式事務和編程式事務,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

贵阳市| 屯门区| 密山市| 溆浦县| 成都市| 玉溪市| 陆川县| 鄂托克前旗| 拜城县| 岱山县| 嘉峪关市| 东阿县| 黄大仙区| 永和县| 保康县| 西贡区| 广西| 承德县| 阳谷县| 东源县| 大关县| 化州市| 广丰县| 郎溪县| 邳州市| 白山市| 阿拉善右旗| 镶黄旗| 垣曲县| 且末县| 黎川县| 家居| 红河县| 东兰县| 赤峰市| 永善县| 七台河市| 民丰县| 浮梁县| 澄迈县| 太仆寺旗|