Knowledge: spring spring BeanFactoryPostProcessor extension principle of the source code parsing and BeanDefinitionPostProcessor and ApplicationListener

How does Spring publish events? ApplicationListener

1. Write a NiuhApplicationListener implementation ApplicationListener and add the component to the container

@Configuration
@ComponentScan("com.niuh") public class MainConfig {} @component public class NiuhApplicationListener implements ApplicationListener { @override public void onApplicationEvent(ApplicationEvent ApplicationEvent) {system.out.println ("NiuhApplicationListener receives an event:"+ applicationEvent); } } public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class); // Manually publish an event context.publishevent (new ApplicationEvent("I manually posted an event.") {
        @Override
        public Object getSource() {
            returnsuper.getSource(); }}); Context.close (); }Copy the code

Test results:

NiuhApplicationListener receives an event: org. Springframework. Context. Event. ContextRefreshedEvent [source=org.springframework.context.annotation.AnnotationConfigApplicationContext@7bfcd12c: startup date [Fri Jul 05 12:58:12 CST 2019]; Root of Context Hierarchy] NiuhApplicationListener Receives an event: com.niuh.SpringTestThe $1[source= I manually released an event] NiuhApplicationListener receives an event: org. Springframework. Context. Event. ContextClosedEvent [source=org.springframework.context.annotation.AnnotationConfigApplicationContext@7bfcd12c: startup date [Fri Jul 05 12:58:12 CST 2019]; root of context hierarchy]
Copy the code

Source code analysis:

i1>org.springframework.context.support.AbstractApplicationContext#refresh
i2 >org.springframework.context.support.AbstractApplicationContext# initApplicationEventMulticaster (multicast) initialization events
i3  >org.springframework.context.support.AbstractApplicationContext# listeners register event listeners to multicast listeners
Copy the code
  • I2: Initialize event multicast source parsing
/**
 * Initialize the ApplicationEventMulticaster.
 * Uses SimpleApplicationEventMulticaster if none defined in the context.
 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
 */
protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); Judging the IOC container contains applicationEventMulticaster event / / multicast is the name of the Beanif(the beanFactory containsLocalBean (APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {/ / create a applicationEventMulticaster In the IOC container, The bean's name for applicationEventMulticaster enclosing applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);if (logger.isDebugEnabled()) {
         logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); }} / / container does not contain a beanName for applicationEventMulticaster multicast componentselse{/ / create a SimpleApplicationEventMulticaster multicast, enclosing applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); / / register into the container the beanFactory. RegisterSingleton (APPLICATION_EVENT_MULTICASTER_BEAN_NAME, enclosing applicationEventMulticaster);if (logger.isDebugEnabled()) {
         logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
               APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
               "': using default [" + this.applicationEventMulticaster + "]"); }}}Copy the code
  • I3: register the listeners in the container to the multicast source code parsing
/**
 * Add beans that implement ApplicationListener as listeners.
 * Doesn't affect other listeners, which can be added without being beans. */ protected void registerListeners() { // Register statically specified ApplicationListener
       listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let post-processors apply to them! / / we realized ApplicationListener component String [] listenerBeanNames = getBeanNamesForType (ApplicationListener. Class, true, false); for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } // Publish early application events now that we finally have a multicaster... // Prior to this, the event we wanted to publish earlier was not published due to the lack of multicast, so here we finally have our own multicast, Can release the early accumulation of events Set here < ApplicationEvent > earlyEventsToProcess = this. EarlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess ! = null) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); }}} -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- how to publish events -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the public void multicastEvent (final ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = (eventType ! = null ? eventType : resolveDefaultEventType(event)); For (final ApplicationListener
       Listeners: getApplicationListeners(event, type); thread listeners: getApplicationListeners(event, type) if (executor ! = null) { executor.execute(() -> invokeListener(listener, event)); } else {invokeListener(listener, event); } } } private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {try {/ / call for the listener onApplicationEvent event listener onApplicationEvent (event); } catch (ClassCastException ex) { String msg = ex.getMessage(); if (msg == null || matchesClassCastMessage(msg, event.getClass())) { // Possibly a lambda-defined listener which we could not resolve the generic event type for // -> let's suppress the exception and just log a debug message.
         Log logger = LogFactory.getLog(getClass());
         if (logger.isDebugEnabled()) {
            logger.debug("Non-matching event type for listener: "+ listener, ex); }}else{ throw ex; }}}Copy the code

Second, the BeanDefinitionRegistryPostProcessor processing source process

Execution time: All bean definition information will be loaded into the container, and the bean instance has not been initialized.

@Component
public class NiuhBeanDefinationRegisterPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        System.out.println("NiuhBeanDefinationRegisterPostProcessor postProcessBeanDefinitionRegistry method");
        System.out.println("Number of bean definitions:" + beanDefinitionRegistry.getBeanDefinitionCount());
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(NiuhLog.class);
        beanDefinitionRegistry.registerBeanDefinition("niuhLog",rootBeanDefinition);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("NiuhBeanDefinationRegisterPostProcessor postProcessBeanFactory method"); System.out.println(configurableListableBeanFactory.getBeanDefinitionCount()); }}Copy the code

BeanFactoryPostProcessor processing process

Execution time: All Bean definition information has been loaded into the container, but the Bean instance has not been initialized.

@Component
public class NiuhBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("The IOC container calls NiuhBeanFactoryPostProcessor postProcessBeanFactory method");
        for(String name:beanFactory.getBeanDefinitionNames()) {
            if("niuhLog".equals(name)) {
                BeanDefinition beanDefinition = beanFactory.getBeanDefinition(name);
                beanDefinition.setLazyInit(true); }}}}Copy the code

Call chain:

i1:org.springframework.context.support.AbstractApplicationContext#refresh
>i2:org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors
 >i3:org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
  >i4:org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors
   >i5:org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
    >i6:org.springframework.context.annotation.ConfigurationClassParser#parse
     >i7:org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass
      >i8:org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass
Copy the code
  • I3 tags in the source code parsing org. Springframework. Context. Support. PostProcessorRegistrationDelegate# invokeBeanFactoryPostProcessors
public static void invokeBeanFactoryPostProcessors(
      ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

   // Invoke BeanDefinitionRegistryPostProcessors first, ifany. Set<String> processedBeans = new HashSet<>(); // Determine if the IOC container is BeanDefinitionRegistryif(beanFactory instanceof BeanDefinitionRegistry) {cast an IOC container to BeanDefinitionRegistry of type BeanDefinitionRegistry  = (BeanDefinitionRegistry) beanFactory; List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); / / create a BeanDefinitionRegistryPostProcessor type of list list < BeanDefinitionRegistryPostProcessor > registryProcessors = new ArrayList<>(); // Handle the beanFactoryProcessor that the container hardcoded (out of new) intofor(spring BeanFactoryPostProcessor postProcessor: beanFactoryPostProcessors) {/ / BeanDefinitionRegistryPostProcessor judgmentif(postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor =  (BeanDefinitionRegistryPostProcessor) postProcessor; / / call BeanDefinitionRegistryPostProcessor postProcessBeanDefinitionRegistry registryProcessor.postProcessBeanDefinitionRegistry(registry); / / added to the list in the collection ConfigurationClassPostProcessor registryProcessors. Add (registryProcessor); }else{/ / judgment not BeanDefinitionRegistryPostProcessor / / regularPostProcessors added to the collection. The add (postProcessor); } } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized toletthe bean factory post-processors apply to them! // Separate between BeanDefinitionRegistryPostProcessors that implement // PriorityOrdered, Ordered, And the rest. / / create a collection of RegistryProcessors current registered List < BeanDefinitionRegistryPostProcessor > currentRegistryProcessors = new  ArrayList<>(); // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. // The first step: to container query whether have BeanDefinitionRegistryPostProcessor type String [] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,true.false);
      for(String ppName: postProcessorNames) {// Check whether the PriorityOrdered interface is implementedif(beanFactory.isTypeMatch(ppName, PriorityOrdered. Class)) {/ / added to the collection of currentRegistryProcessors currentRegistryProcessors. Add (the beanFactory) getBean (ppName, BeanDefinitionRegistryPostProcessor.class)); Processedbeans.add (ppName); // Add to the collection of processedBeans. }} / / sorting sortPostProcessors (currentRegistryProcessors, the beanFactory); registryProcessors.addAll(currentRegistryProcessors); / / call BeanDefinitionRegistryPostProcessors postProcessBeanDefinitionRegistry method invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. // Step 2: go to the container if there is a BeanDefinitionRegistryPostProcessor type postProcessorNames = query beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,true.false);
      for(String ppName: postProcessorNames) {// Exclude those that were processed and implemented the Ordered interfaceif(! processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); // Add processedBeans.add(ppName) to the list to process; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); / / call BeanDefinitionRegistryPostProcessors postProcessBeanDefinitionRegistry method invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. / / call ordinary BeanDefinitionRegistryPostProcessors useless implementing Boolean PriorithOrdered and Ordered interface reiterate =true;
      while (reiterate) {
         reiterate = false;
         postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
         for (String ppName : postProcessorNames) {
            if(! processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate =true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); } // Now, Invoke the postProcessBeanFactory callback of all processors handled so far. / / call appeals realized also realized BeanFactoryPostProcessors interface invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); }else {
      // Invoke factory processors registered with the context instance.
      invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
   }

   // Do not initialize FactoryBeans here: We need to leave all regular beans
   // uninitialized to letthe bean factory post-processors apply to them! // Go to the IOC container and get String[] postProcessorNames = of type BeanFactoryPostProcessor beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class,true.false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, And the rest. / / separation achieved PriorityOrdered interface Ordered interface of ordinary List < spring BeanFactoryPostProcessor > priorityOrderedPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>();for (String ppName : postProcessorNames) {
      if (processedBeans.contains(ppName)) {
         // skip - already processed in first phase above
      }
      else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
         priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
      }
      else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
         orderedPostProcessorNames.add(ppName);
      }
      else{ nonOrderedPostProcessorNames.add(ppName); } } // First, Invoke the BeanFactoryPostProcessors that implement PriorityOrdered. / / call PriorityOrdered. sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, Invoke the BeanFactoryPostProcessors that implement Ordered. / / call Ordered. List < spring BeanFactoryPostProcessor > orderedPostProcessors = new ArrayList<>();for(String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, Invoke all other BeanFactoryPostProcessors. / / call ordinary List < spring BeanFactoryPostProcessor > nonOrderedPostProcessors = new ArrayList<>();for (String postProcessorName : nonOrderedPostProcessorNames) {
      nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
   }
   invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

   // Clear cached merged bean definitions since the post-processors might have
   // modified the original metadata, e.g. replacing placeholders in values...
   beanFactory.clearMetadataCache();
}
Copy the code
  • I5 tags in the source code parsing, org. Springframework. Context. The annotation. ConfigurationClassPostProcessor# processConfigBeanDefinitions
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); / / not before parsing system candidate bean definition configuration (own) have their own system String [] candidateNames = registry. GetBeanDefinitionNames (); // The name of the loop Bean definition finds its own incoming Bean definition message configCandidates for the main configuration classfor(String beanName : candidateNames) { BeanDefinition beanDef = registry.getBeanDefinition(beanName); // Check whether the bean definition object is used to describe the configuration classif (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));
      }
   }

   // Return immediately if no @Configuration classes were found
   if (configCandidates.isEmpty()) {
      return;
   }

   // Sort by previously determined @Order value, ifConfigcandidates.sort ((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());returnInteger.compare(i1, i2); }); // Detect any custom bean name generation strategy supplied through the enclosing Application Context SingletonBeanRegistry sbr = null;if (registry instanceof SingletonBeanRegistry) {
      sbr = (SingletonBeanRegistry) registry;
      if(! this.localBeanNameGeneratorSet) { BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);if(generator ! = null) { this.componentScanBeanNameGenerator = generator; this.importBeanNameGenerator = generator; }}}if(this.environment == null) { this.environment = new StandardEnvironment(); } / * * * to create a configuration class parser reader factory this. 1) metadata metadataReaderFactory = metadataReaderFactory; 3) this. ProblemReporter = problemReporter; // Set environment this. Environment = environment; This. ResourceLoader = resourceLoader; 4) to create a component scanner this.com ponentScanParser = new ComponentScanAnnotationParser (environment, resourceLoader, componentScanBeanNameGenerator, registry); this.conditionEvaluator = new ConditionEvaluator(registry, environment, resourceLoader); ****/ // Parse each @Configuration class ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); // Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); // Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); // The configuration class that has been resolved (due todo whileConfigurationClass> alreadyParsed = new HashSet<>(configcandidates.size ());doParser. parse(candidates); // Run the parser.parser command. Parser.validate (); Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); configClasses.removeAll(alreadyParsed); // Read the model and create bean definitions based on its contentif(this.reader == null) { this.reader = new ConfigurationClassBeanDefinitionReader( registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry()); } / / @ CompentScan is directly registered Bean definitions of information But by getting @ Import @ Bean this annotation is not yet registered Bean definitions, enclosing reader. LoadBeanDefinitions (configClasses); // alreadyParsed alreadyParse.addall (configClasses); // Clear the parsed configuration file candidate.clear (); // The number of registered bean definitions is greater than that of the latest start system + main configuration class.if(registry. GetBeanDefinitionCount () > candidateNames. Length) {/ / acquisition system + own parsing + mainconfig String bean definition information [] newCandidateNames = registry.getBeanDefinitionNames(); Set<String> oldCandidateNames = new HashSet<>(arrays.aslist (candidateNames)); Set<String> alreadyParsedClasses = new HashSet<>();for (ConfigurationClass configurationClass : alreadyParsed) {
            alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
         }
         for(String candidateName: newCandidateNames) {// Old (system +mainconfig) does not contain parsedif(! OldCandidateNames. The contains (candidateName)) {/ / the current bean definitions BeanDefinition bd = get out registry.getBeanDefinition(candidateName); // Check if it is parsedif(ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && ! AlreadyParsedClasses. The contains (bd) getBeanClassName ())) {/ / if it is not parsed and by examining the current bean definitions join the candidates candidates. Add (new BeanDefinitionHolder(bd, candidateName)); }} // if (candidateNames = newCandidateNames) {// if (candidateNames = newCandidateNames; }}while(! candidates.isEmpty()); // Register the ImportRegistry as a beanin order to support ImportAware @Configuration classes
   if(sbr ! = null && ! sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) { sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry()); }if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
      // Clear cache in externally provided MetadataReaderFactory; this is a no-op
      // for a shared cache since it'll be cleared by the ApplicationContext. ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache(); }}Copy the code
  • I6 tags in the source code parsing org. Springframework. Context. The annotation. ConfigurationClassParser# parse
public void parse(Set<BeanDefinitionHolder> configCandidates) {
   this.deferredImportSelectors = new LinkedList<>();

   for(BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); // Define information for the bean in the form of annotationsif(AnnotatedBeanDefinition) {parse((AnnotatedBeanDefinition).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(); } = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = >org.springframework.context.annotation.ConfigurationClassParser#parse
	>org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass
 
 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);
}

===================================================================
>org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
      throws IOException {

   // Recursively process any member (nested) classes first
   processMemberClasses(configClass, sourceClass);

   // Process any @PropertySource annotations
   //处理@PropertySource注解
   for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
         sourceClass.getMetadata(), PropertySources.class,
         org.springframework.context.annotation.PropertySource.class)) {
      if (this.environment instanceof ConfigurableEnvironment) {
         processPropertySource(propertySource);
      }
      else {
         logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
               "]. Reason: Environment must implement ConfigurableEnvironment");
      }
   }

    //处理@ComponentScan注解
    //解析@ComponentScans注解的属性 封装成一个一个的componentscan对象
   // Process any @ComponentScan annotations
   Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
         sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
   if (!componentScans.isEmpty() &&
         !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
      //循环componentScans的set
      for (AnnotationAttributes componentScan : componentScans) {
         // The config class is annotated with @ComponentScan -> perform the scan immediately
         // 立即执行扫描解析
         Set<BeanDefinitionHolder> 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) {
            //获取原始的bean定义信息
            BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
            if (bdCand == null) {
               bdCand = holder.getBeanDefinition();
            }
            //检查当前的bean定义信息是不是配置类  比如MainConfig的bean定义信息
            if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
               //递归调用来解析MainConfig,解析出来配置类的中导入的bean定义信息
               parse(bdCand.getBeanClassName(), holder.getBeanName());
            }
         }
      }
   }
   
   //处理@Import注解   解析Import 注解的ImportSelector  ImportBeanDefinitionRegister,@Bean这种
	//存放在ConfigClass中
   // Process any @Import annotations
   processImports(configClass, sourceClass, getImports(sourceClass), true);

   //处理 @ImportResource annotations
   // Process any @ImportResource annotations
   AnnotationAttributes importResource =
         AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
   if (importResource != null) {
      String[] resources = importResource.getStringArray("locations");
      Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
      for (String resource : resources) {
         String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
         configClass.addImportedResource(resolvedResource, readerClass);
      }
   }
   // 处理  @Bean methods
   // Process individual @Bean methods
   Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
   for (MethodMetadata methodMetadata : beanMethods) {
      configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
   }
   //处理接口
   // Process default methods on interfaces
   processInterfaces(configClass, sourceClass);
   // 处理超类的
   // Process superclass, if any
   if (sourceClass.getMetadata().hasSuperClass()) {
      String superclass = sourceClass.getMetadata().getSuperClassName();
      if (superclass != null && !superclass.startsWith("java") &&
            !this.knownSuperclasses.containsKey(superclass)) {
         this.knownSuperclasses.put(superclass, configClass);
         // Superclass found, return its annotation metadata and recurse
         return sourceClass.getSuperClass();
      }
   }

   // No superclass -> processing is complete
   return null;
}

=========================================================
//通过组件扫描器进行真正的解析
>org.springframework.context.annotation.ComponentScanAnnotationParser#parse

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
   //创建一个类路径下的bean定义扫描器
   ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
         componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

   //为扫描器设置一个bean 名称的生成器
   Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
   boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
   scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
         BeanUtils.instantiateClass(generatorClass));

   ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
   if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
      scanner.setScopedProxyMode(scopedProxyMode);
   }
   else {
      Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
      scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
   }

   scanner.setResourcePattern(componentScan.getString("resourcePattern"));

   for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
      for (TypeFilter typeFilter : typeFiltersFor(filter)) {
         scanner.addIncludeFilter(typeFilter);
      }
   }
   for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
      for (TypeFilter typeFilter : typeFiltersFor(filter)) {
         scanner.addExcludeFilter(typeFilter);
      }
   }

   boolean lazyInit = componentScan.getBoolean("lazyInit");
   if (lazyInit) {
      scanner.getBeanDefinitionDefaults().setLazyInit(true);
   }

   Set<String> basePackages = new LinkedHashSet<>();
   String[] basePackagesArray = componentScan.getStringArray("basePackages");
   for (String pkg : basePackagesArray) {
      String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
            ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
      Collections.addAll(basePackages, tokenized);
   }
   for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
      basePackages.add(ClassUtils.getPackageName(clazz));
   }
   if (basePackages.isEmpty()) {
      basePackages.add(ClassUtils.getPackageName(declaringClass));
   }

   scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
      @Override
      protected boolean matchClassName(String className) {
         return declaringClass.equals(className);
      }
   });
   //真正扫描器扫描指定路径
   return scanner.doScan(StringUtils.toStringArray(basePackages));
}

===========================================================
>org.springframework.context.annotation.ClassPathBeanDefinitionScanner#ClassPathBeanDefinitionScanner

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
      Environment environment, @Nullable ResourceLoader resourceLoader) {

   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
   this.registry = registry;

   //使用默认的扫描规则
   if (useDefaultFilters) {
      registerDefaultFilters();
   }
   //设置环境变量
   setEnvironment(environment);
   //设置资源加载器
   setResourceLoader(resourceLoader);
}

=====================================
//默认的扫描规则
protected void registerDefaultFilters() {
    //添加了Componet的解析,这就是我们为啥@Componet @Respository @Service @Controller的  @AspectJ
   this.includeFilters.add(new AnnotationTypeFilter(Component.class));
   ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
   try {
      //添加Jsr 250规范的注解 
      this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
      logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning"); } catch (ClassNotFoundException ex) {// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.} try { This.includefilters. Add (new AnnotationTypeFilter((Class
      ) ClassUtils.forName("javax.inject.Named", cl)), false)); logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. } } = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = use the scanner to the real scanning class, return to the Set < BeanDefinitionHolder > >org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan protected Set
      
        doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); //// Set
       
         beanDefinitions = new LinkedHashSet<>(); // Loop scan path for (String basePackage: BasePackages) {Set
        
          Candidates = findCandidateComponents(basePackage); // For (BeanDefinition candidate: candidates) { ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); / / the name of the generated bean String beanName = this. BeanNameGenerator. GenerateBeanName (candidate, enclosing registry); / / determine whether abstract bean definition if (candidate instanceof AbstractBeanDefinition) {postProcessBeanDefinition ((AbstractBeanDefinition) candidate, beanName); } // AnnotatedBeanDefinition if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } if (checkCandidate(beanName, BeanDefinitionHolder BeanDefinitionHolder = new {// Check whether the current and storage bean definitions conflict BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); // Add beandefines.add (definitionHolder) to the collection of bean definitions; RegisterBeanDefinition (definitionHolder, this.registry); } } } return beanDefinitions; } = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = > org. Springframework. Context. The annotation. ClassPathScanningCandidateComponentProvider# findCandidateComponents find candidate components Returns a collection of Set
         
           >org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandidateComponents private Set
          
            scanCandidateComponents(String basePackage) {// // Candidate bean definition message Set
           
             Candidates = new LinkedHashSet<>(); Try {/ / stitching need to scan the package of the following class path classpath * : com/niuh/testapplicationlistener / * * / *. The class String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '
           
          
         
        
       
      /' + this.resourcePattern; / / the path parsed into one by one. The class file Resource [] resources = getResourcePatternResolver () getResources (packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); For (resource Resource: resources) {if (traceEnabled) {logger.trace("Scanning "+ resource); If (resource.isreadable ()) {try {MetadataReader MetadataReader = getMetadataReaderFactory().getMetadataReader(resource); / / whether the source of the class information the reader for the candidate components if (isCandidateComponent (metadataReader)) {/ / is the candidate components / / encapsulate a meta information the reader into a ScannedGenericBeanDefinition ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setResource(resource); sbd.setSource(resource); // Is the candidate component if (isCandidateComponent(SBD)) {if (debugEnabled) {logger.debug("Identified candidate component class: " + resource); } // Add the current parsed definition to the BeanDefinition candidate.add (SBD); // Add the current parsed definition to the BeanDefinition candidate.add (SBD); } else { if (debugEnabled) { logger.debug("Ignored because not a concrete top-level class: " + resource); } } } else { if (traceEnabled) { logger.trace("Ignored because not matching any filter: " + resource); } } } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to read candidate component class: " + resource, ex); } } else { if (traceEnabled) { logger.trace("Ignored because not readable: " + resource); } } } } catch (IOException ex) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } return candidates; } = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = if need scan components org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#isCandidateComponent protected Boolean isCandidateComponent(MetadataReader MetadataReader) throws IOException {// For (TypeFilter tf: this.excludeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { return false; }} // In the included component for (TypeFilter tf: this.includeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { return isConditionMatch(metadataReader); } } return false; } = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = can @ Conditional judgment org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#isConditionMatch private boolean isConditionMatch(MetadataReader metadataReader) { if (this.conditionEvaluator == null) { this.conditionEvaluator = new ConditionEvaluator(getRegistry(), getEnvironment(), getResourceLoader()); } return ! this.conditionEvaluator.shouldSkip(metadataReader.getAnnotationMetadata()); }Copy the code