Spring Async异步处理源码解读
小编微信:372787553 进入社区交流群
在项目想实用异步的处理方式时,spring为我们提供了解决方案,就在在类或者方法上添加@Async的注解,当然如果写在类上代表整个类都是异步处理的方式,今天我们就来揭晓一下为何在方法上添加一个@Async的注解就可以让方法变成异步处理的方式.本文的分析,是基于spring 5.2.6.RELEASE | 2.3.1.RELEASE的版本进行分析学习
EnableAsync
在spring中,如果你想实用@Async的功能,需要在启动类添加@EnableAsync
@EnableAsync
@SpringBootApplication
public class OkHttpAppStart {
public static void main(String[] args) {
SpringApplication.run(OkHttpAppStart.class, args);
}
}
我们来看看为甚在启动类添加了此注解就可以将方法变成异步的,它到底做了什么?
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 重点在这里 async的配置类
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {
/**
* 指示要在类或方法级别检测的“异步”注释类型。
* 此属性的存在使得开发人员可以提供自己的自定义注释类型,以指示应异步调用方法(或给定类的所有方法)
*/
Class<? extends Annotation> annotation() default Annotation.class;
boolean proxyTargetClass() default false;
/**
*
* 指示应如何应用异步建议。
* 默认值为AdviceMode.PROXY。请注意,代理模式仅允许通过代理拦截呼叫。
* 同一类中的本地调用不能以这种方式被拦 截;在本地调用中,对这样的方法的Async注释将被忽略,
* 因为Spring的拦截器甚至不参与这样的运行时场景。对于更高级的拦截模式,
* 请考虑将其切换到AdviceMode.ASPECTJ。
*
*/
AdviceMode mode() default AdviceMode.PROXY;
/**
* 直接加载顺序,
*/
int order() default Ordered.LOWEST_PRECEDENCE;
}
AsyncConfigurationSelector
public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
/**
* Returns {@link ProxyAsyncConfiguration} or {@code AspectJAsyncConfiguration}
* for {@code PROXY} and {@code ASPECTJ} values of {@link EnableAsync#mode()},
* respectively.
*/
@Override
@Nullable
public String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {ProxyAsyncConfiguration.class.getName()};
case ASPECTJ:
return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
default:
return null;
}
}
}
默认走的是PROXY,通过ProxyAsyncConfiguration生成AsyncAnnotationBeanPostProcessor对象
AsyncAnnotationBeanPostProcessor
public class AsyncAnnotationBeanPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor {
/**
* The default name of the {@link TaskExecutor} bean to pick up: "taskExecutor".
* <p>Note that the initial lookup happens by type; this is just the fallback
* in case of multiple executor beans found in the context.
* @since 4.2
* @see AnnotationAsyncExecutionInterceptor#DEFAULT_TASK_EXECUTOR_BEAN_NAME
* 这是线程的默认值
*/
public static final String DEFAULT_TASK_EXECUTOR_BEAN_NAME =
AnnotationAsyncExecutionInterceptor.DEFAULT_TASK_EXECUTOR_BEAN_NAME;
protected final Log logger = LogFactory.getLog(getClass());
// 线程执行器
@Nullable
private Supplier<Executor> executor;
// 异常处理器
@Nullable
private Supplier<AsyncUncaughtExceptionHandler> exceptionHandler;
// 扫描注解的类型
@Nullable
private Class<? extends Annotation> asyncAnnotationType;
// ...
// 生成代理对象,回调后 AsyncAnnotationAdvisor对象
@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
//构建 异步advisor
public AsyncAnnotationAdvisor(
@Nullable Supplier<Executor> executor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
Set<Class<? extends Annotation>> asyncAnnotationTypes = new LinkedHashSet<>(2);
//@Async注解作为切点
asyncAnnotationTypes.add(Async.class);
try {
asyncAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.ejb.Asynchronous", AsyncAnnotationAdvisor.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
// If EJB 3.1 API not present, simply ignore.
}
//赋值advice 为 AnnotationAsyncExecutionInterceptor
//会将 线程执行器和异常处理器放入进去,不过我们一般不去自定义的话,这个时候是null,他会处理走默认的
this.advice = buildAdvice(executor, exceptionHandler);
//根据@Async生成对应的切点
this.pointcut = buildPointcut(asyncAnnotationTypes);
}
AsyncExecutionAspectSupport.buildAdvice
创建AnnotationAsyncExecutionInterceptor
protected Advice buildAdvice(
@Nullable Supplier<Executor> executor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
AnnotationAsyncExecutionInterceptor interceptor = new AnnotationAsyncExecutionInterceptor(null);
interceptor.configure(executor, exceptionHandler);
return interceptor;
}
这里需要追溯到父类AsyncExecutionAspectSupport类
public AsyncExecutionAspectSupport(@Nullable Executor defaultExecutor) {
this.defaultExecutor = new SingletonSupplier<>(defaultExecutor, () -> getDefaultExecutor(this.beanFactory));
this.exceptionHandler = SingletonSupplier.of(SimpleAsyncUncaughtExceptionHandler::new);
}
getDefaultExecutor(this.beanFactory));方法就是会去获取默认的线程执行器 会先去单例池中获取,如果没有才会自己创建。 在下方会调用到!
getDefaultExecutor的大概逻辑就是:
先去spring容器中获取 TaskExecutor.class 的实例 -> 没有再去spring容器中获取beanName = "taskExecutor" 的实例
protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) {
if (beanFactory != null) {
try {
return beanFactory.getBean(TaskExecutor.class);
}
catch (NoUniqueBeanDefinitionException ex) {
logger.debug("Could not find unique TaskExecutor bean", ex);
try {
return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
}
catch (NoSuchBeanDefinitionException ex2) {
}
}
catch (NoSuchBeanDefinitionException ex) {
logger.debug("Could not find default TaskExecutor bean", ex);
try {
return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
}
catch (NoSuchBeanDefinitionException ex2) {
}
// Giving up -> either using local default executor or none at all...
}
}
return null;
}
再没有 自己去创建 new SimpleAsyncTaskExecutor()
返回到子类AsyncExecutionInterceptor
protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) {
Executor defaultExecutor = super.getDefaultExecutor(beanFactory);
return (defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());
}
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());
}
protected AsyncTaskExecutor determineAsyncExecutor(Method method) {
AsyncTaskExecutor executor = this.executors.get(method);
if (executor == null) {
Executor targetExecutor;
//根据@Async注解上value值 ,判断是否有指定的TaskExecutor或Executor执行器
String qualifier = getExecutorQualifier(method);
if (StringUtils.hasLength(qualifier)) {
targetExecutor = findQualifiedExecutor(this.beanFactory, qualifier);
}
else {
//调用 表达式方法 这个get实际上调用方法是 getDefaultExecutor(this.beanFactory))
//如果没有在spring容器中创建线程池的单例的话 拿到的是 SimpleAsyncTaskExecutor()对象
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 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);
}
//ListenableFuture 类型
else if (ListenableFuture.class.isAssignableFrom(returnType)) {
return ((AsyncListenableTaskExecutor) executor).submitListenable(task);
}
//Future类型
else if (Future.class.isAssignableFrom(returnType)) {
return executor.submit(task);
}
else {
//直接 执行
executor.submit(task);
return null;
}
}