聊一聊Spring中的@Async注解

一、 样例

1.1 demo代码

java 复制代码
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();
    }
}
java 复制代码
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());
    }

}
java 复制代码
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时,会新开一个线程单独运行。

代理:

运行结果:

二、源码流程

!NOTE

只列出本案例相关关键类

2.1 容器初始化阶段

2.1.1 内部bean定义信息注册

java 复制代码
// 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 主配置类注册

java 复制代码
// 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 注册结果

2.2 容器刷新阶段

2.2.1 bean工厂后置处理器处理

java 复制代码
// AbstractApplicationContext
public void refresh() throws BeansException, IllegalStateException {
    invokeBeanFactoryPostProcessors(beanFactory);
}
java 复制代码
// 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注解。

java 复制代码
// 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注解。

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

AsyncConfigurationSelector类图:

AsyncConfigurationSelector源码:

java 复制代码
// 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;
		}
	}

}

处理过程:

java 复制代码
// 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);
    // 省略部分代码...
}
java 复制代码
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;
}
java 复制代码
// 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配置类处理
java 复制代码
// 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定义信息加载

java 复制代码
// ConfigurationClassPostProcessor
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    this.reader.loadBeanDefinitions(configClasses);
}

加载结果:

2.2.4 注册bean后置处理器

2.2.4.1 查找bean后置处理器
java 复制代码
// 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);
        }
    }
}
2.2.4.2 实例化AsyncAnnotationBeanPostProcessor
java 复制代码
// 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);
}
java 复制代码
// AbstractAutowiredCapableBeanFactory
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // 通过工厂方法实例化
    return instantiateUsingFactoryMethod(beanName, mbd, args);
}
java 复制代码
// 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);
    // 省略部分代码...
}
java 复制代码
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.4.3 初始化AsyncAnnotationBeanPostProcessor
java 复制代码
// 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);
        }
    }
}
java 复制代码
// 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类结构图:

2.2.3.4 小结

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

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

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

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

2.2.5 单例实例化

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

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

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

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

java 复制代码
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    // 省略部分代码...
    
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}
java 复制代码
// 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:

实例化结果:

2.3 客户端调用阶段

方法拦截:

java 复制代码
// 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();
        
}
java 复制代码
// 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());
}
java 复制代码
// AsyncExecutionAspectSupport
protected Object doSubmit(Callable<Object> task, AsyncTaskExecutor executor, Class<?> returnType) {
    // 省略部分代码...
    executor.submit(task);
    return null;
}
java 复制代码
// 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 执行异步逻辑。

相关推荐
图像僧10 小时前
vs2019中的属性页使用说明
java·开发语言·jvm
武子康10 小时前
Java-03 深入浅出 MyBatis 增删改查与映射配置详解
java·后端
静心观复11 小时前
.puml文件是什么,怎么用
java
YOU OU11 小时前
SpringBoot 日志
java·开发语言
snowfoootball11 小时前
解决低版本navicat连接PostgreSQl的不兼容报错问题
数据库·postgresql
江南十四行11 小时前
并发编程(二)
java·开发语言
徐sir(徐慧阳)11 小时前
ORACLE RAC GI目录下crfclust.bdb文件过大问题处理
数据库·oracle
qingfeng1541511 小时前
企业微信 API 自动化开发指南:从消息回调到智能运营实战
java·开发语言·python·自动化·企业微信
琢磨先生David11 小时前
人大金仓(KingbaseES)数据库简介
数据库