EnableAsync注解异步源码分析

源码分析以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~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值