spring小結(3)-@Configuration

之前介紹 ConfigurationClassPostProcessor時很關鍵的類,解析@Configuration的類

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
      PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {

 

...................................

其中:public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
   List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
   String[] candidateNames = registry.getBeanDefinitionNames();

   for (String beanName : candidateNames) {
      BeanDefinition beanDef = registry.getBeanDefinition(beanName);
      if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
            ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
         if (logger.isDebugEnabled()) {
            logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
         }
      }
      else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
         configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
      }
   }

其實對於Appconfig類,加不加@Configuration無所謂,後面有@ComponentScan,。。。同樣可以,加了便是FullConfigurationClass, 不加是isLiteConfigurationClass

ConfigurationClassPostProcessor會調用ConfigurationClassUtils來判斷

abstract class ConfigurationClassUtils {

   private static final String CONFIGURATION_CLASS_FULL = "full";  //全註解

   private static final String CONFIGURATION_CLASS_LITE = "lite";   //部分註解類,

........................................................

if (isFullConfigurationCandidate(metadata)) {
   beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
else if (isLiteConfigurationCandidate(metadata)) {
   beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
   return false;

@import引入類有三種形式,幫助把importClass註冊到beanfactory,以bd形式,這裏先說明實現ImportSelector的形式

@Configuration
@ComponentScan("com.lmq.BaseService")
//@Import(MyImportBeanDefinitionRegistrar.class)
@Import(MyImportSelector.class)
public class AppConfig {


}
import org.springframework.core.type.AnnotationMetadata;

public class MyImportSelector  implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{LmqService2.class.getName()};
    }
}

這裏在ConfigurationClassPostProcessor中,new  ConfigurationClassParser,

ConfigurationClassParser parser = new ConfigurationClassParser(
      this.metadataReaderFactory, this.problemReporter, this.environment,
      this.resourceLoader, this.componentScanBeanNameGenerator, registry);

調用

ConfigurationClassParser的方法:
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), true);
具體怎麼處理可查看源碼,判斷一組類是不是import(三種,比如這裏是MyImportSelector,便是)
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
      Collection<SourceClass> importCandidates, boolean checkForCircularImports) {

   if (importCandidates.isEmpty()) {
      return;
   }

   if (checkForCircularImports && isChainedImportOnStack(configClass)) {
      this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
   }
   else {
      this.importStack.push(configClass);
      try {
         for (SourceClass candidate : importCandidates) {
            if (candidate.isAssignable(ImportSelector.class)) {
               // Candidate class is an ImportSelector -> delegate to it to determine imports
               Class<?> candidateClass = candidate.loadClass();
               ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
               ParserStrategyUtils.invokeAwareMethods(
                     selector, this.environment, this.resourceLoader, this.registry);
               if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
                  this.deferredImportSelectors.add(
                        new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
               }
               else {
                  String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                  Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
                  processImports(configClass, currentSourceClass, importSourceClasses, false);//遞歸調用,因爲
//importclass可能也有@import註解
               }
            }
            else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) { //可能的
               // Candidate class is an ImportBeanDefinitionRegistrar ->
               // delegate to it to register additional bean definitions
               Class<?> candidateClass = candidate.loadClass();
               ImportBeanDefinitionRegistrar registrar =
                     BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
               ParserStrategyUtils.invokeAwareMethods(
                     registrar, this.environment, this.resourceLoader, this.registry);
               configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
            }
            else {
               // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
               // process it as an @Configuration class
               this.importStack.registerImport(
                     currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
               processConfigurationClass(candidate.asConfigClass(configClass));
            }

 

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
   if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
      return;
   }

   ConfigurationClass existingClass = this.configurationClasses.get(configClass);
   if (existingClass != null) {
      if (configClass.isImported()) {
         if (existingClass.isImported()) {
            existingClass.mergeImportedBy(configClass);
         }
         // Otherwise ignore new imported config class; existing non-imported class overrides it.
         return;
      }
      else {
         // Explicit bean definition found, probably replacing an import.
         // Let's remove the old one and go with the new one.
         this.configurationClasses.remove(configClass);
         this.knownSuperclasses.values().removeIf(configClass::equals);
      }
   }

   // 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);
}

String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());//反射invok額方法獲取要引入的類

最後吧import中的class(比如上面的LmqService2.class)放在this.configurationClasses.put(configClass, configClass);

然後再合併到beanFactory中的bd map,具體就是parser完,回到ConfigurationClassPostProcessor中

do {
   parser.parse(candidates);
   parser.validate();

   Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());//就是上面放置的包括處理@import得到的class,也包括@Config的類
   configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
   this.reader = new ConfigurationClassBeanDefinitionReader(
         registry, this.sourceExtractor, this.resourceLoader, this.environment,
         this.importBeanNameGenerator, parser.getImportRegistry());
}
this.reader.loadBeanDefinitions(configClasses);//把沒有加到bd map中的加入,比如包括myimportselecotr的lmqservice2

alreadyParsed.addAll(configClasses);

........................................

 

對於ImportBeanDefinitionRegistrar.class的·import類似,沒有遞歸

else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
   // Candidate class is an ImportBeanDefinitionRegistrar ->
   // delegate to it to register additional bean definitions
   Class<?> candidateClass = candidate.loadClass();
   ImportBeanDefinitionRegistrar registrar =
         BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
   ParserStrategyUtils.invokeAwareMethods(
         registrar, this.environment, this.resourceLoader, this.registry);
   configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}

不過提前放的map不一樣

public void addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar registrar, AnnotationMetadata importingClassMetadata) {
   this.importBeanDefinitionRegistrars.put(registrar, importingClassMetadata);
}

那麼什麼時候把這些importBeanDefinitionRegistrar.class impor的·類註冊到bd map中?

還是上面的loadBeanDefinitions,

this.reader.loadBeanDefinitions(configClasses);//

進入,如下,在裏面處理了,所以importBeanDefinitionRegistrar.class impor的·類註冊到bd map

loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());

其中的configClass.getImportBeanDefinitionRegistrars()就是上面的 this.importBeanDefinitionRegistrars.put(registrar, importingClassMetadata);然後循環註冊到this.registry(等同於beanfactory的applictionConetxt),如下

private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
   registrars.forEach((registrar, metadata) ->
         registrar.registerBeanDefinitions(metadata, this.registry));//
}

 

 

總結:bd註冊流程,1,解析config  2,掃描得到所有@component的普通類 3,處理Import,註冊imported 的bd

 

至此,所有

BeanDefinitionRegistryPostProcessor(BeanFactoryPostProcessor的子類接口

處理完後,回到最初的起點

往後面處理繼續處理回調invokeBeanFactoryPostProcessors,使用BeanFactoryPostProcessor處理,

    }
   sortPostProcessors(currentRegistryProcessors, beanFactory);
   registryProcessors.addAll(currentRegistryProcessors);
   invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
   currentRegistryProcessors.clear();
}

// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); //回調處理同時繼承BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor的,比如ConfigurarionClassPostProcessor
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);//回調BeanFactoryPostProcessor的

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章