This is the 25th day of my participation in the August Genwen Challenge.More challenges in August

preface

It says it found Spring source code deprecation series, but Spring source code content is really too much, Or from the refresh template method in core method. InvokeBeanFactoryPostProcessors method will instantiate and call all spring BeanFactoryPostProcessor (including its subclasses BeanDefinitionRegistryPostProcessor).

The BeanFactoryPostProcessor interface is the extension point exposed when Spring initializes the BeanFactory. The Spring IoC container allows the BeanFactoryPostProcessor to read the definition of a bean before the container instantiates any bean, (This is why the Spring Ecosystem is so popular, providing a series of extension points for third-party frameworks to integrate with).

BeanDefinitionRegistryPostProcessor inherited from spring BeanFactoryPostProcessor, a higher priority than spring BeanFactoryPostProcessor, It is used to register other bean definitions before normal BeanFactoryPostProcessor testing begins.

Spring source code analysis series

  • Spring source code analysis – source code reading environment construction
  • Spring source Code analysis -IOC basic concepts
  • Spring source code analysis -IOC core components
  • Spring Source Code Analysis -IOC source code Analysis (1)
  • Spring IOC source code analysis -obtainFreshBeanFactory

Source code analysis

1. refresh#invokeBeanFactoryPostProcessors

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   / / 1. GetBeanFactoryPostProcessors () to obtain the current application context
   / / 2. InvokeBeanFactoryPostProcessors instantiate and call all registered BeanFactoryPostProcessors
   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)
   if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      beanFactory.setTempClassLoader(newContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); }}Copy the code

2. getBeanFactoryPostProcessors

/ / get beanFactoryPostProcessors context has been registered
/ / by default, the enclosing beanFactoryPostProcessors is to return empty.
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors(a) {
   return this.beanFactoryPostProcessors;
}
Copy the code

GetBeanFactoryPostProcessors () will get the current application context have registered a spring BeanFactoryPostProcessor, by default, the enclosing beanFactoryPostProcessors is to return empty.

So how do you add a BeanFactoryPostProcessor to a beanFactory?

The two methods

  1. Register your implementation of beanFactoryPostProcessor with beanFactory as an annotation.
  2. Create a new ApplicationContextInitializer implementation class SpringApplicationContextInitializer and write our logic in the initialize method.
// Implement BeanFactoryPostProcessor with annotations
@Component
public class MyBeanPostProcessor implements BeanFactoryPostProcessor {
   @Override
   public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
      System.out.println("this is my BeanFactoryPostProcessor"); }}Copy the code

// No component annotation is required
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
   @Override
   public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
      System.out.println("this is my BeanFactoryPostProcessor2"); }}/ / by ApplicationContextInitializer add spring BeanFactoryPostProcessor implementation class
public class SpringApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
   @Override
   public void initialize(ConfigurableApplicationContext applicationContext) {
      MyBeanFactoryPostProcessor myBeanFactoryPostProcessor = newMyBeanFactoryPostProcessor(); applicationContext.addBeanFactoryPostProcessor(myBeanFactoryPostProcessor); }}Copy the code

3. invokeBeanFactoryPostProcessors

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

   // Invoke BeanDefinitionRegistryPostProcessors first, if any.
   Set<String> processedBeans = new HashSet<>();

   // 1. Check whether beanFactory is BeanDefinitionRegistry
   if (beanFactory instanceof BeanDefinitionRegistry) {
      BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
      // Used to store ordinary BeanFactoryPostProcessor
      List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
      / / to hold BeanDefinitionRegistryPostProcessor
      / / mybatis rear BeanDefinitionRegistryPostProcessor processor is used to realize the bean and beandefinition
      List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

      / / 2. Traverse all beanFactoryPostProcessors, will be treated as ordinary spring BeanFactoryPostProcessor and BeanDefinitionRegistryPostProcessor respectively
      for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
         if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
            BeanDefinitionRegistryPostProcessor registryProcessor =
                  (BeanDefinitionRegistryPostProcessor) postProcessor;
            registryProcessor.postProcessBeanDefinitionRegistry(registry);
            registryProcessors.add(registryProcessor);
         }
         else{ regularPostProcessors.add(postProcessor); }}/ / retention of secondary BeanDefinitionRegistryPostProcessor execution
      List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

      // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
      / / 3. Call all realize PriorityOrdered interface BeanDefinitionRegistryPostProcessors implementation class
      / / 3.1 find BeanName BeanDefinitionRegistryPostProcessor interface beans
      String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
      // 3.2 Iterate through postProcessorNames
      for (String ppName : postProcessorNames) {
         // 3.3 Checking whether the PriorityOrdered interface is implemented
         if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            / / 3.4 obtained ppName corresponding Bean instance, added to the currentRegistryProcessors
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            / / 3.5 against the heavyprocessedBeans.add(ppName); }}// 3.6 Sort (based on whether the PriorityOrdered, Ordered interface, and order values are implemented)
      sortPostProcessors(currentRegistryProcessors, beanFactory);
      // 3.7 Adds processors to registryProcessors
      registryProcessors.addAll(currentRegistryProcessors);
      / / 3.8 traversal currentRegistryProcessors BeanDefinitionRegistryPostProcessor and execution
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
      / / 3.9 to empty
      currentRegistryProcessors.clear();

      // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
      / / 4. Call for Ordered interface BeanDefinitionRegistryPostProcessor implementation class
      / / 4.1 to find out all the implementation BeanDefinitionRegistryPostProcessor interface classes
      postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true.false);
      for (String ppName : postProcessorNames) {
         // Verify that the Ordered interface is implemented
         if(! processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors);/ / 4.2 traversal currentRegistryProcessors BeanDefinitionRegistryPostProcessor and execution
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
      currentRegistryProcessors.clear();

      // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
      / / 5. Finally, call all the remaining BeanDefinitionRegistryPostProcessors
      boolean 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.
      / / 6. Call all BeanDefinitionRegistryPostProcessor postProcessBeanFactory method
      invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
      // 7. Finally, call the postProcessBeanFactory method of regularPostProcessors
      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 let the bean factory post-processors apply to them!
   / / handle your spring BeanFactoryPostProcessor container, process is similar to the above
   // 8. Find the implementation class of the BeanFactoryPostProcessor interface
   String[] postProcessorNames =
         beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true.false);

   // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
   // Ordered, and the rest.
   List<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.
   sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
   invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

   // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
   List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
   for (String postProcessorName : orderedPostProcessorNames) {
      orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
   }
   sortPostProcessors(orderedPostProcessors, beanFactory);
   invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

   // Finally, invoke all other BeanFactoryPostProcessors.
   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, e.g. replacing placeholders in values...
   beanFactory.clearMetadataCache();
}
Copy the code