聊一聊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 执行异步逻辑。

相关推荐
柔弱女子爱java7 分钟前
XML文件(超详细):XML文件概念、作用、写法、如何用程序解析XML、写入XML、dom4j框架、DTD文档、schema文档
xml·java·开发语言·后端
wsd_ontheroad9 分钟前
HTML 转 PDF
java·pdf·html
sxy1993sxy201820 分钟前
多线程下使用数据库 - 20241124
数据库
律队i26 分钟前
【数据库原理】创建数据库,SQL语句
数据库·sql
xmh-sxh-131426 分钟前
redis使用介绍
java
halfbloodghost27 分钟前
【数据库】SQL语句简单运用
数据库·sql·oracle
是老余27 分钟前
【数据库入门】关系型数据库入门及SQL语句的编写
数据库·sql
ejinxian27 分钟前
SQLite 管理工具 SQLiteStudio 3.4.5 发布
数据库·oracle·sqlite
锐策28 分钟前
〔 MySQL 〕中三种重要的日志类型
数据库·mysql
暴力的bug制造机28 分钟前
【MySQL】库的操作(增删查改 | 备份 | 恢复)
linux·数据库·mysql·oracle