目录
二、AsyncAnnotationBeanPostProcessor
前言
在spring框架中,我们可以使用async注解实现方法的异步执行,但是如果不了解内部源码的运行机制,也会导致很多问题,比如默认线程池的问题,async导致循环依赖报错的问题等,本篇文章主要分析async任务执行的全流程,并给出自定义异步线程池的方法,关于循环依赖相关内容会在下篇文章中给出。
一、@EnableAsync
首先从EnableAsync注解进行分析,主要是引入了ProxyAsyncConfiguration类。
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {}
public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
@Override
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;
}
}
}
ProxyAsyncConfiguration本身是一个Configuration类,通过@Bean的方式引入了AsyncAnnotationBeanPostProcessor。
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration {
@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();
Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
bpp.setAsyncAnnotationType(customAsyncAnnotation);
}
//将ProxyAsyncConfiguration中的executor赋值给AsyncAnnotationBeanPostProcessor,executor通过AbstractAsyncConfiguration中的setConfigurers方法
//在自定义的AsyncConfigurer类中的getAsyncExecutor方法获取。
if (this.executor != null) {
bpp.setExecutor(this.executor);
}
if (this.exceptionHandler != null) {
bpp.setExceptionHandler(this.exceptionHandler);
}
bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
return bpp;
}
}
ProxyAsyncConfiguration继承了AbstractAsyncConfiguration ,同样是一个Configuration类,通过setConfigurers调用容器中的AsyncConfigurer的getAsyncExecutor方法,可以创建自定义线程池。这个方法的在registerBeanPostProcessors中创建AsyncAnnotationBeanPostProcessor 时调用,此时可以保证容器内的beandefination已经加载完毕,可以确保自定义异步线程池已经在容器中。
@Configuration
public abstract class AbstractAsyncConfiguration implements ImportAware {
protected Executor executor;
protected AsyncUncaughtExceptionHandler exceptionHandler;
/**
* Collect any {@link AsyncConfigurer} beans through autowiring.
* 自动注入容器中的AsyncConfigurer
*/
@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();
//调用容器中的AsyncConfigurer的getAsyncExecutor方法,可以在此处构建自定义异步线程池
this.executor = configurer.getAsyncExecutor();
this.exceptionHandler = configurer.getAsyncUncaughtExceptionHandler();
}
}
二、AsyncAnnotationBeanPostProcessor
在AsyncAnnotationBeanPostProcessor初始化的过程中,由于实现了BeanFactoryAware接口,所以会调用setBeanFactory方法。
exposedObject = initializeBean(beanName, exposedObject, mbd);
invokeAwareMethods(beanName, bean);
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
//调用setBeanFactory方法
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
在setBeanFactory方法中主要创建了一个AsyncAnnotationAdvisor对象,为后面的代理做准备。
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
//创建advisor,将AsyncAnnotationBeanPostProcessor中的引入线程池赋值给AnnotationAsyncExecutionInterceptor的默认线程池
AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);
if (this.asyncAnnotationType != null) {
advisor.setAsyncAnnotationType(this.asyncAnnotationType);
}
advisor.setBeanFactory(beanFactory);
this.advisor = advisor;
}
}
在构建AsyncAnnotationAdvisor对象的过程中引入了AnnotationAsyncExecutionInterceptor,这也时后续执行过程中的拦截器。
public AsyncAnnotationAdvisor(Executor executor, AsyncUncaughtExceptionHandler exceptionHandler) {
//构建切面切点
this.advice = buildAdvice(executor, this.exceptionHandler);
this.pointcut = buildPointcut(asyncAnnotationTypes);
}
protected Advice buildAdvice(Executor executor, AsyncUncaughtExceptionHandler exceptionHandler) {
return new AnnotationAsyncExecutionInterceptor(executor, exceptionHandler);
}
AbstractAdvisingBeanPostProcessor的postProcessAfterInitialization方法中完成了代理对象创建。
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof AopInfrastructureBean) {
// Ignore AOP infrastructure such as scoped proxies.
return bean;
}
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;
}
}
if (isEligible(bean, beanName)) {
//基于advisor创建代理对象
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;
}
三、AsyncExecutionInterceptor
执行的主要逻辑在AsyncExecutionInterceptor的invoke方法,基本就是构建Callable对象,然后放入线程池中执行。
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 = new Callable<Object>() {
@Override
public Object call() throws Exception {
try {
Object result = invocation.proceed();
if (result instanceof Future) {
return ((Future<?>) result).get();
}
}
return null;
}
};
//执行任务
return doSubmit(task, executor, invocation.getMethod().getReturnType());
}
获取线程池首先获取异步拦截器的默认线程池,也就是拦截器创建时赋值的默认线程池,没有赋值时获取容易内的默认线程池,如果没有就会新建线程池。
protected AsyncTaskExecutor determineAsyncExecutor(Method method) {
AsyncTaskExecutor executor = this.executors.get(method);
if (executor == null) {
}
else {
//获取配置的异步线程池
targetExecutor = this.defaultExecutor;
if (targetExecutor == null) {
synchronized (this.executors) {
if (this.defaultExecutor == null) {
//获取默认线程池,没有的话自行创建SimpleAsyncTaskExecutor,但是SimpleAsyncTaskExecutor每次提交都会开启新线程,最好添加自己的线程池
//在beanFactory中获取TaskExecutor,需要让当前bean能够感知beanFactory,所以需要实现BeanFactoryAware接口
this.defaultExecutor = getDefaultExecutor(this.beanFactory);
}
targetExecutor = this.defaultExecutor;
}
}
}
this.executors.put(method, executor);
}
return executor;
}
spring默认创建的是SimpleAsyncTaskExecutor线程池,该线程池在执行任务的时候会直接新建一个线程执行,且没有线程数上限,不宜使用。
protected Executor getDefaultExecutor(BeanFactory beanFactory) {
//获取容器中的TaskExecutor类
Executor defaultExecutor = super.getDefaultExecutor(beanFactory);
//新建SimpleAsyncTaskExecutor线程池
return (defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());
}
protected void doExecute(Runnable task) {
//新建线程执行
Thread thread = (this.threadFactory != null ? this.threadFactory.newThread(task) : createThread(task));
thread.start();
}
public Thread createThread(Runnable runnable) {
Thread thread = new Thread(getThreadGroup(), runnable, nextThreadName());
thread.setPriority(getThreadPriority());
thread.setDaemon(isDaemon());
return thread;
}
根据异步任务不同的返回值形式,会调用不同的方法执行任务。
protected Object doSubmit(Callable<Object> task, AsyncTaskExecutor executor, Class<?> returnType) {
if (completableFuturePresent) {
Future<Object> result = CompletableFutureDelegate.processCompletableFuture(returnType, task, executor);
if (result != null) {
return result;
}
}
//返回值是ListenableFuture
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;
}
}
四、自定义异步线程池
在执行在实际项目中,一般通过继承AsyncConfigureSupport的方式,指定程序中使用的异步线程池,从而避免使用默认的线程池。
public class AsyncExecutorConfig extends AsyncConfigurerSupport {
//设置异步线程池
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//配置核心线程数
executor.setCorePoolSize(20);
//配置最大线程数
executor.setMaxPoolSize(50);
//配置队列大小
executor.setQueueCapacity(999);
executor.setKeepAliveSeconds(60 * 15);
executor.setThreadNamePrefix("-async-getAsyncExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//执行初始化
executor.initialize();
return executor;
}
}
五、TaskDecorator
有些情况下,我们需要在主线程和子线程之间传递变量,spring提供了TaskDecorator接口,一般用于日志,用户信息传递。在decorate方法中,对Runnable对象进行包装,可以先行获取主线程中线程本地变量的值,在对子线程进行赋值,注意最后要情况线程本地变量情况,避免内存泄漏。
public class ContextCopyingDecorator implements TaskDecorator {
@Override
public Runnable decorate(Runnable runnable) {
try {
Integer data = DataHolder.getData();
return () -> {
try {
DataHolder.setData(data);
runnable.run();
} finally {
DataHolder.removeData();
}
};
} catch (IllegalStateException e) {
return runnable;
}
}
}
public class DataHolder {
private static final ThreadLocal<Integer> CURRENT_USER_THREAD_LOCAL = new ThreadLocal<>();
public static void setData(Integer num) {
CURRENT_USER_THREAD_LOCAL.set(num);
}
public static Integer getData() {
Integer num = CURRENT_USER_THREAD_LOCAL.get();
if (num == null) {
return null;
}
return num;
}
public static void removeData() {
CURRENT_USER_THREAD_LOCAL.remove();
}
}
要在initializeExecutor方法中,新建ThreadPoolExecutor,在有TaskDecorator存在的情况下,回对execute方法进行重写,对任务进行包装。
protected ExecutorService initializeExecutor(
ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
BlockingQueue<Runnable> queue = createQueue(this.queueCapacity);
ThreadPoolExecutor executor;
if (this.taskDecorator != null) {
executor = new ThreadPoolExecutor(
this.corePoolSize, this.maxPoolSize, this.keepAliveSeconds, TimeUnit.SECONDS,
queue, threadFactory, rejectedExecutionHandler) {
@Override //重写execute方法,使用装饰器装饰
public void execute(Runnable command) {
super.execute(taskDecorator.decorate(command));
}
};
}
return executor;
}
总结
本文主要分析了spring中异步任务的创建和执行流程,并且实现了自定义异步线程池,关于异步任务导致的循环依赖问题将在接下来的文章中分析