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