spring <task>元素 实现任务调度和异步方法 【spring】@async原理 在Spring3中使用注解(@Scheduled)创建计划任务

    在我们使用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>  

猜你喜欢

转载自xls9577087.iteye.com/blog/2123279