??? spring 在掃描bean的時候會掃描方法上是否包含@async的注解,如果包含的,spring會為這個bean動態的生成一個子類,我們稱之為代理類(?),代理類是繼承我們所寫的bean的,然后把代理類注入進來,那此時,在執行此方法的時候,會到代理類中,代理類判斷了此方法需要異步執行,就不會調用父類(我們原本寫的bean)的對應方法。spring自己維護了一個隊列,他會把需要執行的方法,放入隊列中,等待線程池去讀取這個隊列,完成方法的執行,從而完成了異步的功能。我們可以關注到再配置task的時候,是有參數讓我們配置線程池的數量的。 因為這種實現方法,所以在同一個類中的方法調用,添加@async注解是失效的! ,原因是當你在同一個類中的時候,方法調用是在類體內執行的,spring無法截獲這個方法調用。?
??? 那在深入一步,spring為我們提供了AOP,面向切面的功能。他的原理和異步注解的原理是類似的,spring在啟動容器的時候,會掃描切面所定義的類。在這些類被注入的時候,所注入的也是代理類,當你調用這些方法的時候,本質上是調用的代理類。通過代理類再去執行父類相對應的方法,那spring只需要在調用之前和之后執行某段代碼就完成了AOP的實現了!?
?? 那最后我們還有一個問題,spring是如何動態的生成某一個類的子類的?代理類??
?? 生成代理類可以通過jdk 和 CGLIB 兩種方式生成.具體的可以?
?? 參考 1.代理類說明: http://wenku.baidu.com/link?url=YpU3CNXsyLivMCnpILQ1qQc8PcKuqRrqZd1X8hPNQa9QuBFmbpCugSdjkXlY2L_ey4rUxM7TlwHeAatL65e664h_W8n0IKgTP1vFU5wacrm
??????? 2.CGLIB和JDK代理類的區別: http://www.blogjava.net/hello-yun/archive/2011/11/09/363359.html ?
這里就不詳細說明了?
假如在網站的用戶注冊后,需要發送郵件,然后用戶得到郵件確認后才能繼續其他工作;?
假設發送是一個很耗費時間的過程,因此需要異步。?
1 namespace要注意,加上task?
??
- <?xml?version=” 1.0 ″?encoding=”UTF- 8 ″?>??
- ??
- <beans?xmlns=”http: //www.springframework.org/schema/beans”?xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” ??
- xmlns:p=”http: //www.springframework.org/schema/p”?xmlns:context=”http://www.springframework.org/schema/context” ??
- xsi:schemaLocation=”??
- http: //www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans-3.0.xsd ??
- http: //www.springframework.org/schema/context?http://www.springframework.org/schema/context/spring-context-3.0.xsd ??
- http: //www.springframework.org/schema/task?http://www.springframework.org/schema/task/spring-task-3.0.xsd”> ??
- ??
- <context:component-scan?base- package =”cs”/>??
- ??
- </beans>??
2 RegularService.java 注冊類?
??
- ? import ?org.springframework.beans.factory.annotation.Autowired;??
- import ?org.springframework.stereotype.Service;??
- ??
- import ?cs.async.MailUtility;??
- ??
- @Service ??
- public ? class ?RegularService?{??
- ??
- @Autowired ??
- private ?MailUtility?mailUtility?;??
- ??
- public ? void ?registerUser(String?userName){??
- ??
- System.out.println(”?User?registration? for ??“+userName?+”?complete”);??
- ??
- mailUtility.sendMail(userName);??
- ??
- System.out.println(”?注冊完成,郵件稍后發送“);??
- }??
- ??
- }??
- ??
- 3 ?發送郵件的工具類??
- import ?org.springframework.scheduling.annotation.Async;??
- import ?org.springframework.stereotype.Component;??
- ??
- @Component ??
- public ? class ?MailUtility?{??
- ??
- @Async ??
- public ? void ?sendMail(String?name){??
- ??
- System.out.println(”?在做發送準備工作中??“);??
- ??
- try ?{??
- Thread.sleep( 5000 );??
- ??
- }? catch ?(InterruptedException?e)?{??
- ??
- e.printStackTrace();??
- }??
- ??
- System.out.println(”?異步發送完畢“);??
- ??
- }??
- ??
- }??
- ?
- ?
- 4 ?最后在applicationContext.xml中加入:??
- <?xml?version=” 1.0 ″?encoding=”UTF- 8 ″?>??
- ??
- <beans?xmlns=”http: //www.springframework.org/schema/beans”?xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” ??
- xmlns:p=”http: //www.springframework.org/schema/p”?xmlns:context=”http://www.springframework.org/schema/context” ??
- xmlns:task=”http: //www.springframework.org/schema/task” ??
- xsi:schemaLocation=”??
- http: //www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans-3.0.xsd ??
- http: //www.springframework.org/schema/context?http://www.springframework.org/schema/context/spring-context-3.0.xsd ??
- http: //www.springframework.org/schema/task?http://www.springframework.org/schema/task/spring-task-3.0.xsd“> ??
- ??
- <context:component-scan?base- package =”cs”/>??
- ??
- <task:annotation-driven/>??
- ??
- </beans>??
- ? ?就是<task:annotation-driven/>這個一定不能少喔。 ?
- ?
- 5 ?運行:??
- ? User?registration? for ??tom?complete??
- ? 注冊完成,郵件稍后發送??
- ? 在做發送準備工作中??
- ? 異步發送完畢??
- ?
- ? 6 ?有的時候,要從異步中返回值,這個時候,spring會返回一個java.util.concurrent.Future對象,要調用其中的get方法,比如??
- @Async ??
- public ?Future<Balance>?findBalanceAsync( final ?Account?account)?{??
- ????Balance?balance?=?accountRepository.findBalance(account);??
- ???? return ? new ?AsyncResult<Balance>(balance);??
- }??
- ??
- Balance?balance?=?future.get();??
- ??
-
Spring3中加強了注解的使用,其中計劃任務也得到了增強,現在創建一個計劃任務只需要 兩步 就完成了:
- 創建一個Java類,添加一個無參無返回值的方法,在方法上用@Scheduled注解修飾一下;
- 在Spring配置文件中添加三個<task:**** />節點;
最后說明一下,第一步創建的Java類要成為Spring可管理的Bean,可以直接寫在XML里,也可以@Component一下
?
示例如下
計劃任務類:
- /** ?
- ?*?com.zywang.spring.task.SpringTaskDemo.java ?
- ?*?@author?ZYWANG?2011-3-9 ?
- ?*/ ??
- package ?com.zywang.spring.task;??
- ??
- import ?org.springframework.scheduling.annotation.Scheduled;??
- import ?org.springframework.stereotype.Component;??
- ??
- /** ?
- ?*?Spring3?@Scheduled?演示 ?
- ?*?@author?ZYWANG?2011-3-9 ?
- ?*/ ??
- @Component ??
- public ? class ?SpringTaskDemo?{??
- ??
- ???? @Scheduled (fixedDelay?=? 5000 )??
- ???? void ?doSomethingWithDelay(){??
- ????????System.out.println( "I'm?doing?with?delay?now!" );??
- ????}??
- ??????
- ???? @Scheduled (fixedRate?=? 5000 )??
- ???? void ?doSomethingWithRate(){??
- ????????System.out.println( "I'm?doing?with?rate?now!" );??
- ????}??
- ??????
- ???? @Scheduled (cron?=? "0/5?*?*?*?*?*" )??
- ???? void ?doSomethingWith(){??
- ????????System.out.println( "I'm?doing?with?cron?now!" );??
- ????}??
- }??
Spring配置文件:
- <? xml ? version = "1.0" ? encoding = "UTF-8" ?> ??
- < beans ? xmlns = "http://www.springframework.org/schema/beans" ??
- ???? xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" ? xmlns:task = "http://www.springframework.org/schema/task" ??
- ???? xsi:schemaLocation ="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans.xsd??
- ????????http://www.springframework.org/schema/task?http://www.springframework.org/schema/task/spring-task-3.0.xsd" > ??
- ???? <!--?Enables?the?Spring?Task?@Scheduled?programming?model?--> ??
- ???? < task:executor ? id = "executor" ? pool-size = "5" ? /> ??
- ???? < task:scheduler ? id = "scheduler" ? pool-size = "10" ? /> ??
- ???? < task:annotation-driven ? executor = "executor" ? scheduler = "scheduler" ? /> ??
- </ beans > ??
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
