源码分析以5.2.15_ReELEASE版本为准
EnableAsync注解是一个很有代表性的springboot编程模式的实现,通过这个源码分析可以从中学到线程池相关的设计和AOP相关知识;
代码入口
我们开启异步一般我们是在启动类上添加 @EnableAsync注解
EnableAsync类定义
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {
Class<? extends Annotation> annotation() default Annotation.class;
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default Ordered.LOWEST_PRECEDENCE;
}
从代码上看EnableAsync 是一 Import的组合注解,也就是说你可以把它当成Import注解(如果对组合注解不了解这个可以看我的这篇 【Spring 组合注解】),但是还额外提供了一些配置属性:
annotation()、proxyTargetClass()、mode()、order()
熟悉spring boot/spring 源码的同学知道,@Import注解会被ConfigurationClassPostProcessor 进行处理,其是工厂级别的后置处理器;其解析的时机可以参看我另一篇文章【Spring之ConfigurationClassPostProcessor配置类后置处理器源码分析】
AsyncConfigurationSelector
AsyncConfigurationSelector是@Import默认引入的类,这个类的继承关系很简单,如下:
这个类核心方法是向容器返回了一个ProxyAsyncConfiguration类
public String[] selectImports(AdviceMode adviceMode) {
// @A
switch (adviceMode) {
case PROXY:
return new String[] {ProxyAsyncConfiguration.class.getName()};
case ASPECTJ:
return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
default:
return null;
}
}
@A:跟代码这里默认会走 case PROXY 分支
ProxyAsyncConfiguration
来看一下类图,继承关系也比较简单
父类 AbstractAsyncConfiguration的setConfigurers方法如下:
@Autowired(required = false)
void setConfigurers(Collection<AsyncConfigurer> configurers) {
if (CollectionUtils.isEmpty(configurers)) {
return;
}
if (configurers.size() > 1) {
throw new IllegalStateException("Only one AsyncConfigurer may exist");
}
AsyncConfigurer configurer = configurers.iterator().next();
this.executor = configurer::getAsyncExecutor;
this.exceptionHandler = configurer::getAsyncUncaughtExceptionHandler;
}
这里使用Autowired方式将AsyncConfigurer的实例在初始化完成后注入进来,这里我猜测主要的价值在自定义扩展executor 和exceptionHandler
我们回到ProxyAsyncConfiguration类,它提供了一个bean配置
@Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
// @A
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;
}
@A:这个配置核心是向容器中注册一个bean级别的后置处理器AsyncAnnotationBeanPostProcessor,然后根据具体情况向其设置executor和exceptionHandler
其中executor和exceptionHandler是通过AsyncConfigurer配置注入的
AsyncAnnotationBeanPostProcessor
后置处理器类图如下,有点复杂
这个子类提供api主要有
1、设置Executor和ExceptionHandler
2、设置自定义注解标记
3、重写父类的setBeanFactory方法因为父类AbstractBeanFactoryAwareAdvisingPostProcessor实现了BeanFactoryAware接口
其中第3个是一个需要重点关注的方法
@Override
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
// @A
AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);
if (this.asyncAnnotationType != null) {
advisor.setAsyncAnnotationType(this.asyncAnnotationType);
}
advisor.setBeanFactory(beanFactory);
this.advisor = advisor;
}
@A:初始化一个AsyncAnnotationAdvisor并设置成这个后置处理器的advisor 属性
我们知道bean级别的后置处理器是在postProcessAfterInitialization这个方法将原对象进行apo封装的,这个方法被封装到了其父类AbstractAdvisingBeanPostProcessor里
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
// @A
if (this.advisor == null || bean instanceof AopInfrastructureBean) {
// Ignore AOP infrastructure such as scoped proxies.
return bean;
}
// @B
if (bean instanceof Advised) {
Advised advised = (Advised) bean;
if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
// Add our local Advisor to the existing proxy's Advisor chain...
if (this.beforeExistingAdvisors) {
advised.addAdvisor(0, this.advisor);
}
else {
advised.addAdvisor(this.advisor);
}
return bean;
}
}
// @C
if (isEligible(bean, beanName)) {
ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
if (!proxyFactory.isProxyTargetClass()) {
evaluateProxyInterfaces(bean.getClass(), proxyFactory);
}
proxyFactory.addAdvisor(this.advisor);
customizeProxyFactory(proxyFactory);
return proxyFactory.getProxy(getProxyClassLoader());
}
// No proxy needed.
return bean;
}
@A:是AopInfrastructureBean的子类
@B:是 Advised 的子类(其实在Spring AOP中,无论是基于JDK动态代理的代理对象,还是基于CGLIB的代理对象,他们最终都实现了这个接口);可参看文章【Spring AOP编程官方文档解读之操作Advised对象】
@C:经检测,如果该对象需要被包装
创建代理的线梳理结束了,我们回来看看advisor的逻辑,核心逻辑都在这个里面;
AsyncAnnotationAdvisor
这个类里主要属性有:
- private Advice advice;
- private Pointcut pointcut;
这是一个很标准的Advisor,即Advisor = advice + pointcut,这些顶级类设计与其所扮演的角色可以看这里的解释:【AOP名词解释Advice,Pointcut,Advisor,Joinpoint,Advised是什么?】
我们来看看核心方法:org.springframework.scheduling.annotation.AsyncAnnotationAdvisor#buildAdvice
protected Advice buildAdvice(
@Nullable Supplier<Executor> executor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
// @A
AnnotationAsyncExecutionInterceptor interceptor = new AnnotationAsyncExecutionInterceptor(null);
// @B
interceptor.configure(executor, exceptionHandler);
return interceptor;
}
@A:这里创建了一个AnnotationAsyncExecutionInterceptor
@B:把executor和exceptionHandler设置进AnnotationAsyncExecutionInterceptor
AnnotationAsyncExecutionInterceptor
看来核心逻辑就在AnnotationAsyncExecutionInterceptor里了,其实现了MethodInterceptor接口我们看看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);
// @A
AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
if (executor == null) {
throw new IllegalStateException(
"No executor specified and no default executor set on AsyncExecutionInterceptor either");
}
// @B
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;
};
// @C
return doSubmit(task, executor, invocation.getMethod().getReturnType());
}
@A:确定线程池AsyncTaskExecutor 对象
@B:封装一个Callable
@C:调用doSubmit方法
doSubmit方法如下
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;
}
}
这里根据方法的返回时是CompletableFuture、ListenableFuture、Future等做不同处理
over~