@EnableAsync ,@Async 源码分析

在Springboot 项目中,使用 @EnableAsync  可以开启异步请求 ,使用 @Async   可以标注需要异步执行的方法,那到底是如何实现的的呢?

首先:从入口 @EnableAsync 源码查看

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {

	
	Class annotation() default Annotation.class;

	
	boolean proxyTargetClass() default false;

	
	AdviceMode mode() default AdviceMode.PROXY;

	
	int order() default Ordered.LOWEST_PRECEDENCE;

}

 

代码中声明了:

AdviceMode mode() default AdviceMode.PROXY;

并且导入了:AsyncConfigurationSelector.class

查看 AsyncConfigurationSelector    继承 AdviceModeImportSelector , AdviceModeImportSelector 实现了 ImportSelector ,

ImportSelector 接口只有一个方法:作用是根据参数AnnotationMetadata ,确定应该使用哪个配置类。

public interface ImportSelector {

	/**
	 * Select and return the names of which class(es) should be imported based on
	 * the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
	 */
	String[] selectImports(AnnotationMetadata importingClassMetadata);

}

继续回来查看 AsyncConfigurationSelector 重写了 selectImports 方法,根据参数AdviceMode的值选择:ProxyAsyncConfiguration 还是 AspectJAsyncConfiguration,参数AdiviceMode 是根据 EnableAsync#mode的值确定,前面看到 EnableAsync 定义的mode 为 AdviceMode.PROXY 。

进入到 ProxyAsyncConfiguration , 继承了 AbstractAsyncConfiguration , 声明了一个Bean。

AbstractAsyncConfiguration 实现了 ImportAware 接口,

有两个方法 setImportMetadata ,setConfigurers

setImportMetadata 是实现接口ImportAware的方法,在方法中获取可以获取 EnableAsync 的注解属性,并赋值到 AbstractAsyncConfiguration 的属性 enableAsync 上 。
	@Override
	public void setImportMetadata(AnnotationMetadata importMetadata) {
		this.enableAsync = AnnotationAttributes.fromMap(
				importMetadata.getAnnotationAttributes(EnableAsync.class.getName(), false));
		if (this.enableAsync == null) {
			throw new IllegalArgumentException(
					"@EnableAsync is not present on importing class " + importMetadata.getClassName());
		}
	}

方法 setConfigurers 代码如下:

	/**
	 * Collect any {@link AsyncConfigurer} beans through autowiring.
	 */
	@Autowired(required = false)
	void setConfigurers(Collection 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;
	}

从spring 容器中获取configurers ,并赋值给 executor,exceptionHandler ,跟进AsyncConfigurer 实现类,发现其返回的都是null,所以暂时不管。此时 AbstractAsyncConfiguration 里面只包含 EnableAsync 注解属性的值,其他什么都没干,继续返回 ProxyAsyncConfiguration ,跟进 AsyncAnnotationBeanPostProcesson 。

@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();
		bpp.configure(this.executor, this.exceptionHandler);
		Class 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.getNumber("order"));
		return bpp;
	}

从源码中看出看到实例化的 AsyncAnnotationBeanPostProcessor 主要是根据 EnableAsync 配置信息 , EnableAsync 默认配置信息如下:

annotation:Annotation.class
proxyTargetClass:false 
order:Ordered.LOWEST_PRECEDENCE

至此,好像没有了头绪,实例化AsyncAnnotationBeanPostProcessor 就没了,只能继续看看AsyncAnnotationBeanPostProcessor 干了什么操作了,查看该类的类图和方法列表如下:

@EnableAsync ,@Async 源码分析_第1张图片

@EnableAsync ,@Async 源码分析_第2张图片

该类的父类实现了BeanFactoryAware接口,该接口声明的方法 setBeanFactory 会在初始化Bean的时候执行,去查看该类的 setBeanFactory 方法如下:

@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;
	}

 

未完,待续

你可能感兴趣的:(springboot)