obtainFreshBeanFactory of Spring startup process source code

Invokebeanfactoryprocessors is a very important method in Spring startup. We need to understand several concepts before parsing the source code of this method.

1, BeanDefinition

1.1. Instantiation of common objects

We know that ordinary java files will be compiled into java files when Java runs When we instantiate an object into memory, we use new to load it into memory as follows:

1.2. Instantiation of bean s in Spring

Instantiating an object in Spring is different from ordinary java files. It introduces a BeanDefinition object. BeanDefinition is an interface. Its main function is to describe some information of Java objects, including whether they are singletons, methods and properties in Java objects, which can be regarded as another class object. The inheritance diagram of BeanDefinition is as follows:

From the figure, we can see that BeanDefinition is mainly implemented by the following:

  1. GenericBeanDefinition: General bean implementation. The newly added bean file configuration attribute definition class since 2.5 is a better substitute for ChildBeanDefinition and RootBeanDefinition;
  2. ScannedGenericBeanDefinition: the bean definition scanned by the package;
  3. AnnotatedGenericBeanDefinition: find the definition of class annotation initialization;
  4. RootBeanDefinition: represents a BeanDefinition generated from the configuration source (XML, Java Config, etc.)
  5. ChildBeanDefinition: you can integrate construction methods, attributes, etc. from the parent BeanDefinition.

Refer to the following figure for the instantiation process of Spring:

See my other article for the specific process and source code analysis [Spring] three level cache and circular dependency in Spring

There will be no detailed comparison and elaboration here.  

2, Invokebeanfactoryprocessors

The source code of invokebeanfactoryprocessors is at org springframework. context. support. Abstractapplicationcontext#invokebeanfactoryprocessors combines the concepts of BeanDefinition we mentioned earlier. The specific analysis is as follows:

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory{
		/**
		 * The beanfactor postprocessor is called here through reflection
		 * The calling sequence is: 1 Bean definition registration post processor, 2 Bean factory post processor
		 * The process of creating beans such as getBean, doGetBean, createBean and doCreateBean will also be called
         * Note: getbeanfactoryprocessors is an initialization object, and there is no content in it
		 */
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());  // ===>
		
		//Detect the existence of loadTimeWeaver
		if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
}

As can be seen from the above code, the main implementation of invokebeanfactory postprocessors is postprocessor registrationdelegate invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); This line of code, so what does it do? Let's continue to look.

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
        //A collection that holds the names of all postprocessor bean s
		Set<String> processedBeans = new HashSet();
		//Beanfactoryprocessor collection
        ArrayList regularPostProcessors;
		//BeanDefinitionRegistryPostProcessor collection
        ArrayList registryProcessors;
        int var9;
        ArrayList currentRegistryProcessors;
        String[] postProcessorNames;
		//Beanfactoryprocessors are divided into beanfactoryprocessor set and BeanDefinitionRegistryPostProcessor set
		//1. Judge whether beanFactory is BeanDefinitionRegistry. Ordinary beanFactory is DefaultListableBeanFactory, and DefaultListableBeanFactory implements BeanDefinitionRegistry interface, so it is true here
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
            regularPostProcessors = new ArrayList();
            registryProcessors = new ArrayList();
            Iterator var6 = beanFactoryPostProcessors.iterator();

			//2. Processing input parameter bean factorypostprocessors
            while(var6.hasNext()) {
                BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var6.next();
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor)postProcessor;
                    //If it is BeanDefinitionRegistryPostProcessor, directly execute the postProcessBeanDefinitionRegistry method of BeanDefinitionRegistryPostProcessor interface
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                } else {
                    regularPostProcessors.add(postProcessor);
                }
            }

            currentRegistryProcessors = new ArrayList();
			//3. Find out the beanName of all beans that implement the BeanDefinitionRegistryPostProcessor interface
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            String[] var16 = postProcessorNames;
            var9 = postProcessorNames.length;

            int var10;
            String ppName;
            for(var10 = 0; var10 < var9; ++var10) {
                ppName = var16[var10];
				//Verify whether the PriorityOrdered interface is implemented
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					//Get the corresponding bean instance and add it to currentRegistryProcessors
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
			//Sort (sort according to whether priorityordered, ordered interface and order value are implemented)
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
			//Traverse currentRegistryProcessors and execute the postProcessBeanDefinitionRegistry method
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			//Empty currentRegistryProcessors
            currentRegistryProcessors.clear();
			
			//4. The process is similar to that in the above 3. This is to implement the Ordered interface
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            var16 = postProcessorNames;
            var9 = postProcessorNames.length;

            for(var10 = 0; var10 < var9; ++var10) {
                ppName = var16[var10];
                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);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
			
			//5. Call all the remaining BeanDefinitionRegistryPostProcessors
            boolean reiterate = true;
            while(reiterate) {
                reiterate = false;
				//Find all classes that implement the BeanDefinitionRegistryPostProcessor interface
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                String[] var19 = postProcessorNames;
                var10 = postProcessorNames.length;

                for(int var26 = 0; var26 < var10; ++var26) {
                    String ppName = var19[var26];
					//Skip already executed
                    if (!processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        reiterate = true;
                    }
                }

                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
				//6. Traverse currentRegistryProcessors and execute the postProcessBeanDefinitionRegistry method
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
            }
			//7. Call the postProcessBeanFactory method of all beandefinitionregistrypostprocessors
            invokeBeanFactoryPostProcessors((Collection)registryProcessors, (ConfigurableListableBeanFactory)beanFactory);
            //8. finally, calling the postProcessBeanFactory method of ordinary BeanFactoryPostProcessor in parameter beanFactoryPostProcessors.
			invokeBeanFactoryPostProcessors((Collection)regularPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
        } else {
            invokeBeanFactoryPostProcessors((Collection)beanFactoryPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
        }

		//Here, the input bean factorypostprocessors and all beandefinitionregistrypostprocessors in the container have been processed
		//Now start processing all beanfactoryprocessors in the container
		//9. Find out all classes that implement beanfactoryprocessor interface
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
		
		//It is used to store the beanfactorypost processor that implements the PriorityOrdered interface
        regularPostProcessors = new ArrayList();
		//The beanName used to store the beanfactoryprocessor that implements the Ordered interface
        registryProcessors = new ArrayList();
		//beanName for storing ordinary beanfactoryprocessor
        currentRegistryProcessors = new ArrayList();
		
        postProcessorNames = postProcessorNames;
        int var20 = postProcessorNames.length;

        String ppName;
        for(var9 = 0; var9 < var20; ++var9) {
            ppName = postProcessorNames[var9];
			//Skip the traversal that has been performed, and add beanfactoryprocessor to the corresponding collection according to different interfaces
            if (!processedBeans.contains(ppName)) {
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    regularPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
                } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    registryProcessors.add(ppName);
                } else {
                    currentRegistryProcessors.add(ppName);
                }
            }
        }
		//10. Call all beanfactorypost processors that implement the PriorityOrdered interface
		//10.1 sorting priorityOrderedPostProcessors
        sortPostProcessors(regularPostProcessors, beanFactory);
		//10.2 traverse priorityOrderedPostProcessors and execute the postProcessBeanFactory method
        invokeBeanFactoryPostProcessors((Collection)regularPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
        
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList();
        Iterator var21 = registryProcessors.iterator();

        while(var21.hasNext()) {
            String postProcessorName = (String)var21.next();
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
		//10.3 sorting orderedPostProcessors
        sortPostProcessors(orderedPostProcessors, beanFactory);
		//10.4 traverse orderedPostProcessors sorting and execute the postProcessBeanFactory method
        invokeBeanFactoryPostProcessors((Collection)orderedPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
		
		// 11. Call all the remaining beanfactoryprocessor
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList();
        Iterator var24 = currentRegistryProcessors.iterator();

        while(var24.hasNext()) {
            ppName = (String)var24.next();
			// 11.1 obtain the bean instance corresponding to postProcessorName, add it to nonOrderedPostProcessors, and prepare for execution
            nonOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }

		// 11.2 traverse nonOrderedPostProcessors and execute the postProcessBeanFactory method
        invokeBeanFactoryPostProcessors((Collection)nonOrderedPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
        // 12. Clear the metadata cache (mergedBeanDefinitions, allBeanNamesByType, singletonBeanNamesByType),
		// Because the postprocessor may have modified the original metadata, for example, replacing placeholders in values
		beanFactory.clearMetadataCache();
    }

From the above source code analysis, we can see that there is a condition in the invokebeanfactoryprocessors method. If the incoming beanFactory is BeanDefinitionRegistry, its main process is as follows:

  1. Traverse the incoming BeanFactoryPostProcessor collection, find and execute the BeanDefinitionRegistryPostProcessor type, and then add it to the collection;
  2. The postorderdefined processor traverses the collection of postorderdefined, and finds all the collection in the container;
  3. Find all BeanDefinitionRegistryPostProcessor sets that implement the Ordered interface in the container, sort and traverse the postprocessor set, and execute the postProcessBeanDefinitionRegistry method of postprocessing;
  4. Find other beandefinitionregistrypostprocessors (without sorting interface) in the container and add them to the collection nonOrderedPostProcessors to sort and traverse the post processor collection and execute the postProcessBeanDefinitionRegistry method of post processing;
  5. After the methods of all current BeanDefinitionRegistryPostProcessor processors have been executed, execute its parent class postProcessBeanFactory method;
  6. Execute the postProcessBeanFactory method of all post processors of non BeanDefinitionRegistryPostProcessor type.

If the incoming beanFactory is not BeanDefinitionRegistry, the main process is as follows:

  1. Traverse the incoming beanfactoryprocessor set and execute the postProcessBeanFactory method of the postprocessor;
  2. In the container (beanFactory.getBeanNamesForType), find all beanfactoryprocessor sets that implement the PriorityOrdered interface, sort, traverse and execute post-processing on the post processor set;
  3. Find all beanfactoryprocessor sets that implement the Ordered interface in the container, sort, traverse and execute post-processing on the post processor set;
  4. Find other beanfactoryprocessors (without sorting interface) in the container and add them to the collection nonOrderedPostProcessors to sort, traverse and execute the post processor collection.
  5. Note: there are several implementations of beanfactory postprocessor in Spring, and each implementation has different functions. You can sort out the source code by yourself, or we can implement beanfactory postprocessor by ourselves.

Although there are a lot of contents in invokebeanfactoryprocessors, it can be found by carefully reading the source code that the whole method is mainly carried out around the two interfaces of BeanDefinitionRegistryPostProcessor and beanfactoryprocessor. Its main functions are as follows:

  1. Process the beanfactoryprocessor in the parameter beanfactoryprocessors (empty by default), that is, execute the postProcessBeanDefinitionRegistry method of the BeanDefinitionRegistryPostProcessor interface;
  2. Process all beandefinitionregistrypostprocessors in the container;
  3. Process all remaining beanfactoryprocessors in the container.

Keywords: Java Spring

Added by sara_kovai on Tue, 08 Mar 2022 13:06:07 +0200