淺談@Async和@Transaction


@Async注解使用條件:

1、@Async注解一般用在類的方法上,如果用在類上,那么這個類所有的方法都是異步執行的;

2、所使用的@Async注解方法的類對象應該是Spring容器管理的bean對象;

3、調用異步方法類上需要配置上注解@EnableAsync。

使用注意:

1、默認情況下(即@EnableAsync注解的mode=AdviceMode.PROXY),同一個類內部沒有使用@Async注解修飾的方法調用@Async注解修飾的方法,是不會異步執行的,這點跟 @Transitional 注解類似,底層都是通過動態代理實現的(詳見:Java中的引用和動態代理的實現詳解)。如果想實現類內部自調用也可以異步,則需要切換@EnableAsync注解的mode=AdviceMode.ASPECTJ;

2、任意參數類型都是支持的,但是方法返回值必須是void或者Future類型。當使用Future時,你可以使用 實現了Future接口的ListenableFuture接口或者CompletableFuture類與異步任務做更好的交互。如果異步方法有返回值,沒有使用Future<V>類型的話,調用方獲取不到返回值。

循環依賴問題解決:

A的某個field或者setter依賴了B的實例對象,同時B的某個field或者setter依賴了A的實例對象,Spring通過三級緩存解決循環依賴。同樣對於循環依賴的場景,構造器注入和prototype類型的屬性注入都會初始化Bean失敗,因為@Service默認是單例的,所以單例的屬性注入是可以成功的。

總結:

1、構造器注入和prototype類型的field注入發生循環依賴時都無法初始化;

2、field注入單例的bean時,盡管有循環依賴,但bean仍然可以被成功初始化。詳見:Spring-bean的循環依賴以及解決方式

但是如果A類里面方法使用了 @Async 注解,就引起了循環依賴報錯,這是為什么呢。查閱官方文檔:Async注解初始化

NOTE: AsyncConfigurer configuration classes get initialized early in the application context bootstrap. If you need any dependencies on other beans there, make sure to declare them 'lazy' as far as possible in order to let them go through other post-processors as well.

在Spring 啟動過程中Async注解為類創建代理類,這樣Spring 三級緩存中就沒有單例bean的早期引用對象而是Async代理對象,緩存里面找不到bean原始早期對象就引起報錯。

解決方法是為注入的其他類增加懶加載@Lazy注解,解決循環依賴報錯問題。

懶加載@Lazy:

默認情況下 Bean 等同於 @Lazy(false),在 IOC 容器啟動的時候就創建了。如果定義 Bean 的時候加上 @Lazy ,則在 IOC 容器加載的時候,該 Bean 不會被初始化,在調用該 Bean 的時候才會被初始化。

插播sql注入問題:

sql中經常用like進行模糊查詢,而模糊查詢就要用到百分號“%”,下划線“_”這些通配符,其中“%”匹配任意多個字符,“_”匹配單個字符。如果我們想要模糊查詢帶有通配符的字符串,如“60%”,“user_name”,就需要對通配符進行轉義,有兩種方式,如下:

1、反斜杠是轉義符,通過反斜杠來轉義%,使其不再是通配符。這里第一個%是通配符,第二個%不是通配符。

select percent from score where percent like '%0\%';

2、這種是通過escape關鍵字進行轉義,將特定符號后的字符進行轉義,這里斜杠后面的%就不再是通配符,斜杠之前的%仍然起通配符作用。

select percent from score where percent like '%0/%' escape '/';

建議concat配合escape使用。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM