《底层到底做了什么》--- 从spring 的 EnableAsync 看指定bean的装配过程

在spring 框架中开启某项功能,常常会在Application类中使用@EnableXXX注解。比如使用@EnableAsync,开启支持Async。“开启”其实就是把相关的bean注入spring容器中。

以@EnableAsync为例,就是在@EnableAsync中使用@import把相关的bean注入容器中,这个bean一般是ProxyAsyncConfiguration。ProxyAsyncConfiguration是个@Configuration,继续递归的导入AsyncAnnotationBeanPostProcessor,这是实际Async功能使用的bean。

另外,在spring中起到自动化配置的@EnableConfigurationProperties,也是通过@import注入 EnableConfigurationPropertiesRegistrar。

下面将说明@EnableAsync在spring底层的执行流程。通过这个例子,也能看到spring中最基础的功能 IOC和AOP 的底层执行过程。

先上一个常规的demo

@SpringBootApplication
@EnableConfigurationProperties
@EnableAsync  //1
public class ApiApplication {
  public static void main(String[] args) { 
    SpringApplication.run(ApiApplication.class, args);
  }
}

1、 在ApiApplication上声明 @EnableAsync


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

2、在@EnableAsync里,声明通过AsyncConfigurationSelector导入


public class AsyncConfigurationSelector extends AdviceModeImportSelector { 
//省略

    @Nullable
    public String[] selectImports(AdviceMode adviceMode) {
        switch(adviceMode) {
        case PROXY:
            return new String[]{ProxyAsyncConfiguration.class.getName()};//3
        case ASPECTJ:
            return new String[]{"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration"};
         //省略
        }
    }

3、spring会根据返回值selectImports的返回值里实际去构造bean。 selector的意义就在于根据参数选择要装配的bean。

以上业务层看到的,但是看不到@EnableAsync什么时候被被解析,selectImports什么时候被调用,bean怎么被构造和装配。下面深入底层看执行流程。


public class ApiApplication {
  public static void main(String[] args) { 
    SpringApplication.run(ApiApplication.class, args);//1
  }
} 

1、还是相同的入口,args是启动时配置-D的参数。


public class SpringApplication {
    public ConfigurableApplicationContext run(String... args) {
    //省略
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            this.refreshContext(context);//2
            this.afterRefresh(context, applicationArguments);
    //省略 
  }

    protected void refresh(ConfigurableApplicationContext applicationContext) {
        applicationContext.refresh();//3
    }
} 

2、3 依次调用SpringApplication的run和refresh方法。


public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
   
    public void refresh() throws BeansException, IllegalStateException {

    //省略
    this.prepareRefresh();
    this.postProcessBeanFactory(beanFactory);
    this.invokeBeanFactoryPostProcessors(beanFactory);//4
    this.registerBeanPostProcessors(beanFactory);
    //省略
   }
}

final class PostProcessorRegistrationDelegate {
private static void invokeBeanDefinitionRegistryPostProcessors(Collection postProcessors, BeanDefinitionRegistry registry) {
        Iterator var2 = postProcessors.iterator();

        while(var2.hasNext()) {
            BeanDefinitionRegistryPostProcessor postProcessor = (BeanDefinitionRegistryPostProcessor)var2.next();
            postProcessor.postProcessBeanDefinitionRegistry(registry);//5
        }

    }
 }

4、调用AbstractApplicationContext的refresh。
5、PostProcessorRegistrationDelegate 的invokeBeanDefinitionRegistryPostProcessors方法。

后续代码不一一粘贴。
6、调用ConfigurationClassPostProcessor的processConfigBeanDefinitions(BeanDefinitionRegistry registry) 方法,
这里registry是DefaultListableBeanFactory。

    protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
        this.processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
    }

7、调用ConfigurationClassParser类parse(AnnotationMetadata metadata, String beanName)方法。这里beanName代表ApiApplication,metadata代表ApiApplication上所有的注解,包括@EnableAsync。

    protected final ConfigurationClassParser.SourceClass doProcessConfigurationClass(ConfigurationClass configClass, ConfigurationClassParser.SourceClass sourceClass, Predicate filter) throws IOException {
         this.processImports(configClass, sourceClass, this.getImports(sourceClass), filter, true);//8
     }

8、调用ConfigurationClassParser的getImports(sourceClass),sourceClass是ApiApplication.class,这个方法获得ApiApplication上所有的annotation,返回@import声明的bean名称列表。具体实现是以ApiApplication为root,递归的扫描过程所有的@注解。


    private void processImports(ConfigurationClass configClass, ConfigurationClassParser.SourceClass currentSourceClass, Collection importCandidates, Predicate exclusionFilter, boolean checkForCircularImports) { 
//省略
 Iterator var6 = importCandidates.iterator();

 while(var6.hasNext()) {
//省略
         String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());//9

         Collection importSourceClasses = this.asSourceClasses(importClassNames, exclusionFilter);
         this.processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);//10
}
//省略

9、调用ConfigurationClassParser的processImports方法,用来处理@import声明的bean。输入参数importCandidates是ApiApplication上@import声明的bean名称列表,包括AsyncConfigurationSelector。这个方法,逐个处理@import声明的bean,当处理到AsyncConfigurationSelector时,先通过构造器生成AsyncConfigurationSelector对象,然后调用Selector的selectImports方法,返回ProxyAsyncConfiguration类名。
10、此时importSourceClasses为ProxyAsyncConfiguration类名。继续递归processImports。

 if (candidate.isAssignable(ImportSelector.class)) {
//省略
 } else {
    this.importStack.registerImport(currentSourceClass.getMetadata(),     candidate.getMetadata().getClassName());//11
    this.processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);//12

}
//省略

11、如果importSourceClasses是Selector,将递归的获得@import的bean。这里ProxyAsyncConfiguration是个普通的bean,所以直接构造bean。
12、与第8步相同,继续递归的检查ProxyAsyncConfiguration上的@import声明。

到此,ProxyAsyncConfiguration解析完成。下面创建ProxyAsyncConfiguration bean并初始化


public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
   
    public void refresh() throws BeansException, IllegalStateException {

    //省略
    this.prepareRefresh();
    this.postProcessBeanFactory(beanFactory);
    this.invokeBeanFactoryPostProcessors(beanFactory);//1
    this.registerBeanPostProcessors(beanFactory);//2
    //省略
   }
}

前面的解析过程都是在1中执行,实际创建bean在2中。


public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
            beanInstance = this.getInstantiationStrategy().instantiate(mbd, beanName, this);
            }//3

            BeanWrapper bw = new BeanWrapperImpl(beanInstance); 
            this.initBeanWrapper(bw);
            return bw;
   }
}
class DelegatingConstructorAccessorImpl extends ConstructorAccessorImpl {
    private ConstructorAccessorImpl delegate;

    public Object newInstance(Object[] var1) throws InstantiationException, IllegalArgumentException, InvocationTargetException {
        return this.delegate.newInstance(var1);//4 
    }
 
}

3、创建ProxyAsyncConfiguration对象。
4、这里delegate封装了CGLIB的构造器,生成roxyAsyncConfiguration对象。


public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);//5

            this.populateBean(beanName, mbd, instanceWrapper);//6
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);//7

 protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {

            this.autowireByName(beanName, mbd, bw, newPvs); //8

            pvsToUse = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);//8

5、第3和4在这个方法里执行
6和8、将生成的bean放入容器,也就是IOC的核心步骤(?)
7、初始化bean,包括触发bean生成后的回调方法。ProxyAsyncConfiguration实现了ImportAware接口,这里触发setImportMetadata方法。

到此ProxyAsyncConfiguration bean的构造及初始化。

后续:@Async 执行过程

你可能感兴趣的:(《底层到底做了什么》--- 从spring 的 EnableAsync 看指定bean的装配过程)