@Async java 異步方法

  在spring 3中,@Async註解能讓某個方法快速變爲異步執行,立刻來先DEMO上手下。 

假如在網站的用戶註冊後,須要發送郵件,而後用戶獲得郵件確認後才能繼續其餘工做; 
假設發送是一個很耗費時間的過程,所以須要異步。 

1 namespace要注意,加上task 
  html

Java代碼   收藏代碼
  1. <?xml version=」1.0″ encoding=」UTF-8″?>  
  2.   
  3. <beans xmlns=」http://www.springframework.org/schema/beans」 xmlns:xsi=」http://www.w3.org/2001/XMLSchema-instance」  
  4. xmlns:p=」http://www.springframework.org/schema/p」 xmlns:context=」http://www.springframework.org/schema/context」  
  5. xsi:schemaLocation=」  
  6. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd  
  8. http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd」>  
  9.   
  10. <context:component-scan base-package=」cs」/>  
  11.   
  12. </beans>  



2 RegularService.java 註冊類 
  java

Java代碼   收藏代碼
    1.  import org.springframework.beans.factory.annotation.Autowired;  
    2. import org.springframework.stereotype.Service;  
    3.   
    4. import cs.async.MailUtility;  
    5.   
    6. @Service  
    7. public class RegularService {  
    8.   
    9. @Autowired  
    10. private MailUtility mailUtility ;  
    11.   
    12. public void registerUser(String userName){  
    13.   
    14. System.out.println(」 User registration for  「+userName +」 complete」);  
    15.   
    16. mailUtility.sendMail(userName);  
    17.   
    18. System.out.println(」 註冊完成,郵件稍後發送「);  
    19. }  
    20.   
    21. }  
    22.   
    23. 3 發送郵件的工具類  
    24.    <pre name="code" class="java">import org.springframework.scheduling.annotation.Async;  
    25. import org.springframework.stereotype.Component;  
    26.   
    27. @Component  
    28. public class MailUtility {  
    29.   
    30. @Async  
    31. public void sendMail(String name){  
    32.   
    33. System.out.println(」 在作發送準備工做中  「);  
    34.   
    35. try {  
    36. Thread.sleep(5000);  
    37.   
    38. catch (InterruptedException e) {  
    39.   
    40. e.printStackTrace();  
    41. }  
    42.   
    43. System.out.println(」 異步發送完畢「);  
    44.   
    45. }  
    46.   
    47. }  
    48. </pre>  
    49. <br>  
    50. <br>4 最後在applicationContext.xml中加入:  
    51. <br>  <pre name="code" class="java"><?xml version=」1.0″ encoding=」UTF-8″?>  
    52.   
    53. <beans xmlns=」http://www.springframework.org/schema/beans」 xmlns:xsi=」http://www.w3.org/2001/XMLSchema-instance」  
    54. xmlns:p=」http://www.springframework.org/schema/p」 xmlns:context=」http://www.springframework.org/schema/context」  
    55. xmlns:task=」http://www.springframework.org/schema/task」  
    56. xsi:schemaLocation=」  
    57. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
    58. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd  
    59. http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd「>  
    60.   
    61. <context:component-scan base-package=」cs」/>  
    62.   
    63. <task:annotation-driven/>  
    64.   
    65. </beans>  
    66. </pre>  
    67. <br>   就是<task:annotation-driven/>這個必定不能少喔。  
    68. <br>  
    69. <br>5 運行:  
    70. <br>   User registration for  tom complete  
    71. <br>  註冊完成,郵件稍後發送  
    72. <br>在作發送準備工做中  
    73. <br>異步發送完畢  
    74. <br>  
    75. <br>6 有的時候,要從異步中返回值,這個時候,spring會返回一個java.util.concurrent.Future對象,要調用其中的get方法,好比  
    76. <br>   <pre name="code" class="java">@Async  
    77. public Future<Balance> findBalanceAsync(final Account account) {  
    78.     Balance balance = accountRepository.findBalance(account);  
    79.     return new AsyncResult<Balance>(balance);  
    80. }  
    81.   
    82. Balance balance = future.get();  
    83.   
    84. </pre>  
    85. <br>     
    86. <br>  
    87. 注意事項:必須解決循環依賴
    88. 原理: spring 在掃描bean的時候會掃描方法上是否包含@async的註解,若是包含的,spring會爲這個bean動態的生成一個子類,咱們稱之爲代理類(?),代理類是繼承咱們所寫的bean的,而後把代理類注入進來,那此時,在執行此方法的時候,會到代理類中,代理類判斷了此方法須要異步執行,就不會調用父類(咱們本來寫的bean)的對應方法。spring本身維護了一個隊列,他會把須要執行的方法,放入隊列中,等待線程池去讀取這個隊列,完成方法的執行,從而完成了異步的功能。
    89. 今天對項目工程(spring3.0.6+structs2.2.3)進行瘦身,業務層bean統一用@Service註解,set注入用@Autowired替換,從xml配置文件中將業務bean配置所有清掉。
      這時專門處理異步操做的bean報循環依賴(引用):
      Bean with name ‘*********’ has been injected into other beans [******, **********, **********, **********] in its raw version as part of a circular reference具體狀況是beanA注入用於異步處理的beanB(含有@Async註解的方法),用於對某些操做進行異步處理,而beanB又注入beanA用於實現異步處理
      解決方案:beanA注入異步處理的beanB的代理服務beanC(不含@Async註解),再由beanC注入beanB進行處理spring

相關文章
相關標籤/搜索