学一学Spring中的@Async注解

320 阅读6分钟

一、 样例

1.1 demo代码

 package com.lazy.snail;
 ​
 import org.springframework.context.annotation.*;
 import org.springframework.core.task.SimpleAsyncTaskExecutor;
 import org.springframework.scheduling.annotation.EnableAsync;
 ​
 @Configuration
 @EnableAsync
 @ComponentScan(basePackages = "com.lazy.snail")
 public class AppConfig {
     @Bean(name = "taskExecutor")
     public SimpleAsyncTaskExecutor taskExecutor() {
         return new SimpleAsyncTaskExecutor();
     }
 }
 package com.lazy.snail;
 ​
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 ​
 /**
  * @ClassName MyService
  * @Description TODO
  * @Author lazysnail
  * @Date 2024/10/28 16:20
  * @Version 1.0
  */
 @Service
 public class MyService {
     @Async
     public void asynMethod() {
         System.out.println("Start Async Method: " + Thread.currentThread().getName());
         try {
             // 模拟耗时操作
             Thread.sleep(3000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         System.out.println("End Async Method: " + Thread.currentThread().getName());
     }
 ​
 }
 package com.lazy.snail;
 ​
 import lombok.extern.slf4j.Slf4j;
 import org.junit.jupiter.api.Test;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 ​
 @Slf4j
 public class SpringTest {
 ​
     @Test
     void test() {
         ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
         MyService myService = context.getBean(MyService.class);
         myService.asynMethod();
 ​
         // 等待一段时间,确保异步任务执行
         try {
             Thread.sleep(5000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
 ​
     }
 }

1.2 demo概述

AppConfig中注解:

  • @Configuration 声明配置类
  • @EnableAsync 开启异步方法执行功能
  • @ComponentScan 组件扫描
  • @Bean 声明一个简单的异步任务执行器

MyService中注解:

  • @Service 声明该类是组件
  • @Bean 声明该方法是异步方法

1.3 样例效果

MyService会被代理,执行asynMethod时,会新开一个线程单独运行。

代理:

image-20241029105034521

运行结果:

image-20241029105241937

二、源码流程

只列出本案例相关关键类

2.1 容器初始化阶段

2.1.1 内部bean定义信息注册

 // AnnotationConfigUtils
 public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
         BeanDefinitionRegistry registry, @Nullable Object source) {
     // 省略部分代码...
     if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
         // ConfigurationClassPostProcessor在后续配置类的处理起关键作用
         RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
         def.setSource(source);
         beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
     }
     // 省略部分代码...
 }

2.1.2 主配置类注册

 // AnnotationConfigApplicationContext
 public void register(Class<?>... componentClasses) {
     Assert.notEmpty(componentClasses, "At least one component class must be specified");
     StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register")
             .tag("classes", () -> Arrays.toString(componentClasses));
     this.reader.register(componentClasses);
     registerComponentClass.end();
 }

2.1.3 注册结果

image-20241029110559287

2.2 容器刷新阶段

2.2.1 bean工厂后置处理器处理

 // AbstractApplicationContext
 public void refresh() throws BeansException, IllegalStateException {
     invokeBeanFactoryPostProcessors(beanFactory);
 }
 // PostProcessorRegistrationDelegate
 public static void invokeBeanFactoryPostProcessors(
             ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
     // [org.springframework.context.annotation.internalConfigurationAnnotationProcessor]
     String[] postProcessorNames =
                     beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
     for (String ppName : postProcessorNames) {
         if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
             // 实例化internalConfigurationAnnotationProcessor
             currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
             processedBeans.add(ppName);
         }
     }
     sortPostProcessors(currentRegistryProcessors, beanFactory);
     registryProcessors.addAll(currentRegistryProcessors);
     // 调用ConfigurarionClassPostProcessor的postProcessBeanDefinitionRegistry方法
     // 解析配置类,注册解析出来的bean定义信息到容器中
     invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
     currentRegistryProcessors.clear();
 }

2.2.2 主配置类解析

主要关注AppConfig类上@EnableAsync和方法上@Bean注解。

 // ConfigurationClassParser
 protected final SourceClass doProcessConfigurationClass(
             ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
             throws IOException {
 ​
     // 处理@Import注解
     processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
 ​
     // 处理@Bean方法
     Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
     for (MethodMetadata methodMetadata : beanMethods) {
         configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
     }
 }
2.2.2.1@EnableAsync
2.2.2.1.1 @Import处理

@EnableAsync中有@Import注解,所以在解析过程中会处理@Import注解。

 @Target(ElementType.TYPE)
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 @Import(AsyncConfigurationSelector.class)
 public @interface EnableAsync {
     // 省略部分代码...
 }

AsyncConfigurationSelector类图:

image-20241029112512592

AsyncConfigurationSelector源码:

 // AsyncConfigurationSelector
 public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
 ​
     private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
             "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
 ​
     @Override
     @Nullable
     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;
         }
     }
 ​
 }

处理过程:

 // ConfigurationClassParser
 private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
             Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
             boolean checkForCircularImports) {
     // 省略部分代码...
     String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
     Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
     processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
     // 省略部分代码...
 }
 public final String[] selectImports(AnnotationMetadata importingClassMetadata) {
     // 省略部分代码...
     
     // adviceMode在@EnableAsync中默认值是PROXY
     AdviceMode adviceMode = attributes.getEnum(getAdviceModeAttributeName());
     String[] imports = selectImports(adviceMode);
     if (imports == null) {
         throw new IllegalArgumentException("Unknown AdviceMode: " + adviceMode);
     }
     return imports;
 }
 // AsyncConfigurationSelector
 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;
     }
 }
2.2.2.1.2 ProxyAsyncConfiguration配置类处理
 // ProxyAsyncConfiguration
 @Configuration(proxyBeanMethods = false)
 @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();
         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;
     }
 ​
 }

ProxyAsyncConfiguration中有一个@Bean注解的方法,后续肯定会将对应的AsyncAnnotationBeanPostProcessor注册到容器中。

2.2.2.1.3 @EnableAsync小结

@EnableAsync包含了一个选择器,选择器根据AdviceMode选择了一个配置类ProxyAsyncConfiguration,配置类中有一个@Bean注解的方法。

@EnableAsync --> AsyncAnnotationBeanPostProcessor

2.2.2.2 AppConfig中的@Bean

在AppConfig中新增了一个beanMethod

2.2.3 配置类bean定义信息加载

 // ConfigurationClassPostProcessor
 public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
     this.reader.loadBeanDefinitions(configClasses);
 }

image-20241029115803423

加载结果:

image-20241029115939748

2.2.2 注册bean后置处理器

2.2.2.1 查找bean后置处理器
 // PostProcessorRegistrationDelegate
 public static void registerBeanPostProcessors(
             ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
     for (String ppName : postProcessorNames) {
         if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
             BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
             priorityOrderedPostProcessors.add(pp);
             if (pp instanceof MergedBeanDefinitionPostProcessor) {
                 internalPostProcessors.add(pp);
             }
         }
         else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
             orderedPostProcessorNames.add(ppName);
         }
         else {
             nonOrderedPostProcessorNames.add(ppName);
         }
     }
 }

image-20241029134248373

2.2.2.2 实例化AsyncAnnotationBeanPostProcessor
 // PostProcessorRegistrationDelegate
 public static void registerBeanPostProcessors(
             ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
     List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
     for (String ppName : orderedPostProcessorNames) {
         // AsyncAnnotationBeanPostProcessor
         BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
         orderedPostProcessors.add(pp);
         if (pp instanceof MergedBeanDefinitionPostProcessor) {
             internalPostProcessors.add(pp);
         }
     }
     sortPostProcessors(orderedPostProcessors, beanFactory);
     registerBeanPostProcessors(beanFactory, orderedPostProcessors);
 }

image-20241029134529026

 // AbstractAutowiredCapableBeanFactory
 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
     // 通过工厂方法实例化
     return instantiateUsingFactoryMethod(beanName, mbd, args);
 }
 // ConstructorResolver
 public BeanWrapper instantiateUsingFactoryMethod(
             String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
 ​
     BeanWrapperImpl bw = new BeanWrapperImpl();
     this.beanFactory.initBeanWrapper(bw);
 ​
     Object factoryBean;
     Class<?> factoryClass;
     boolean isStatic;
     
     // 工厂bean名称:org.springframework.scheduling.annotation.ProxyAsyncConfiguration
     String factoryBeanName = mbd.getFactoryBeanName();
     if (factoryBeanName != null) {
         // 省略部分代码...
         
         // 找容器要工厂bean实例
         // 这时候容器中还没有ProxyAsyncConfiguration实例,需要进行实例化
         factoryBean = this.beanFactory.getBean(factoryBeanName);
         
         // 省略部分代码...
     } else {
         // 省略部分代码...
     }
 ​
     Method factoryMethodToUse = null;
     ArgumentsHolder argsHolderToUse = null;
     Object[] argsToUse = null;
 ​
     // 省略部分代码...
 ​
     if (factoryMethodToUse == null || argsToUse == null) {
         factoryClass = ClassUtils.getUserClass(factoryClass);
 ​
         List<Method> candidates = null;
         if (mbd.isFactoryMethodUnique) {
             if (factoryMethodToUse == null) {
                 // ProxyAsyncConfiguration中的asyncAdvisor方法
                 factoryMethodToUse = mbd.getResolvedFactoryMethod();
             }
             if (factoryMethodToUse != null) {
                 candidates = Collections.singletonList(factoryMethodToUse);
             }
         }
         // 省略部分代码...
        
         // 通过工厂bean的工厂方法实例化
         bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
         return bw;
 ​
         // 省略部分代码...
 }
     
 private Object instantiate(String beanName, RootBeanDefinition mbd,
         @Nullable Object factoryBean, Method factoryMethod, Object[] args) {
     // 省略部分代码...
     
     return this.beanFactory.getInstantiationStrategy().instantiate(
                     mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
     // 省略部分代码...
 }
 public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
             @Nullable Object factoryBean, final Method factoryMethod, Object... args) {
 ​
     // 省略部分代码...
     
     ReflectionUtils.makeAccessible(factoryMethod);
     Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
     currentlyInvokedFactoryMethod.set(factoryMethod);
     // 反射调用ProxyAsyncConfiguration的asyncAdvisor方法
     // 返回值是一个AsyncAnnotationBeanPostProcessor对象
     Object result = factoryMethod.invoke(factoryBean, args);
     if (result == null) {
         result = new NullBean();
     }
     return result;
     
     // 省略部分代码...
 }
2.2.2.3 初始化AsyncAnnotationBeanPostProcessor
 // AbstractAutowireCapableBeanFactory
 protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
     // 省略部分代码...
     
     invokeAwareMethods(beanName, bean);
 ​
     Object wrappedBean = bean;
     if (mbd == null || !mbd.isSynthetic()) {
         wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
     }
 ​
     try {
         invokeInitMethods(beanName, wrappedBean, mbd);
     }
     catch (Throwable ex) {
         throw new BeanCreationException(
                 (mbd != null ? mbd.getResourceDescription() : null),
                 beanName, "Invocation of init method failed", ex);
     }
     if (mbd == null || !mbd.isSynthetic()) {
         wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
     }
 ​
     return wrappedBean;
 }
 ​
 private void invokeAwareMethods(String beanName, Object bean) {
     if (bean instanceof Aware) {
         // 省略部分代码...
         if (bean instanceof BeanFactoryAware) {
             ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
         }
     }
 }
 // AsyncAnnotationBeanPostProcessor
 public void setBeanFactory(BeanFactory beanFactory) {
     super.setBeanFactory(beanFactory);
     // 创建了一个advisor
     AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);
     if (this.asyncAnnotationType != null) {
         advisor.setAsyncAnnotationType(this.asyncAnnotationType);
     }
     advisor.setBeanFactory(beanFactory);
     this.advisor = advisor;
 }

AsyncAnnotationAdvisor类结构图:

image-20241029142039490

2.2.2.4 小结

注册bean后置处理的过程中:

通过工厂bean(ProxyAsyncConfiguration)的工厂方法(asyncAdvisor)实例化了AsyncAnnotationBeanPostProcessor,注册到容器中;

创建了AsyncAnnotationAdvisor,赋值给AsyncAnnotationBeanPostProcessor的advice;

AsyncAnnotationBeanPostProcessor添加到了容器中bean后置处理器集合中;

2.2.4 单例实例化

主要看带有@Async注解方法的MyService类的实例化过程。

createBeanInstance(构造)和populateBean(属性赋值)跟普通的bean一样。

重点在于initializeBean方法中,bean后置处理器在bean初始化后的应用。

核心是AsyncAnnotationBeanPostProcessor的postProcessAfterInitialization方法。(注意继承关系,AbstractAdvisingBeanPostProcessor)

 protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
     // 省略部分代码...
     
     if (mbd == null || !mbd.isSynthetic()) {
         wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
     }
 ​
     return wrappedBean;
 }
 // AbstractAdvisingBeanPostProcessor
 public Object postProcessAfterInitialization(Object bean, String beanName) {
     // 省略部分代码...
 ​
     if (isEligible(bean, beanName)) {
         // 准备代理工厂
         ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
         if (!proxyFactory.isProxyTargetClass()) {
             evaluateProxyInterfaces(bean.getClass(), proxyFactory);
         }
         // 这里的advisor就是2.2.2.3中创建的AsyncAnnotationAdvisor
         proxyFactory.addAdvisor(this.advisor);
         customizeProxyFactory(proxyFactory);
 ​
         ClassLoader classLoader = getProxyClassLoader();
         if (classLoader instanceof SmartClassLoader && classLoader != bean.getClass().getClassLoader()) {
             classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
         }
         // 使用Cglib创建代理,具体过程不再跟,可以看Spring专栏中AOP相关文章
         return proxyFactory.getProxy(classLoader);
     }
 ​
     return bean;
 }

代理对象中的Callback:

image-20241029144804104

实例化结果:

image-20241029145020871

2.3 客户端调用阶段

方法拦截:

 // DynamicAdvisedInterceptor
 public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
     // 省略部分代码...
     
     // 拦截链中只有一个AnnotationAsyncExecutionInterceptor
     List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
     Object retVal;
     
     retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
         
 }
 // AsyncExecutionInterceptor
 public Object invoke(final MethodInvocation invocation) throws Throwable {
     Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
     // asynMethod方法
     Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
     // 
     final Method userDeclaredMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
     // 确定执行方法的具体执行器 -- SimpleAsyncTaskExecutor
     AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
     if (executor == null) {
         throw new IllegalStateException(
                 "No executor specified and no default executor set on AsyncExecutionInterceptor either");
     }
     
     // 创建任务
     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;
     };
     
     // 提交任务
     return doSubmit(task, executor, invocation.getMethod().getReturnType());
 }
 // AsyncExecutionAspectSupport
 protected Object doSubmit(Callable<Object> task, AsyncTaskExecutor executor, Class<?> returnType) {
     // 省略部分代码...
     executor.submit(task);
     return null;
 }
 // SimpleAsyncTaskExecutor
 protected void doExecute(Runnable task) {
     // 创建、启动线程
     Thread thread = (this.threadFactory != null ? this.threadFactory.newThread(task) : createThread(task));
     thread.start();
 }

三、 总结

启用异步支持:通过 @EnableAsync 注解引入异步配置。

配置处理AsyncConfigurationSelector 导入相关的配置类,设置 AsyncAnnotationBeanPostProcessor

方法扫描AsyncAnnotationBeanPostProcessor 识别带有 @Async 的方法,并为其创建代理。

代理生成:根据目标类的特性(接口或非接口)生成 JDK 动态代理或 CGLIB 代理。

客户端调用:通过代理调用标记为异步的方法,触发拦截器。

异步执行:使用配置的 TaskExecutor 执行异步逻辑。