spring @Async处理异步任务以及常见“异步失效”问题

news/2024/7/19 11:40:23 标签: java, 测试, 爬虫

情景:
在某些业务过程,对于一些耗时较长,用户无需等待的过程,可以使用异步方法进行处理。使用spring @Async可以实现异步方法

实现:

1.在spring配置文件中加入异步支持

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="http://www.springframework.org/schema/beans    
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd    
    http://www.springframework.org/schema/tx    
    http://www.springframework.org/schema/tx/spring-tx-4.0.xsd   
    http://www.springframework.org/schema/context   
    http://www.springframework.org/schema/context/spring-context-4.0.xsd   
    http://www.springframework.org/schema/mvc   
    http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
    http://www.springframework.org/schema/task
    http://www.springframework.org/schema/task/spring-task-4.0.xsd">

    <context:annotation-config />
    <!--扫描注解 -->
    <context:component-scan base-package="com.xx.yy.*" />
    <!-- 支持异步方法执行 -->
    <task:annotation-driven />
</beans>

2.写异步方法

@Component
public class AsyncTaskTest {
    
    @Async
    public static void doSomething()throws Exception{
        Thread.sleep(10000);
        System.out.println("begin doSomthing....");
        Thread.sleep(10000);
        System.out.println("end doSomthing....");
    }
}

3.调用异步方法

@Controller
public class DebugController {

    @Autowired
    AsyncTaskTest asyncTask;
    
    @RequestMapping("/main")
    public String asynTest() {        
        try {
            System.out.println("我开始执行了!");
            asyncTask.doSomething();            
            System.out.println("我执行结束了!");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "main";
    }
}

4.常见问题

做了1、2、3程序不一定能正确执行异步方法。因为异步方法有可能因为某些问题而失效。常见的异步失效原因有:
1、异步方法和调用类不要在同一个类中
2、注解扫描时,要注意过滤,避免重复实例化,因为存在覆盖问题,@Async就失效了

问题2举例,如果除了applicationContext.xml 中配置了包扫描外,还在dispatcher-Servlet.xml中还配置了包扫描。则会出现异步失效问题。

<context:component-scan base-package="com.xx.yy.*" />

解决方案:
1.在dispatcher-Servlet.xml 中指定扫描某个包

<context:component-scan base-package="com.xx.yy.controller" >
</context:component-scan>

只有@Async异步方法不再该包下才能避免被重复扫描。

2.指定扫描包下的某个标签

<context:component-scan base-package="com.xx.yy.*"
        use-default-filters="false">
        <context:include-filter type="annotation"
            expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

实际上<context:component-scan> 有个属性use-default-filters它的默认值为true,会扫描指定包下的全部的标有@Component的类,并注册成bean.也就是@Component的子注解@Service,@Reposity等。所以如果仅仅是在配置文件中这么写:

<context:component-scan base-package="com.xx.yy.*" >
    <context:include-filter type="annotation"
        expression="org.springframework.stereotype.Controller" />
</context:component-scan>

Use-default-filter此时为true那么会对base-package包或者子包下的所有的进行Java类进行扫描,并把@Component的类的java类注册成bean,所以还是不能避免异步方法所在类被重复扫描。
如果需要指定一些包扫描,一些包不扫描,则需要修改Use-dafault-filter的默认值。
Use-dafault-filters=”false”的情况下:<context:exclude-filter>指定的不扫描,<context:include-filter>指定的扫描。

<context:component-scan base-package="com.xx.yy.*"
        use-default-filters="false">
        <context:include-filter type="annotation"
            expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

-----end-----


http://www.niftyadmin.cn/n/546246.html

相关文章

oracle之sql总结2之groupby having ,where in 别名排序

1、select avg(sal) , max(sal) ,deptno from emp group by deptno; 2、 select avg(sal) , max(sal) ,deptno,job from emp group by deptno,job; 3、 select avg(sal) ,deptno from emp group by deptno having avg(sal)<2000; 转载于:https://www.cnblogs.com/ku…

matlab 绘制原始信号的谐波

这里以锯齿信号为例&#xff1a; clear;clc; figuretime 0:1/20:1000; wave sawtooth(time); subplot(3, 1, 1); plot(time, wave);samples length(wave); sampling 100; ampl zeros(sampling, floor(samples/sampling)); frame 1; for i0:sampling:samplesfirst max(1,…

spark Streaming和storm区别

2019独角兽企业重金招聘Python工程师标准>>> Storm风暴和Spark Streaming火花流都是分布式流处理的开源框架。这里将它们进行比较并指出它们的重要的区别。 处理模型,延迟 虽然这两个框架都提供可扩展性和容错性,它们根本的区别在于他们的处理模型。而Storm处理的是…

SRM533 D2 L3

Problem Statement 这题的描述比较复杂&#xff0c;就不说了。整个过程类似一个游戏&#xff0c;参数有天&#xff0c;生命值&#xff0c;胜利的概率&#xff0c;最后求最大存活的期望天数。 用dp[i][j]表示当前生命值为j&#xff0c;考虑了从i...N这些巫师的攻击。 有一点观察…

一维波动函数动画

我们知道 1-d 波动方程的解的形式为&#xff1a;$ \begin{aligned} u(x, t) & \sum_{n1}^{\infty}\sin(\frac{n\pi x}{L})(A_n\cos(\frac{n\pi ct}{L}) B_n\sin(\frac{n\pi ct}{L})) \\ & \sum_{n1}^{\infty} C_n\sin(\frac{n\pi x}{L})\sin(\frac{n\pi ct}{L} \thet…

postman 使用

2019独角兽企业重金招聘Python工程师标准>>> 安装 安装的是chrome扩展程序。也有软件版本。 怕麻烦每次都要在Chrome的扩展程序中启动&#xff0c;可以在软件启动后&#xff0c;把软件固定到任务栏&#xff0c;详细信息->创建快捷方式 简介 在的web和移动开发&am…

转载-Wireshark过滤语法

1.过滤IP&#xff0c;如来源IP或者目标IP等于某个IP例子:ip.src eq 192.168.1.107 or ip.dst eq 192.168.1.107或者ip.addr eq 192.168.1.107 // 都能显示来源IP和目标IP2.过滤端口例子:tcp.port eq 80 // 不管端口是来源的还是目标的都显示tcp.port 80tcp.port eq 2722tcp.po…

今天思考一个问题 --- 自己的强项是什么??

--- 思考中 --- 经过一天的思考&#xff0c;与探索&#xff1a; 小豆腐的答案是&#xff1a;乒乓球&#xff1f;企业级开发&#xff1f; 当然我想要的答案是企业级开发了。 接下来的第二个问题&#xff1a;如何证明呢&#xff1f; 小豆腐的答案是&#xff1a;操作的特别熟练&am…