• @Async java 异步方法


      在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.    <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进行处理

  • 相关阅读:
    Mybatis-Plus的应用场景及注入SQL原理分析
    玩转直播系列之消息模块演进(3)
    Kafka万亿级消息实战
    玩转直播系列之RTMP协议和源码解析(2)
    Tars-Java客户端源码分析
    玩转直播系列之从 0 到 1 构建简单直播系统(1)
    如何把 Caffeine Cache 用得如丝般顺滑?
    kubenets 配置Pod的 /etc/hosts
    kubernetes之多容器部署pod以及通信
    k8s master调度pod
  • 原文地址:https://www.cnblogs.com/leo3689/p/4318692.html
Copyright © 2020-2023  润新知