spring 元素 实现任务调度和异步方法

系统 1577 0
    在我们使用spring框架的过程中,在很多时候我们会使用@async注解来异步执行某一些方法,提高系统的执行效率。今天我们来探讨下 spring 是如何完成这个功能的。 

    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  
这里就不详细说明了 
 
 
在spring 3中,@Async注解能让某个方法快速变为异步执行,马上来先DEMO上手下。 

假如在网站的用户注册后,需要发送邮件,然后用户得到邮件确认后才能继续其他工作; 
假设发送是一个很耗费时间的过程,因此需要异步。 

1 namespace要注意,加上task 
  
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代码   收藏代码
  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. 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.  
  49.  
  50. 4  最后在applicationContext.xml中加入:  
  51. <?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.    就是<task:annotation-driven/>这个一定不能少喔。  
  67.  
  68. 5  运行:  
  69.   User registration  for   tom complete  
  70.   注册完成,邮件稍后发送  
  71.   在做发送准备工作中  
  72.   异步发送完毕  
  73.  
  74.   6  有的时候,要从异步中返回值,这个时候,spring会返回一个java.util.concurrent.Future对象,要调用其中的get方法,比如  
  75. @Async   
  76. public  Future<Balance> findBalanceAsync( final  Account account) {  
  77.     Balance balance = accountRepository.findBalance(account);  
  78.      return   new  AsyncResult<Balance>(balance);  
  79. }  
  80.   
  81. Balance balance = future.get();  
  82.   
  83. Spring3中加强了注解的使用,其中计划任务也得到了增强,现在创建一个计划任务只需要 两步 就完成了:

    1. 创建一个Java类,添加一个无参无返回值的方法,在方法上用@Scheduled注解修饰一下;
    2. 在Spring配置文件中添加三个<task:**** />节点;

    最后说明一下,第一步创建的Java类要成为Spring可管理的Bean,可以直接写在XML里,也可以@Component一下

     

    示例如下

    计划任务类:

    Java代码   收藏代码
    1. /**  
    2.  * com.zywang.spring.task.SpringTaskDemo.java  
    3.  * @author ZYWANG 2011-3-9  
    4.  */   
    5. package  com.zywang.spring.task;  
    6.   
    7. import  org.springframework.scheduling.annotation.Scheduled;  
    8. import  org.springframework.stereotype.Component;  
    9.   
    10. /**  
    11.  * Spring3 @Scheduled 演示  
    12.  * @author ZYWANG 2011-3-9  
    13.  */   
    14. @Component   
    15. public   class  SpringTaskDemo {  
    16.   
    17.      @Scheduled (fixedDelay =  5000 )  
    18.      void  doSomethingWithDelay(){  
    19.         System.out.println( "I'm doing with delay now!" );  
    20.     }  
    21.       
    22.      @Scheduled (fixedRate =  5000 )  
    23.      void  doSomethingWithRate(){  
    24.         System.out.println( "I'm doing with rate now!" );  
    25.     }  
    26.       
    27.      @Scheduled (cron =  "0/5 * * * * *" )  
    28.      void  doSomethingWith(){  
    29.         System.out.println( "I'm doing with cron now!" );  
    30.     }  
    31. }  

    Spring配置文件:

    Xml代码   收藏代码
    1. <? xml   version = "1.0"   encoding = "UTF-8" ?>   
    2. < beans   xmlns = "http://www.springframework.org/schema/beans"   
    3.      xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"   xmlns:task = "http://www.springframework.org/schema/task"   
    4.      xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
    5.         http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd" >   
    6.      <!-- Enables the Spring Task @Scheduled programming model -->   
    7.      < task:executor   id = "executor"   pool-size = "5"   />   
    8.      < task:scheduler   id = "scheduler"   pool-size = "10"   />   
    9.      < task:annotation-driven   executor = "executor"   scheduler = "scheduler"   />   
    10. </ beans >   

spring 元素 实现任务调度和异步方法


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论