Spring source code (6) How does BeanFactoryPostProcessor execute?

The postProcessBeanFactory empty method provided by AbstractApplicationContext

The method postProcessBeanFactory does not have the same name as the method in the BeanFactoryPostProcessor interface, but its function is to provide subclasses to add some additional functions, such as adding the implementation of the BeanPostProcessor interface, or customizing some other functions. You can get BeanFactory, and you can customize some functions of it.

Here is how the subclasses provided by Spring  GenericWebApplicationContext are implemented:

@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
  if (this.servletContext != null) {
    beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
    beanFactory.ignoreDependencyInterface(ServletContextAware.class);
  }
  WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
  WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
}

Here he registers a  ServletContextAwreProcessor to  beanFactory , which  ServletContexAwareProcessor is a  BeanPostProcessor subclass of an interface.

The highlight is BeanFactoryPostProcessor

AbstractApplicationContext#refresh The method in the  next analysis  invokeBeanFactoryPostProcessors , this method is used to register and execute  BeanFactoryPostProcessor .

Go directly to the source code:

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
  // 执行所有的BeanFactoryPostProcessor
  PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

  // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
  // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
  // aop的处理
  if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
    beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
    beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
  }
}

The point is here:

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

The collection obtained first  BeanFactoryPostProcessor , all obtained here are added by the user when customizing  BeanFactory ,  add enter this method:

public static void invokeBeanFactoryPostProcessors( 
  ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { 

  // Invoke BeanDefinitionRegistryPostProcessors first, if any. 
  // Processed Beans 
  Set<String> processedBeans = new HashSet<>(); 
  // Advanced external BFPP Process and judge whether the current Factory is a BeanDefinitionRegistry 
  if (beanFactory instanceof BeanDefinitionRegistry) { 
    BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; 
    // Save BFPP Bean 
    List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); 
    // Save BDRPP Bean 
    List <BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); 
    / / Start processing external incoming BFPP 
    for (BeanFactoryPostProcessor postProcessor :beanFactoryPostProcessors) { 
      // Process BDRPP first 
      if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { 
        BeanDefinitionRegistryPostProcessor registryProcessor = 
          (BeanDefinitionRegistryPostProcessor) postProcessor; 
        // Directly call the interface method of BDRPP, and the following postProcessBeanFactory method will uniformly process 
        registryProcessor.postProcessBeanDefinitionRegistry(registry ); 
        // Add to the collection of BFPP 
        registryProcessors.add(registryProcessor); 
      } 
      else { 
        // Add to the collection of 
        BDRPP regularPostProcessors.add(postProcessor); 
      } 
    } 

    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let the bean factory post-processors apply to them! 
      // Determine the current beanName Yes, they all implement PriorityOrdered
    // Separate between BeanDefinitionRegistryPostProcessors that implement 
    // PriorityOrdered, Ordered, and the rest. 
    // Save the current BDRPP 
    List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); 

    // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. 
    // Press Type get BeanName 
    String[] postProcessorNames = 
      beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); 
    for (String ppName : postProcessorNames) { 
      if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { 
        // Add to the currently registered In the BDRPP collection 
        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); 
        // Add to the processed beans collection 
        processedBeans.add(ppName); 
      } 
    } 
    / / Sort the current BDRPP 
    sortPostProcessors(currentRegistryProcessors, beanFactory); 
    // Add all the current BDRPP to the set of BDRPP defined at the front 
    registryProcessors.addAll(currentRegistryProcessors); 
    // Execute the postProcessBeanDefinitionRegistry method of the current BDRPP 
    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors , registry); 
    // clear the current BDRPP 
    currentRegistryProcessors.clear();

    // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. 
    // sort
    // Get bdrpp again, because the above execution may also add new bdrpp in 
    postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); 
    for (String ppName : postProcessorNames) { 
      // Determine whether it has been processed, and Whether the Ordered interface is implemented 
      if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { 
        // Add to the current BDRPP collection 
        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class )); 
        // add to the processed set 
        processedBeans.add(ppName); 
      } 
    } 
    sortPostProcessors(currentRegistryProcessors, beanFactory); 
    // add to the BDRPP set
    registryProcessors.addAll(currentRegistryProcessors); 
    // Execute bdrpp's postProcessBeanDefinitionRegistry method 
    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); 
    // Clear the current bdrpp collection 
    currentRegistryProcessors.clear(); 

    // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. 
    boolean reiterate = true; 
    // Loop to get BDRPP, then sort and perform operations until all BDRPP are executed 
    while (reiterate) { 
      reiterate = false; 
      // Get BDRPP  
      postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor .class, true, false);
      for (String ppName : postProcessorNames) { 
        // If it has been processed , execute BDRPP and exit the loop, otherwise continue the loop 
        if (!processedBeans.contains(ppName)) {
          currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
          processedBeans.add(ppName);
          reiterate = true;
        }
      }
      // 排序
      sortPostProcessors(currentRegistryProcessors, beanFactory);
      // 加入到BDRPP集合中
      registryProcessors.addAll(currentRegistryProcessors);
      // 执行bdrpp
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
      currentRegistryProcessors.clear();
    }

    // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
    // Execute the postProcessBeanFactory method in
    invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
    // Execute the postProcessBeanFactory method in 
    bfpp invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); 
  } 

  else { 
    // If it is not bdrpp, then directly execute the postProcessBeanFactory of bfpp 
    // 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 let the bean factory post-processors apply to them! 
  // Get BFPP's beanName collection 
  String[] postProcessorNames = 
    beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true , false);

  // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, 
  // Ordered, and the rest. 
  // Define a BFPP 
  List that implements PriorityOrdered<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); 
  // Define a collection that implements the Ordered interface 
  // List <String> orderedPostProcessorNames = new ArrayList<>(); 
  List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(); 
  // define an unordered collection 
  // List<String> nonOrderedPostProcessorNames = new ArrayList<>(); 
  List<BeanFactoryPostProcessor > nonOrderedPostProcessors = new ArrayList<>(); 
  for (String ppName : postProcessorNames) { 
    // don't do processing if already processed 
    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);
      orderedPostProcessors.add(beanFactory.getBean(ppName,BeanFactoryPostProcessor.class));
    }
    else {
      //				nonOrderedPostProcessorNames.add(ppName);
      nonOrderedPostProcessors.add(beanFactory.getBean(ppName,BeanFactoryPostProcessor.class));
    }
  }

  // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. 
  // Sort 
  // for (String postProcessorName : orderedPostProcessorNames) {
  sortPostProcessors(priorityOrderedPostProcessors, beanFactory); 
  // First execute the bfpp of the PriorityOrdered interface 
  invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); 

  // Next, invoke the BeanFactoryPostProcessors that implement Ordered. 
  // Here, the BFPP obtained from the Ordered interface is converted into a collection, and then sorted , and then execute, which can be directly merged here, 
  // put it in this orderedPostProcessors collection when the above is obtained 
  // List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size()); 
  // orderedPostProcessors.add( beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); 
  // } 
  sortPostProcessors(orderedPostProcessors, beanFactory); 
  invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

  // Finally, invoke all other BeanFactoryPostProcessors. 
  // Process unordered 
  // List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); 
  // 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, eg replacing placeholders in values... 
  // Clear the cached metadata, because the BFPP's Execution, the property value of the BeanDefinition may have changed, such as using the property value of the placeholder 
  beanFactory.clearMetadataCache(); 
}

This method is probably very long, but in fact it does a few things:

  • BeanFactoryPostProcessor Execute the implementation of the external incoming first 
  •  The implementation BeanFactoryPostProcessor of the sub-interface  that is processed first BeanDefinitionRegistryPostProcessor
  • When processing  BeanDefinitionRegistryPostProcessor the implementation, first process  PriorityOrdered the implementation that implements the interface
  • After processing  PriorityOrdered the class that implements the interface, then process  Ordered the implementation that implements the interface
  • After the implementation class of the  Ordered interface is processed, the unsorted ones are processed
  • Processed  BeanDefinitionRegistryPostProcessor implementation after processed  BeanFactoryPostProcessor implementation
  • The processing order is also  PriorityOreded ,  Ordered , not sorted

The approximate logic here is this, it may not seem to understand very well, draw a flow chart:

Through the flow chart, it can be simplified as: first traverse and execute the external input  BFPP , then execute  BDRPP , and then execute the  BFPP three parts, and each part may be sorted, sorted according to  PriorityOrdered ,  Ordered ,  noSort and then executed.

Explained here  BeanDefinitionRegistryPostProcessor , this interface is  BeanFactoryPostProcessor that it contains a method called  postProcessBeanDefinitionRegistry . This method is very important. This method  ConfigurationClassPostProcessor is used to parse annotations in the implementation class, and this class is also  SpringBoot the key to automatic assembly.

ConfigurationClassPostProcessor When was this class added to the  Spring container?

When we start the container,  the scan Spring will be performed  BeanDefinition , if we  xml enable annotation scanning in the configuration file:

<context:component-scan base-package="com.redwinter.test"/>

Then at this time, more than one will be automatically added  BeanDefinition to the  Spring container,  beanName for  org.springframework.context.annotation.internalConfigurationAnnotationProcessor , there are several others:

Previous  articleSpring source code (4) How to implement custom tags in Spring configuration files? - Ling, Xi- Blog Garden  talks about custom tags. When spring parses xml, it is divided into default namespace and custom namespace, and context is a custom namespace. The parser of this tag is ComponentScanBeanDefinitionParser, this class The parse method in is parsing logic processing:

@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
  String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
  basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
  String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
                                                            ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
  // Actually scan for bean definitions and register them.
  // 配置扫描器
  ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
  // 扫描BeanDefinition,在指定的包下
  Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
  // 注册组件
  registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

  return null;
}

This method executes the process:

BeanDefinition
registerComponents

registerComponents The method is  ConfigurationClassPostProcessor the place to add, because there is too much code, only part of the code is posted here:

// ... omit part of the code 
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8); 
		// Determine whether the register contains org.springframework.context.annotation.internalConfigurationAnnotationProcessor 
		// If not, add a BeanDefinition of ConfigurationClassPostProcessor 
		// For parsing annotations 
		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { 
			// Create a BeanDefinition as ConfigurationClassPostProcessor 
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); 
			def.setSource(source); 
			// Register a beanName as org. springframework.context.annotation.internalConfigurationAnnotationProcessor 
			// BeanDefinition, class is ConfigurationClassPostProcessor
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); 
		} 
		// Create a BeanDefinition of AutowiredAnnotationBeanPostProcessor 
		// for autowiring 
		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { 
			RootBeanDefinition def = new RootBeanDefinition(;AutowiredAnnotationBeanPostProcessor.) 
			def.setSource(source); 
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); 
		} 
// ...omit some code

A name is registered as a constant in the source code  beanName .  CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME This constant is  org.springframework.context.annotation.internalConfigurationAnnotationProcessor ,  class for ConfigurationClassPostProcessor

Guess you like

Origin blog.csdn.net/Trouvailless/article/details/124449384