Spring源码之Async注解

Spring源码之Async注解spring@Async注解的处理

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

@EnableAsync注解

	/** * 可自定义扫描的注解 */
	Class<? extends Annotation> annotation() default Annotation.class;

	/** * 采用代理的方式,如果设置为true,后续会使用CGLIB进行代理 */
	boolean proxyTargetClass() default false;

	/** * 使用代理的模式 */
	AdviceMode mode() default AdviceMode.PROXY;

	/** * 注解处理的顺序 */
	int order() default Ordered.LOWEST_PRECEDENCE;

ProxyAsyncConfiguration

	@Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AsyncAnnotationBeanPostProcessor asyncAdvisor() { 

//创建一个异步注解处理器
AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
//将从容器中获取到的 Executor 和 ExceptionHandler设置到对象中
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;
}
/** * 获取到注解是否开启异步代理 */
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) { 

this.enableAsync = AnnotationAttributes.fromMap(
importMetadata.getAnnotationAttributes(EnableAsync.class.getName()));
if (this.enableAsync == null) { 

throw new IllegalArgumentException(
"@EnableAsync is not present on importing class " + importMetadata.getClassName());
}
}
/** * 从容器中找到实现了 AsyncConfigurer 类,然后获取到自定义的 线程执行器和异常处理器;默认为null */
@Autowired
void setConfigurers(ObjectProvider<AsyncConfigurer> configurers) { 

//默认会使用第一个配置对象
Supplier<AsyncConfigurer> configurer = SingletonSupplier.of(() -> { 

List<AsyncConfigurer> candidates = configurers.stream().collect(Collectors.toList());
if (CollectionUtils.isEmpty(candidates)) { 

return null;
}
if (candidates.size() > 1) { 

throw new IllegalStateException("Only one AsyncConfigurer may exist");
}
return candidates.get(0);
});
this.executor = adapt(configurer, AsyncConfigurer::getAsyncExecutor);
this.exceptionHandler = adapt(configurer, AsyncConfigurer::getAsyncUncaughtExceptionHandler);
}
//这里会返回一个Supplier对象用于在 AsyncExecutionAspectSupport 当中设置默认的线程池
private <T> Supplier<T> adapt(Supplier<AsyncConfigurer> supplier, Function<AsyncConfigurer, T> provider) { 

return () -> { 

//如果不配置 AsyncConfigurer 这里就会返回null
AsyncConfigurer configurer = supplier.get();
return (configurer != null ? provider.apply(configurer) : null);
};
}

AsyncAnnotationBeanPostProcessor

在这里插入图片描述

1. setBeanFactory()

实现了 BeanFactoryAware 接口,初始化 AsyncAnnotationBeanPostProcessor 时会调用内部的**setBeanFactory() **方法设置切面

在这里插入图片描述

2. postProcessAfterInitialization

方法在容器创建好之后执行,给bean对象创建一个代理对象

AsyncAnnotationAdvisor

	public AsyncAnnotationAdvisor(
@Nullable Supplier<Executor> executor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) { 

Set<Class<? extends Annotation>> asyncAnnotationTypes = new LinkedHashSet<>(2);
//添加注解的类型
asyncAnnotationTypes.add(Async.class);
try { 

asyncAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.ejb.Asynchronous", AsyncAnnotationAdvisor.class.getClassLoader()));
}
catch (ClassNotFoundException ex) { 

}
//构建一个通知对象
this.advice = buildAdvice(executor, exceptionHandler);
//根据注解构造一个切点,切点用于对类进行匹配,匹配了之后真正执行的是 Advice 来进行
//返回一个ComposablePointcut支持多个过滤方式进行匹配,就是将多个ClassFilter和MethodMather进行合并
this.pointcut = buildPointcut(asyncAnnotationTypes);
}

AnnotationAsyncExecutionInterceptor

在这里插入图片描述

	/** * 通过父类的构造器,设置一个默认的线程池的获取方式 */
public AsyncExecutionAspectSupport(@Nullable Executor defaultExecutor, AsyncUncaughtExceptionHandler exceptionHandler) { 

// defaultExecutor就是在 ProxyAsyncConfiguration 中设置的Supplier对象,如果获取不到就调用
this.defaultExecutor = new SingletonSupplier<>(defaultExecutor, () -> getDefaultExecutor(this.beanFactory));
this.exceptionHandler = SingletonSupplier.of(exceptionHandler);
}

1. getExecutorQualifier()

protected String getExecutorQualifier(Method method) { 

//获取到方法上面的注解,获取到vlue值,然后通过value值去确定线程池
Async async = AnnotatedElementUtils.findMergedAnnotation(method, Async.class);
if (async == null) { 

async = AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(), Async.class);
}
return (async != null ? async.value() : null);
}

2. invoke()

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);
//确定异步使用的线程池 默认使用 SimpleAsyncTaskExecutor
AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
if (executor == null) { 

throw new IllegalStateException();
}
//包装成 Callable 类的任务
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());
}

3. determineAsyncExecutor()

protected AsyncTaskExecutor determineAsyncExecutor(Method method) { 

//初始获取的会是null
AsyncTaskExecutor executor = this.executors.get(method);
if (executor == null) { 

Executor targetExecutor;
//调用复写的方法通过注解来获取到对应的value来确定容器中的线程池名称
String qualifier = getExecutorQualifier(method);
if (StringUtils.hasLength(qualifier)) { 

targetExecutor = findQualifiedExecutor(this.beanFactory, qualifier);
}
else { 

//调用默认的 SingletonSupplier 对象来获取到对应的默认线程池。如果设置的对象都没有获取到,就会调用 getDefaultExecutor() 方法
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;
}

4. getDefaultExecutor()

AsyncExecutionInterceptor复写的方法,如果都容器中都没有获取到对应的线程池,那么就返回 SimpleAsyncTaskExecutor

	protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) { 

//调用父类方法去获取线程池
Executor defaultExecutor = super.getDefaultExecutor(beanFactory);
return (defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());
}

面试题

spring中Async注解是使用线程池进行异步处理,还是使用单线程?
答:根据spring容器中配置的 ObjectProvider<AsyncConfigurer> configurers 配置对象进行配置线程池还是单线程进行异步处理;如果没有指定配置对象那么默认就会去容器中查找 TaskExecutor 类型如果抛出异常就会去找名称为 taskExecutor 类型为 Executor 的线程池;如果都没有则使用默认 SimpleAsyncTaskExecutor 单线程进行异步处理

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/157804.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 200个Gmail邀请,要的请留下邮箱地址

    200个Gmail邀请,要的请留下邮箱地址

  • linux 压缩成bz2,linux 将文件压缩成bz2格式 命令:bzip2

    linux 压缩成bz2,linux 将文件压缩成bz2格式 命令:bzip2bzip2命令用于创建和管理(包括解压缩)“.bz2”格式的压缩包。我们遇见Linux压缩打包方法有很多种,以下讲解了Linux压缩打包方法中的Linuxbzip2命令的多种范例供大家查看,相信大家看完后会有很多收获。语法bzip2(选项)(参数)选项-c或——stdout:将压缩与解压缩的结果送到标准输出;-d或——decompress:执行解压缩;-f或-force:bzip2在…

  • 电子基本元件介绍-电容「建议收藏」

    完成电阻的介绍后,接下来对电容进行介绍。0定义电容器(Capacitor,电路中常用C来表示)。两个相互靠近的导体,中间夹一层不导电的绝缘介质,这就构成了电容器。当电容器的两个极板之间加上电压时,电容器就会储存电荷。电容器的电容量在数值上等于一个导电极板上的电荷量与两个极板之间的电压之比。电容器的电容量的基本单位是法拉(F)。电容器往往用于调谐、旁路、耦合、滤波等电路中起着重要的作用。晶体管收音机的调谐电路要用到它,彩色电视机…

  • jquery选择器用法_jQuery属性选择器

    jquery选择器用法_jQuery属性选择器jQuery的选择器一、基本选择器1.ID选择器ID选择器#id就是利用DOM元素的id属性值来筛选匹配的元素,并以iQuery包装集的形式返回给对象。使用公式:$("#id")示例:$("#box")//获取id属性值为box的元素2.元素选择器…

    2022年10月31日
  • Shiro框架学习

    Shiro框架学习shiro (java安全框架) 编辑ApacheShiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。软件名称ApacheShiro开发商Apache性    质Java安全框架主要功能三个核心组件:Subject,SecurityManage…

  • phpstom 激活码2021(最新序列号破解)

    phpstom 激活码2021(最新序列号破解),https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号