spring 的异步处理
1.先解析几个类的用法
1.1 java.lang.annotation.Annotation
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String color() default "red";
}
javac编译之后,interface MyAnnotation extends java.lang.annotation.Annotation 这段表示我自定义的MyAnnotation注解最终是被编译成一个继承java.lang.annotation.Annotation的接口
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync { /**
* 表示可以在这里指定注解类,开启异步操作和@Async同样效果*/
Class<? extends Annotation> annotation() default Annotation.class;
具体原理可以查看:
ProxyAsyncConfiguration
public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
bpp.configure(this.executor, this.exceptionHandler);
Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
bpp.setAsyncAnnotationType(customAsyncAnnotation);
}
bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
return bpp;
}
AsyncAnnotationBeanPostProcessor
@Override
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory); AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);
if (this.asyncAnnotationType != null) {
advisor.setAsyncAnnotationType(this.asyncAnnotationType);
}
advisor.setBeanFactory(beanFactory);
this.advisor = advisor;
}
AsyncAnnotationAdvisor
public void setAsyncAnnotationType(Class<? extends Annotation> asyncAnnotationType) {
Assert.notNull(asyncAnnotationType, "'asyncAnnotationType' must not be null");
Set<Class<? extends Annotation>> asyncAnnotationTypes = new HashSet<>();
asyncAnnotationTypes.add(asyncAnnotationType);
this.pointcut = buildPointcut(asyncAnnotationTypes);
}
protected Pointcut buildPointcut(Set<Class<? extends Annotation>> asyncAnnotationTypes) {
ComposablePointcut result = null;
for (Class<? extends Annotation> asyncAnnotationType : asyncAnnotationTypes) {
Pointcut cpc = new AnnotationMatchingPointcut(asyncAnnotationType, true);
Pointcut mpc = new AnnotationMatchingPointcut(null, asyncAnnotationType, true);
if (result == null) {
result = new ComposablePointcut(cpc);
}
else {
result.union(cpc);
}
result = result.union(mpc);
}
return (result != null ? result : Pointcut.TRUE);
}
1.2.@Role
@see BeanDefinition#ROLE_APPLICATION 通常为用户自定义的bean
* @see BeanDefinition#ROLE_INFRASTRUCTURE 处理bean注册时,内部工作的 例如:生成代理类的配置
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration { @Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
* @see BeanDefinition#ROLE_SUPPORT 支持大配置中的一部分
未找到使用场景
2.配置方法
2.1 @EnableAsync (ProxyAsyncConfiguration)
2.2TaskExecutionAutoConfiguration
3.主要处理类
3.1 AnnotationAsyncExecutionInterceptor
protected Object doSubmit(Callable<Object> task, AsyncTaskExecutor executor, Class<?> returnType) {
if (CompletableFuture.class.isAssignableFrom(returnType)) {
return CompletableFuture.supplyAsync(() -> {
try {
return task.call();
}
catch (Throwable ex) {
throw new CompletionException(ex);
}
}, executor);
}
else if (ListenableFuture.class.isAssignableFrom(returnType)) {
return ((AsyncListenableTaskExecutor) executor).submitListenable(task);
}
else if (Future.class.isAssignableFrom(returnType)) {
return executor.submit(task);
}
else {
executor.submit(task);
return null;
}
}
3.2 获取executor的过程
public Object invoke(final MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
final Method userDeclaredMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
if (executor == null) {
throw new IllegalStateException(
"No executor specified and no default executor set on AsyncExecutionInterceptor either");
}
Callable<Object> task = () -> {
try {
Object result = invocation.proceed();
if (result instanceof Future) {
return ((Future<?>) result).get();
}
}
catch (ExecutionException ex) {
handleError(ex.getCause(), userDeclaredMethod, invocation.getArguments());
}
catch (Throwable ex) {
handleError(ex, userDeclaredMethod, invocation.getArguments());
}
return null;
};
return doSubmit(task, executor, invocation.getMethod().getReturnType());
@Nullable
protected AsyncTaskExecutor determineAsyncExecutor(Method method) {
AsyncTaskExecutor executor = this.executors.get(method);
if (executor == null) {
Executor targetExecutor;
String qualifier = getExecutorQualifier(method);
if (StringUtils.hasLength(qualifier)) {
targetExecutor = findQualifiedExecutor(this.beanFactory, qualifier);
}
else {
targetExecutor = this.defaultExecutor.get();
}
if (targetExecutor == null) {
return null;
}
executor = (targetExecutor instanceof AsyncListenableTaskExecutor ?
(AsyncListenableTaskExecutor) targetExecutor : new TaskExecutorAdapter(targetExecutor));
this.executors.put(method, executor);
}
return executor;
}
protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) {
Executor defaultExecutor = super.getDefaultExecutor(beanFactory);
return (defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());
}
//super.getDefaultExecutor(beanFactory);
return beanFactory.getBean(TaskExecutor.class);
常用的Executor的几个种类,和转换
public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport
implements AsyncListenableTaskExecutor, SchedulingTaskExecutor { public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
implements AsyncListenableTaskExecutor, Serializable { Executor targetExecutor;
new TaskExecutorAdapter(targetExecutor)
注意 TaskDecorator 应用场景1.thread中 traceId往子线程中传递可以在在这个任务修饰器中完成
class MdcTaskDecorator implements TaskDecorator {
@Override
public Runnable decorate(Runnable runnable) {
Map<String, String> contextMap = MDC.getCopyOfContextMap();
Runnable runnable1 = new Runnable() {
@Override
public void run() {
if (contextMap != null) {
MDC.setContextMap(contextMap);
}
runnable.run();
}
};
return runnable1;
}
}
@Slf4j
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer { @Bean
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("async-pool-");
executor.setTaskDecorator(new MdcTaskDecorator());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
} @Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (throwable, method, params) -> {
log.error("异步任务异常:方法:{} 参数:{}", method.getName(), JSON.toJSONString(params));
log.error(throwable.getMessage(), throwable);
};
}
}
spring 的异步处理的更多相关文章
- Spring mvc异步处理
基于Servlet3.0的异步处理,springmvc的异步处理 控制器返回callable, spring mvc异步处理,将callable提交到TaskExecutor 使用一个隔离线程进行执 ...
- Spring MVC 异步处理请求,提高程序性能
原文:http://blog.csdn.net/he90227/article/details/52262163 什么是异步模式 如何在Spring MVC中使用异步提高性能? 一个普通 Servle ...
- Spring Boot系列二 Spring @Async异步线程池用法总结
1. TaskExecutor Spring异步线程池的接口类,其实质是java.util.concurrent.Executor Spring 已经实现的异常线程池: 1. SimpleAsyncT ...
- spring启动异步线程
大纲: spring启动异步线程 spring配置线程池 一.spring启动异步线程 spring启动异步线程方法就是在方法上加上注解@Async,然后启动类或配置类上加上注解@EnableAsyn ...
- Spring中异步注解@Async的使用、原理及使用时可能导致的问题
前言 其实最近都在研究事务相关的内容,之所以写这么一篇文章是因为前面写了一篇关于循环依赖的文章: <面试必杀技,讲一讲Spring中的循环依赖> 然后,很多同学碰到了下面这个问题,添加了S ...
- Spring DeferredResult 异步请求
Spring DeferredResult 异步请求 一.背景 二.分析 三.实现要求 四.后端代码实现 五.运行结果 1.超时操作 2.正常操作 六.DeferredResult运行原理 六.注意事 ...
- 基于Spring的异步系统实现方案
一般的实现方案 发送异步消息所使用的工具类: import java.util.Date; import javax.jms.Destination; import javax.jms.JMSExce ...
- Spring @EventListener 异步中使用condition的问题
@EventListener是spring在4.2+推出的更好的使用spring事件架构的方式,并且异步方式也很好设定 但是在spring4.2.7版本上使用eventlistener的conditi ...
- 深入理解Spring的异步机制
一.Spring中实现异步执行 在这里我先以事件的机制举例,注意默认情况下事件的发布与监听都是同步执行的.那么我们来看一看基于异步事件的例子该怎么写 首先还是定义事件: package com.bdq ...
- Spring MVC 异步测试
从spring3.2开始,支持servlet3的异步请求,这对于处理耗时的请求如缓慢的数据库查询是非常有好处的,不至于很快的耗光servlet的线程池,影响可扩展性. 让我们先来了解一下servlet ...
随机推荐
- mysql远程连接失败的两种解决方法
---恢复内容开始--- (这是转载别人的,因为我觉得很有用,每次都是参考这个的第二种方法解决的,不管你听不听得到,先说声谢谢!也记下来方便大家看看) mysql解决远程不能访问的二种方法,需要的朋友 ...
- 假期学习【一】Ubuntu中Linux的基础操作
题目: Linux 系统的安装和常用命令 姓名: 赵路仓 日期: 2020.1.24 实验环境: Ubuntu 实验内容与完成情况: (1)切换到目录 /usr/bin: (2)查看目录/usr/lo ...
- 【转载】SpringMVC前台给后台传值的方式
转自:http://blog.csdn.net/flymoringbird/article/details/53126505 1. 基本数据类型(以int为例,其他类似): Controller代码: ...
- lib目录和maven dependency目录的jar包冲突
用eclipse时新建项目时,会在lib目录下自动生成一些jar包,然后又在pom.xml文件中添加了依赖,导致lib下的jar包和maven dependency目录下的jar包产生了冲突.刚开始r ...
- JUC-线程间通信
面试题: 两个线程,一个线程打印1-52,另一个打印字母A-Z打印顺序为12A34B...5152Z, 要求用线程间通信 线程间通信:1.生产者+消费者2.通知等待唤醒机制 多线程编程模版中 1.判断 ...
- Android开发之JDK配置,及ADT下载
第一步: 到官网上下载jdk,记住关键的一点,首先要查看自己的windows电脑是32位的还是64位的,这里想下载相应的位数的jdk 第二步: 安装JDK,一般默认安装路径,不做自己修改安装路径,如: ...
- ScrollView示例(转载)
// 初始化var scrollView = new ccui.ScrollView(); // 设置方向scrollView.setDirection(ccui.ScrollView.DIR_VER ...
- python3 yield实现假的多并发
import time def fun1(): while True: print("fun1") time.sleep(0.1) yield def fun2(): while ...
- codis安装以及启动
https://blog.csdn.net/ygd266/article/details/78469654
- npx工具
参考文章:阮一峰的网络日志 - npx 使用教程 npx的作用 1.调用项目模块 即node_modules目录下的模块,而不用加上相对路径 $ npx mocha --version 原本应该是这样 ...