Spring starts invokebeanfactoryprocessors method explanation

summary

This method (invokebeanfactoryprocessors) will instantiate and call all beanfactoryprocessors (including its subclass BeanDefinitionRegistryPostProcessor).

The beanfactoryprocessor interface is an extension point exposed when Spring initializes BeanFactory. The Spring IoC container allows beanfactoryprocessor to read the bean definition and modify it before the container instantiates any bean.

BeanDefinitionRegistryPostProcessor inherits from beanfactoryprocessor and has a higher priority than beanfactoryprocessor. It is mainly used to register other bean definitions before the normal beanfactoryprocessor detection starts. In particular, you can register some conventional beanfactory postprocessors through BeanDefinitionRegistryPostProcessor, because all conventional beanfactory postprocessors have not been processed at this time.

Actual combat in the project

Example of BeanDefinitionRegistryPostProcessor initializing Bean

// We want to dynamically generate our Bean objects according to the configuration file
public class MultiOssScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
	@Setter
	private MultiOssProperties multiOssProperties;

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
		String beanSuffixName = StringUtils.capitalize(OssConstants.BEAN_SUFFIX_NAME);
		multiOssProperties.getClients().forEach((productCode, ossProperties) -> {
			AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(OssClient.class,
					() -> OssClientUtils.buildOssClient(ossProperties))
					.getRawBeanDefinition();
			beanDefinition.setInitMethodName("init");
			beanDefinition.setDestroyMethodName("shutDown");
			beanDefinitionRegistry.registerBeanDefinition(productCode + beanSuffixName, beanDefinition);
		});
	}
}

do something during beanfactoryprocessor initialization

public class KeplerBeanFactoryPostInitializer implements BeanFactoryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		Map<String, AviatorFunction> aviatorFunctionMap = beanFactory.getBeansOfType(AviatorFunction.class);
		if (aviatorFunctionMap.size() > 0) {
			log.info("Initialize customization RuleLoader...");
			aviatorFunctionMap.forEach((k, v) -> {
				log.info("load Rule:{}", k);
				AviatorEvaluator.addFunction(v);
			});
		}
		RuleLoader.initRule();
	}
}

Follow up source code

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	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(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
	}
}
getBeanFactoryPostProcessors
/**
	 * Return the list of BeanFactoryPostProcessors that will get applied
	 * to the internal BeanFactory.
	 */
	public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
		return this.beanFactoryPostProcessors;
	}

Here, getbeanfactoryprocessors () will get the beanfactoryprocessor registered in the current application context. By default, this.beanfactoryprocessors returns null.

public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {

	/**
	 * Initialize the given application context.
	 * @param applicationContext the application to configure
	 */
	void initialize(C applicationContext);
}
invokeBeanFactoryPostProcessors
public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
 
    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    Set<String> processedBeans = new HashSet<String>();
 
    // 1. Judge whether beanFactory is BeanDefinitionRegistry, and beanFactory is DefaultListableBeanFactory,
    // The DefaultListableBeanFactory implements the BeanDefinitionRegistry interface, so this is true
    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        // It is used to store ordinary beanfactoryprocessor
        List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
        // Used to store BeanDefinitionRegistryPostProcessor
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();
 
        // 2. First process the bean factorypostprocessors in the parameter
        // Traverse all beanfactory postprocessors to distinguish BeanDefinitionRegistryPostProcessor from ordinary beanfactory postprocessor
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                // 2.1 if it is BeanDefinitionRegistryPostProcessor
                BeanDefinitionRegistryPostProcessor registryProcessor =
                        (BeanDefinitionRegistryPostProcessor) postProcessor;
                // 2.1.1 directly execute the postProcessBeanDefinitionRegistry method of BeanDefinitionRegistryPostProcessor interface
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                // 2.1.2 add to registryprocessors (used to finally execute the postProcessBeanFactory method)
                registryProcessors.add(registryProcessor);
            } else {
                // 2.2 otherwise, it is just an ordinary beanfactoryprocessor
                // 2.2.1 add to regularpostprocessors (used to finally execute the postProcessBeanFactory method)
                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!
        // Separate between BeanDefinitionRegistryPostProcessors that implement
        // PriorityOrdered, Ordered, and the rest.
        // Used to save the BeanDefinitionRegistryPostProcessor executed this time
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
 
        // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
        // 3. Call all BeanDefinitionRegistryPostProcessor implementation classes that implement the PriorityOrdered interface
        // 3.1 find the beanName of all beans that implement the BeanDefinitionRegistryPostProcessor interface
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        // 3.2 traversing postProcessorNames
        for (String ppName : postProcessorNames) {
            // 3.3 verify whether the PriorityOrdered interface is implemented
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                // 3.4 get the bean instance corresponding to ppName and add it to currentRegistryProcessors,
                // beanFactory.getBean: the getBean method here will trigger the creation of the bean object corresponding to ppName, which will not be deeply resolved at present
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                // 3.5 add processedBeans to be executed to avoid subsequent repeated execution
                processedBeans.add(ppName);
            }
        }
        // 3.6 sorting (sorting according to whether PriorityOrdered, Ordered interface and order value are implemented)
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        // 3.7 add to registryprocessors (used to finally execute the postProcessBeanFactory method)
        registryProcessors.addAll(currentRegistryProcessors);
        // 3.8 traverse currentRegistryProcessors and execute the postProcessBeanDefinitionRegistry method
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        // 3.9 after execution, clear currentRegistryProcessors
        currentRegistryProcessors.clear();
 
        // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
        // 4. Call all BeanDefinitionRegistryPostProcessor implementation classes that implement the Ordered interface (the process is basically the same as step 3 above)
        // 4.1 find out all classes that implement the BeanDefinitionRegistryPostProcessor interface. Repeat the search here because the BeanDefinitionRegistryPostProcessor above is executed,
        // Other BeanDefinitionRegistryPostProcessor may be added, so it needs to be searched again
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            // Verify whether the Ordered interface is implemented and has not been executed
            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 traverse currentRegistryProcessors and execute the postProcessBeanDefinitionRegistry method
        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;
            // 5.1 find out all classes that implement the BeanDefinitionRegistryPostProcessor interface
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                // 5.2 skip already executed
                if (!processedBeans.contains(ppName)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                    // 5.3 if a BeanDefinitionRegistryPostProcessor is executed, a new BeanDefinitionRegistryPostProcessor may be generated,
                    // Therefore, the value of repeat is set to true, which means that it needs to be searched again
                    reiterate = true;
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            // 5.4 traverse currentRegistryProcessors and execute the postProcessBeanDefinitionRegistry method
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
        }
 
        // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
        // 6. Call the postProcessBeanFactory method of all beandefinitionregistrypostprocessors (BeanDefinitionRegistryPostProcessor inherits from beanfactoryprocessor)
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        // 7. finally, calling the postProcessBeanFactory method of ordinary BeanFactoryPostProcessor in parameter beanFactoryPostProcessors.
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    } else {
        // Invoke factory processors registered with the context instance.
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }
 
    // At this point, the input bean factorypostprocessors and all beandefinitionregistrypostprocessors in the container have been processed,
    // Now start processing all beanfactoryprocessors in the container
 
    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let the bean factory post-processors apply to them!
    // 8. Find out all classes that implement beanfactoryprocessor interface
    String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
 
    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    // It is used to store the beanfactorypost processor that implements the PriorityOrdered interface
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    // The beanName used to store the beanfactoryprocessor that implements the Ordered interface
    List<String> orderedPostProcessorNames = new ArrayList<String>();
    // beanName used to store ordinary beanfactoryprocessor
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    // 8.1 traverse the postProcessorNames and distinguish the beanfactory postprocessor according to the implementation of PriorityOrdered, the implementation of Ordered interface and ordinary
    for (String ppName : postProcessorNames) {
        // 8.2 skip already executed
        if (processedBeans.contains(ppName)) {
            // skip - already processed in first phase above
        } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // 8.3 add a beanfactorypost processor that implements the PriorityOrdered interface
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            // 8.4 add the beanName of beanfactoryprocessor that implements the Ordered interface
            orderedPostProcessorNames.add(ppName);
        } else {
            // 8.5 add the beanName of the remaining ordinary beanfactoryprocessor
            nonOrderedPostProcessorNames.add(ppName);
        }
    }
 
    // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    // 9. Call all beanfactorypost processors that implement the PriorityOrdered interface
    // 9.1 sorting priorityOrderedPostProcessors
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    // 9.2 traverse priorityOrderedPostProcessors and execute the postProcessBeanFactory method
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
 
    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    // 10. Call all beanfactoryprocessors that implement the Ordered interface
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    for (String postProcessorName : orderedPostProcessorNames) {
        // 10.1 get the bean instance corresponding to postProcessorName, add it to orderedPostProcessors, and prepare for execution
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    // 10.2 sorting orderedPostProcessors
    sortPostProcessors(orderedPostProcessors, beanFactory);
    // 10.3 traverse orderedPostProcessors and execute the postProcessBeanFactory method
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
 
    // Finally, invoke all other BeanFactoryPostProcessors.
    // 11. Call all the remaining beanfactoryprocessor
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        // 11.1 obtain the bean instance corresponding to postProcessorName, add it to nonOrderedPostProcessors, and prepare for execution
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    // 11.2 traverse nonOrderedPostProcessors and execute the postProcessBeanFactory method
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
 
    // Clear cached merged bean definitions since the post-processors might have
    // modified the original metadata, e.g. replacing placeholders in values...
    // 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();
}
sortPostProcessors
private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {
    Comparator<Object> comparatorToUse = null;
    if (beanFactory instanceof DefaultListableBeanFactory) {
        // 1. Get the set comparator
        comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();
    }
    if (comparatorToUse == null) {
        // 2. If no comparator is set, the default OrderComparator is used
        comparatorToUse = OrderComparator.INSTANCE;
    }
    // 3. Use the comparator to sort the postProcessors
    Collections.sort(postProcessors, comparatorToUse);
}

By default, the comparator is OrderComparator; If annotation config is configured and the value is true, the AnnotationAwareOrderComparator is used. The AnnotationAwareOrderComparator inherits from the OrderComparator and only rewrites some methods. Some codes of the comparator are as follows:

@Override
public int compare(Object o1, Object o2) {
    return doCompare(o1, o2, null);
}
 
private int doCompare(Object o1, Object o2, OrderSourceProvider sourceProvider) {
    // Determine o1 whether the PriorityOrdered interface is implemented
    boolean p1 = (o1 instanceof PriorityOrdered);
    // Determine o2 whether the PriorityOrdered interface is implemented
    boolean p2 = (o2 instanceof PriorityOrdered);
    // 1. If o1 implements the PriorityOrdered interface but o2 does not, o1 is in the front row
    if (p1 && !p2) {
        return -1;
    }
    // 2. If o2 implements the PriorityOrdered interface but o1 does not, o2 comes first
    else if (p2 && !p1) {
        return 1;
    }
 
    // 3. If both o1 and o2 implement (neither implement) the PriorityOrdered interface
    // Direct evaluation instead of Integer.compareTo to avoid unnecessary object creation.
    // Get the order value of o1. If the Ordered interface is not implemented, the value is Ordered.LOWEST_PRECEDENCE
    int i1 = getOrder(o1, sourceProvider);
    // Get the order value of o2. If the Ordered interface is not implemented, the value is Ordered.LOWEST_PRECEDENCE
    int i2 = getOrder(o2, sourceProvider);
    // 4. Sort by order value (the smaller the order value, the higher the priority)
    return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}

summary

The first point: the whole invokebeanfactoryprocessors method revolves around two interfaces, BeanDefinitionRegistryPostProcessor and beanfactoryprocessor. BeanDefinitionRegistryPostProcessor inherits beanfactoryprocessor. BeanDefinitionRegistryPostProcessor is mainly used to register other Bean definitions before normal beanfactory postprocessor detection. To put it simply, BeanDefinitionRegistryPostProcessor has a higher priority and the execution order is before beanfactory postprocessor.

The second point: the entire invokebeanfactoryprocessors method operates on three bean objects:

  • Input parameter beanfactoryprocessors: take the beanfactoryprocessors property value of AbstractApplicationContext class, that is, beanfactoryprocessors added to beanfactoryprocessors before
  • BeanDefinitionRegistryPostProcessor interface implementation class: implements the BeanDefinitionRegistryPostProcessor interface and registers it in the Spring IoC container.
  • General beanfactoryprocessor interface implementation class: implements the beanfactoryprocessor interface and registers it in the Spring IoC container.

Point 3: operating the three bean objects specifically refers to calling their overridden methods. When calling the implementation methods, the following priorities will be followed: two important interfaces for sorting: PriorityOrdered and Ordered. PriorityOrdered inherits Ordered, and PriorityOrdered has a higher priority than Ordered, This is similar to BeanDefinitionRegistryPostProcessor inheriting beanfactoryprocessor. To implement the Ordered interface, you need to override the getOrder method and return an order value for sorting. The range of order value is Integer.MIN_VALUE ~ Integer.MAX_VALUE, the smaller the order value, the higher the priority, Integer.MIN_VALUE has the highest priority, while Integer.MAX_VALUE has the lowest priority.

Point 4: common Java EE related frameworks or middleware often use beanfactory postprocessor for extension, such as Mybatis above. Therefore, understanding the principle of beanfactory postprocessor will be helpful to understand the principles of other middleware in the future.

Reference address

  • https://blog.csdn.net/v123411739/article/details/87741251

If you like my article, you can pay attention to your personal subscription number. Welcome to leave messages and communicate at any time. If you want to join the wechat group for discussion, please add the administrator Jian stack culture - little assistant (lastpass4u), who will pull you into the group.

Posted by mhalloran on Thu, 04 Nov 2021 12:36:00 -0700