目录
1、@Async
2、ProxyAsyncConfiguration
1)、实现ImportAware
2)、AsyncAnnotationBeanPostProcessor
3、AsyncAnnotationBeanPostProcessor
4、AnnotationAsyncExecutionInterceptor
1)、获取线程池(determineAsyncExecutor)
2)、执行任务(doSubmit)
5、SimpleAsyncTaskExecutor
之前编程都是自定义new ThreadPoolExecutor(。。。),并调用invokeAll等进行并发编程。后面发现只要在方法上添加@Async注解,并使用@EnableAsync进行开启,并且@since为Spring 3.1版本。我使用的Spring 5版本的,默认会使用SimpleAsyncTaskExecutor类型。就是一个大坑。
@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;
}
与之前分析@EnableTransactionManagement一样,属性都差不多。使用@Import方式将AsyncConfigurationSelector注册为bean。实现了ImportSelector接口,可以参见(Spring源码-ImportSelector实现分析)。
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;
}
}
@EnableAsync上没有配置mode,则默认使用jdk方式实现。返回ProxyAsyncConfiguration将其注入为bean。
则在ProxyAsyncConfiguration初始化为bean时,会进行回调,实现方法如下:
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());
}
}
获取@EnableAsync注解上的配置信息,并保存到 enableAsync属性中。
将 AsyncAnnotationBeanPostProcessor初始化为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();
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.getNumber("order"));
return bpp;
}
实现了很多Aware接口,注入了BeanFactory和BeanClassLoader,主要是在setBeanFactory方法中:
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;
}
new 了一个AsyncAnnotationAdvisor,而线程池和异常处理器是从初始化 ProxyAsyncConfiguration时传入的,默认都为null。构造器如下:
public AsyncAnnotationAdvisor(@Nullable Supplier executor,
@Nullable Supplier exceptionHandler) {
Set> asyncAnnotationTypes = new LinkedHashSet<>(2);
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.
}
this.advice = buildAdvice(executor, exceptionHandler);
this.pointcut = buildPointcut(asyncAnnotationTypes);
}
buildAdvice:构建拦截器
protected Advice buildAdvice(@Nullable Supplier executor,
@Nullable Supplier exceptionHandler) {
AnnotationAsyncExecutionInterceptor interceptor = new AnnotationAsyncExecutionInterceptor(null);
interceptor.configure(executor, exceptionHandler);
return interceptor;
}
初始化了一个AnnotationAsyncExecutionInterceptor 拦截器,后续进行分析。使用有参构造,但是异步任务的线程池为null。
buildPointcut:根据Async构建拦截匹配点
protected Pointcut buildPointcut(Set> asyncAnnotationTypes) {
ComposablePointcut result = null;
// asyncAnnotationTypes默认只要Async类型
for (Class extends Annotation> asyncAnnotationType : asyncAnnotationTypes) {
Pointcut cpc = new AnnotationMatchingPointcut(asyncAnnotationType, true);
Pointcut mpc = new AnnotationMatchingPointcut(null, asyncAnnotationType, true);
if (result == null) {
// result肯定是null,先添加Class类型的切点匹配器
result = new ComposablePointcut(cpc);
} else {
result.union(cpc);
}
// 再添加Method类型的切点拦截器
result = result.union(mpc);
}
return (result != null ? result : Pointcut.TRUE);
}
默认情况下 asyncAnnotationTypes中只要Async类型,则初始化了配置Async的类和方法的 匹配拦截器(AnnotationMatchingPointcut),并且都添加到ComposablePointcut中。
一切初始化完成后,在每个bean的生命周期都会进行回调 postProcessAfterInitialization方法:
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (this.advisor == null || 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)) {
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;
}
protected ProxyFactory prepareProxyFactory(Object bean, String beanName) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
proxyFactory.setTarget(bean);
return proxyFactory;
}
显然核心实现在 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);
AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
if (executor == null) {
throw new IllegalStateException(
"No executor specified and no default executor set on " +
" AsyncExecutionInterceptor either");
}
Callable
先获取执行的方法信息,再判断执行的异步线程池,再讲任务提交给线程池。
之前初始化的时候,传入的线程池为null,则:
public AsyncExecutionAspectSupport(@Nullable Executor defaultExecutor) {
this.defaultExecutor = new SingletonSupplier<>(defaultExecutor, () -> getDefaultExecutor(this.beanFactory));
this.exceptionHandler = SingletonSupplier.of(SimpleAsyncUncaughtExceptionHandler::new);
}
protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) {
if (beanFactory != null) {
try {
// Search for TaskExecutor bean... not plain Executor since that would
// match with ScheduledExecutorService as well, which is unusable for
// our purposes here. TaskExecutor is more clearly designed for it.
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) {
if (logger.isInfoEnabled()) {
logger.info("More than one TaskExecutor bean found within the context, and none is named " +
"'taskExecutor'. Mark one of them as primary or name it 'taskExecutor' (possibly " +
"as an alias) in order to use it for async processing: " + ex.getBeanNamesFound());
}
}
}
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) {
logger.info("No task executor bean found for async processing: " +
"no bean of type TaskExecutor and no bean named 'taskExecutor' either");
}
// Giving up -> either using local default executor or none at all...
}
}
return null;
}
beanFactory.getBean(TaskExecutor.class)
最后是获取了BeanFactory中的TaskExecutor的子类的bean(可能不存在)。
protected AsyncTaskExecutor determineAsyncExecutor(Method method) {
AsyncTaskExecutor executor = this.executors.get(method);
if (executor == null) {
Executor targetExecutor;
String qualifier = getExecutorQualifier(method);
if (StringUtils.hasLength(qualifier)) {
targetExecutor = findQualifiedExecutor(this.beanFactory, qualifier);
} else {
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;
}
使用本地缓存ConcurrentHashMap, key为Methed, value为线程池。
1)、先获取执行的方法的@Async的value值
protected String getExecutorQualifier(Method method) {
// Maintainer's note: changes made here should also be made in
// AnnotationAsyncExecutionAspect#getExecutorQualifier
Async async = AnnotatedElementUtils.findMergedAnnotation(method, Async.class);
if (async == null) {
async = AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(), Async.class);
}
return (async != null ? async.value() : null);
}
如果获取到配置的值(如定义方法时为:@Async("order") ),则获取正在的线程池
protected Executor findQualifiedExecutor(@Nullable BeanFactory beanFactory, String qualifier) {
if (beanFactory == null) {
throw new IllegalStateException("BeanFactory must be set on " + getClass().getSimpleName() +
" to access qualified executor '" + qualifier + "'");
}
return BeanFactoryAnnotationUtils.qualifiedBeanOfType(beanFactory, Executor.class, qualifier);
}
2)、如果@Async上没有配置,则获取默认值
targetExecutor = this.defaultExecutor.get();
就是之前从BeanFactory中获取TaskExecutor.class类型的实现,当前版本为spring5,,获取到的类型为SimpleAsyncTaskExecutor
protected Object doSubmit(Callable
根据我们定义的方法的返回值进行处理,返回值可以是 null、Future、Spring的AsyncResult是ListenableFuture的子类。
如果使用@Async没有配置线程池,并且没有给AnnotationAsyncExecutionInterceptor设置线程池,则调用时就是一个坑,每次创建一个线程。
submit()方法:
@Override
public Future submit(Callable task) {
FutureTask future = new FutureTask<>(task);
execute(future, TIMEOUT_INDEFINITE);
return future;
}
execute()执行方法:
@Override
public void execute(Runnable task, long startTimeout) {
Assert.notNull(task, "Runnable must not be null");
Runnable taskToUse = (this.taskDecorator != null ? this.taskDecorator.decorate(task) : task);
if (isThrottleActive() && startTimeout > TIMEOUT_IMMEDIATE) {
this.concurrencyThrottle.beforeAccess();
doExecute(new ConcurrencyThrottlingRunnable(taskToUse));
} else {
doExecute(taskToUse);
}
}
doExecute()方法:
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;
}
是否初始化了线程工厂,有则用工厂进行new,否则还是new。也就是说只要使用默认SimpleAsyncTaskExecutor线程池,每次执行任务就new一个新的线程。