天天看點

@Transactional注解在類上還是接口上使用,哪種方式更好?@Transactional介紹Spring的動态代理言歸正傳總結

Spring @Transactional想必大家都很熟悉,那它是在類上或實作類的方法上和在接口上或接口方法上哪種使用方式是更好的選擇呢?

@Transactional介紹

@Transactional 是Spring提供的聲明式事務管理,使用起來簡單、友善,又能和業務邏輯解耦。

Spring的聲明式事務管理在底層是建立在 AOP 的基礎之上的。其本質是對方法前後進行攔截,然後在目标方法開始之前建立或者加入一個事務,在執行完目标方法之後根據執行情況送出或者復原事務。

Spring的動态代理

Spring AOP是通過動态代理實作的。如果代理對象實作了接口,預設使用JDK的動态代理,反之沒有實作接口則使用cglib的動态代理。

言歸正傳

回到問題上,在正确使用@Transactional注解時,不管@Transactional注解是在類上或實作類的方法上還是在接口上或接口方法上,它的事務功能都是可以實作的,隻是選擇那種方式更優雅一點而已。

Spring官方文檔是這樣寫的:

❝Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the @Transactional annotation, as opposed to annotating interfaces. You certainly can place the @Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies. The fact that Java annotations are not inherited from interfaces means that if you are using class-based proxies ( proxy-target-class="true") or the weaving-based aspect ( mode="aspectj"), then the transaction settings are not recognized by the proxying and weaving infrastructure, and the object will not be wrapped in a transactional proxy, which would be decidedly bad.

翻譯過來大概意思是 Spring官方建議在具體的類或類的方法上使用@Transactional注解,而不是在接口或接口方法上使用。@Transactional也可以在接口上使用,但是這僅限于你使用的是基于接口的動态代理。在java中注解是不會被繼承的,如果使用的是基于類的動态代理或者使用aspectj,@Transactional注解的作用就失效了。

總結

Spring 官方建議還是在具體的類上或類的方法上。我本人贊同Spring官方的觀點,事務也是一個實作細節,它應該在具體的類上或方法上,到底具體的實作是否是需要事務要看具體的實作細節。

當然,不是說一定要選擇将@Transactional使用在具體類或者方法上一定是最好的,如果項目架構更适合用接口的動态代理,将@Transactional注解應用到接口或者接口方法上也是可以的。一定要選擇一個最合适自己的,如果沒有找到最合适自己的,那就選擇一個大多數人都認為好的。

能力一般,水準有限,如有錯誤,請多指出。