javascript
@transactional注解_为啥同一个类中普通方法调用Spring注解方法,注解会失效?看完你就明白,So easy!...
Spring注解(如@Transactional、@Cacheable、@Async等),在使用不當(dāng)時(shí),很可能會(huì)失效。失效的情況有很多種,本文我們就來(lái)瞅瞅,為啥同一個(gè)類中普通方法調(diào)用Spring注解方法,注解會(huì)失效呢?
有一些同學(xué)可能不知道其中原由,別急,讓我來(lái)為大家揭曉答案。
聽(tīng)說(shuō)你很懂源碼?Spring讀懂了?還有這20道源碼面試題接得住嗎??zhuanlan.zhihu.comSpring在掃描bean的時(shí)候,如果掃描到方法上有這些注解,那么spring會(huì)通過(guò)動(dòng)態(tài)代理模式,為這個(gè)bean動(dòng)態(tài)地生成一個(gè)代理類,在代理類中,會(huì)對(duì)有注解的這個(gè)方法,做一些增強(qiáng)處理,如給有@Transactional注解的方法開(kāi)啟transaction。
當(dāng)我們想要調(diào)用這個(gè)方法時(shí),實(shí)際上是先調(diào)用了代理對(duì)象中被增強(qiáng)的方法,然后在代理對(duì)象中,又會(huì)調(diào)用我們實(shí)際的目標(biāo)對(duì)象中的方法。在通過(guò)代理對(duì)象中轉(zhuǎn)的這一過(guò)程中,像上邊說(shuō)的開(kāi)啟和提交transaction就實(shí)現(xiàn)了。
實(shí)現(xiàn)機(jī)制我們大體知道了,下面我們用代碼來(lái)模擬演示一下。
假設(shè)我們訂單業(yè)務(wù)處理類中,有兩個(gè)方法:校驗(yàn)訂單參數(shù)方法verifyOrderParameters() 和 保存訂單方法saveOrder(),其中saveOrder方法上加了@Transactional注解,verifyOrderParameters方法內(nèi)會(huì)調(diào)用saveOrder方法。
OrderService
/*** 訂單業(yè)務(wù)層的接口定義*/ public interface OrderService {/*** 校驗(yàn)訂單參數(shù)*/void verifyOrderParameters();/*** 保存訂單*/void saveOrder(); }OrderServiceImpl
/*** 訂單業(yè)務(wù)層的具體處理類*/ public class OrderServiceImpl implements OrderService{@Overridepublic void verifyOrderParameters() {System.out.println("校驗(yàn)訂單參數(shù)");// 調(diào)用保存訂單方法saveOrder();}@Override@Transactionalpublic void saveOrder() {System.out.println("保存訂單信息到DB");} }我們用偽代碼來(lái)演示一下Spring動(dòng)態(tài)代理生成的代理類。
OrderServiceImplProxy
/*** 訂單業(yè)務(wù)層具體處理類的代理類*/ public class OrderServiceImplProxy implements OrderService{/*** 持有被代理的具體的目標(biāo)對(duì)象*/private OrderServiceImpl orderServiceImpl;public OrderServiceImplProxy(OrderServiceImpl orderServiceImpl) {this.orderServiceImpl = orderServiceImpl;}@Overridepublic void verifyOrderParameters() {orderServiceImpl.verifyOrderParameters();}@Overridepublic void saveOrder() {System.out.println("開(kāi)啟事務(wù)。。。");orderServiceImpl.saveOrder();System.out.println("提交事務(wù)。。。");} }邊我們來(lái)看下客戶端調(diào)用saveOrder方法和verifyOrderParameters方法,輸出結(jié)果都是什么樣的。
public class Client {public static void main(String[] args) {// 創(chuàng)建一個(gè)訂單業(yè)務(wù)的真實(shí)處理對(duì)象OrderServiceImpl orderServiceImpl = new OrderServiceImpl();// 創(chuàng)建一個(gè)代理對(duì)象OrderServiceImplProxy orderServiceImplProxy = new OrderServiceImplProxy(orderServiceImpl);// 執(zhí)行代理對(duì)象的校驗(yàn)訂單方法orderServiceImplProxy.verifyOrderParameters();System.out.println("--------------------------------------------");// 執(zhí)行代理對(duì)象的保存訂單方法orderServiceImplProxy.saveOrder();} }執(zhí)行main方法后,得到下邊的輸出:
校驗(yàn)訂單參數(shù)保存訂單信息到DB
--------------------------------------------
開(kāi)啟事務(wù)。。。
保存訂單信息到DB
提交事務(wù)。。。
通過(guò)這個(gè)演示代碼,想必同學(xué)們已經(jīng)了解了吧,普通方法verifyOrderParameters內(nèi)調(diào)用注解方法saveOrder時(shí),其實(shí)調(diào)用的是原目標(biāo)對(duì)象(orderServiceImpl)的saveOrder方法,沒(méi)有走代理對(duì)象(orderServiceImplProxy)中被增強(qiáng)的saveOrder方法,所以就不會(huì)產(chǎn)生效果啦。
動(dòng)態(tài)代理是實(shí)現(xiàn)Spring AOP的一個(gè)重要手段,所以大家以后再用注解以及切面時(shí),一定要注意這個(gè)坑噢。
作者:曉呆同學(xué)原文鏈接:https://blog.csdn.net/daidaineteasy/article/details/105981724
總結(jié)
以上是生活随笔為你收集整理的@transactional注解_为啥同一个类中普通方法调用Spring注解方法,注解会失效?看完你就明白,So easy!...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 华为问界M5有对手了!领克08发布:首搭
- 下一篇: gradle idea java ssm