Spring refresh函数(2)——Spring Boot invokeBeanFactoryPostProcessors

目前Spring Boot已经逐渐取代原来基于xml配置的Spring,渐渐成为各大互联网或软件公司的主力框架。为了贴合实际应用,接下来主要以Spring Boot(本文使用1.5.7.RELEASE版本)为基础进行介绍。

invokeBeanFactoryPostProcessors()函数是在BeanFactory创建之后,Bean创建之前执行,作用是对已经创建的BeanFactory进行后续的操作。其中将Spring Boot中注解的Bean转换为BeanDefinition结构就在这里完成,BeanDefinition结构为之后创建Bean做准备。本文的主题便是探究Spring Boot如何注册BeanDefinition结构。

从类AbstractApplicationContext的refresh()函数中的invokeBeanFactoryPostProcessors()函数开始我们的主题。

invokeBeanFactoryPostProcessors(beanFactory);

进入到类PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors()函数。

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()函数首先会“Invoke BeanDefinitionRegistryPostProcessors first, if any.”,接口BeanDefinitionRegistryPostProcessor的实现类用于注册BeanDefinition,这里传入的是ConfigurationClassPostProcessor对象处理被@Configuration注解的类。

public static void invokeBeanFactoryPostProcessors(
      ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    //...略去部分代码...
    // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
    List priorityOrderedPostProcessors = new ArrayList();
      for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
          priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
          processedBeans.add(ppName);
        }
    }
    sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
    registryPostProcessors.addAll(priorityOrderedPostProcessors);
    invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
    //...略去部分代码...
}
图片选自我的公众号

invokeBeanDefinitionRegistryPostProcessors()函数。

invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);

invokeBeanDefinitionRegistryPostProcessors()函数中的参数ConfigurationClassPostProcessor对象用于注册BeanDefinition。

private static void invokeBeanDefinitionRegistryPostProcessors(
      Collection postProcessors, BeanDefinitionRegistry registry) {

    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
      postProcessor.postProcessBeanDefinitionRegistry(registry);
    }
}
图片选自我的公众号

执行类ConfigurationClassPostProcessor对象的postProcessBeanDefinitionRegistry()方法。

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    int registryId = System.identityHashCode(registry);
    if (this.registriesPostProcessed.contains(registryId)) {
      throw new IllegalStateException(
          "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
    }
    if (this.factoriesPostProcessed.contains(registryId)) {
      throw new IllegalStateException(
          "postProcessBeanFactory already called on this post-processor against " + registry);
    }
    this.registriesPostProcessed.add(registryId);

    processConfigBeanDefinitions(registry);
}

进入processConfigBeanDefinitions()函数。从函数名就可以看出这个函数是用于操作被@configuration注解的类。

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    //...略去部分代码...
    // Parse each @Configuration class
    ConfigurationClassParser parser = new ConfigurationClassParser(
        this.metadataReaderFactory, this.problemReporter, this.environment,
        this.resourceLoader, this.componentScanBeanNameGenerator, registry);

    Set candidates = new LinkedHashSet(configCandidates);
    Set alreadyParsed = new HashSet(configCandidates.size());
    do {
      parser.parse(candidates);
      parser.validate();
      //...略去部分代码...
}

首先创建了ConfigurationClassParser对象将被用于对被@configuration注解的类进行解析使用。

// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
        this.metadataReaderFactory, this.problemReporter, this.environment,
        this.resourceLoader, this.componentScanBeanNameGenerator, registry);

具体解析过程在函数parse()中。

parser.parse(candidates);

进入类ConfigurationClassParser的parse()函数,会看到依据被@configuration注解的类的BeanDefinition的类型选择不同的parse()函数。而if-else逻辑中的parse()函数都会执行processConfigurationClass()函数。

public void parse(Set configCandidates) {
    this.deferredImportSelectors = new LinkedList();

    for (BeanDefinitionHolder holder : configCandidates) {
      BeanDefinition bd = holder.getBeanDefinition();
      try {
        if (bd instanceof AnnotatedBeanDefinition) {
          parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
        }
        else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
          parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
        }
        else {
          parse(bd.getBeanClassName(), holder.getBeanName());
        }
      }
      catch (BeanDefinitionStoreException ex) {
        throw ex;
      }
      catch (Throwable ex) {
        throw new BeanDefinitionStoreException(
            "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
      }
    }

    processDeferredImportSelectors();
}

protected final void parse(String className, String beanName) throws IOException {
    MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
    processConfigurationClass(new ConfigurationClass(reader, beanName));
}

protected final void parse(Class clazz, String beanName) throws IOException {
    processConfigurationClass(new ConfigurationClass(clazz, beanName));
}

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

processConfigurationClass()函数中继续调用doProcessConfigurationClass()函数。

如果变量sourceClass表示的类存在父类,doProcessConfigurationClass()函数会返回其父类,do-while循环执行。

我们程序中只有main()方法所在的类是@configuration注解的,而且无父类,当首次进入到processConfigurationClass()方法中,变量sourceClass就是我们自定义的有main()方法的入口类,do-while循环只执行一次。

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
    //...略去部分代码...
    // Recursively process the configuration class and its superclass hierarchy.
    SourceClass sourceClass = asSourceClass(configClass);
    do {
      sourceClass = doProcessConfigurationClass(configClass, sourceClass);
    }
    while (sourceClass != null);

    this.configurationClasses.put(configClass, configClass);
}

doProcessConfigurationClass()函数根据变量sourceClass表示的类,解析操作注解它的@ComponentScan注解、@Import注解和@ImportResource注解等。

这里看@ComponentScan注解的处理逻辑。此处存在着递归调用,递归以变量sourceClass为基础,如果扫描@ComponentScan注解描述的路径下其他类仍旧是被@configuration注解的,继续更深的扫描。doProcessConfigurationClass()->parse()->processConfigurationClass()>doProcessConfigurationClass()方法递归调用。

this.componentScanParser.parse()进行进一步处理。

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
      throws IOException {
    //...略去部分代码...
    // Process any @ComponentScan annotations
    Set componentScans = AnnotationConfigUtils.attributesForRepeatable(
        sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    if (!componentScans.isEmpty() &&
        !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
      for (AnnotationAttributes componentScan : componentScans) {
        // The config class is annotated with @ComponentScan -> perform the scan immediately
        //处理@ComponentScan注解
        Set scannedBeanDefinitions =
            this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
        // Check the set of scanned definitions for any further config classes and parse recursively if needed
        for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
          if (ConfigurationClassUtils.checkConfigurationClassCandidate(
              holder.getBeanDefinition(), this.metadataReaderFactory)) {
            //这里可能出现递归
            parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
          }
        }
        //...略去部分代码...
}

进入类ComponentScanAnnotationParser中的parse()函数解析@ComponentScan注解相关的参数,例如excludeFilters,basePackages参数等。创建ClassPathBeanDefinitionScanner对象用于扫描@ComponentScan注解指定的包。

直接跳到函数最后一行scanner.doScan()。

public Set parse(AnnotationAttributes componentScan, final String declaringClass) {
    //...略去部分代码...
    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
        componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
    //...略去部分代码...
    return scanner.doScan(StringUtils.toStringArray(basePackages));
}

进入类ClassPathBeanDefinitionScanner中的方法doScan()。

类ClassPathBeanDefinitionScanner扫描参数basePackages指定包下所有定义的Bean,转换为BeanDefinition后进行注册。参数basePackages是根据@ComponentScan注解的参数进行解析获得的,如果没有在注解中设置,默认就是被@ComponentScan注解的类所在的包。所以我们要把有main()方法的入口类放在最外层的包中,这样就会扫描到我们定义的所有包下的Bean。

protected Set doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set beanDefinitions = new LinkedHashSet();
    for (String basePackage : basePackages) {
      //找到包路径下用户定义的Bean
      Set candidates = findCandidateComponents(basePackage);
      //循环依次注册BeanDefinition
      for (BeanDefinition candidate : candidates) {
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
        candidate.setScope(scopeMetadata.getScopeName());
        String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
        if (candidate instanceof AbstractBeanDefinition) {
          postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
        }
        if (candidate instanceof AnnotatedBeanDefinition) {
          AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
        }
        if (checkCandidate(beanName, candidate)) {
          BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
          definitionHolder =
              AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
          beanDefinitions.add(definitionHolder);
          //注册BeanDefinition
          registerBeanDefinition(definitionHolder, this.registry);
        }
      }
    }
    return beanDefinitions;
}

doScan()方法中的findCandidateComponents()方法先找到参数basePackages路径下用户自定义的Bean,然后定义它们的BeanDefinition结构返回。

Set candidates = findCandidateComponents(basePackage);

doScan()方法中之后的for循环依次遍历Set BeanDefinition集合结构,方法registerBeanDefinition()对BeanDefinition进行注册。注册过程,如果是新的BeanDefinition就会直接放入到BeanFactory中的一个map结构beanDefinitionMap变量中存储,如果存在旧的BeanDefinition会进行替换。

registerBeanDefinition(definitionHolder, this.registry);

自此Spring Boot完成了用户自定义Bean的BeanDefinition结构的注册。以后将使用BeanDefinition结构对Bean进行创建。

你可能感兴趣的:(Spring refresh函数(2)——Spring Boot invokeBeanFactoryPostProcessors)