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.