This is the 13th day of my participation in the August More Text Challenge. For details, see:August is more challenging

4. Read from the definition configuration class MainConfig

Registration configuration class, the entry is naturally here

public AnnotationConfigApplicationContext(Class<? >... (componentClasses) {// Enter the constructor and call its constructor this(); // Call the superclass constructor this() before calling its own constructor; // Register (componentClasses); // The ioc container shua new interface -- very important refresh(); }Copy the code

 

Trace in to doRegisterBean(…) methods

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @ Nullable BeanDefinitionCustomizer customizers []) {/ / will be into the configuration class beanClass construct objects into AnnotatedGenericBeanDefinition refs AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } abd.setInstanceSupplier(supplier); / / read the configuration class metadata ScopeMetadata ScopeMetadata = this. ScopeMetadataResolver. ResolveScopeMetadata (abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = (name ! = null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); / / handle the main class general custom annotation AnnotationConfigUtils. ProcessCommonDefinitionAnnotations (abd); if (qualifiers ! = null) { for (Class<? extends Annotation> qualifier : qualifiers) { if (Primary.class == qualifier) { abd.setPrimary(true); } else if (Lazy.class == qualifier) { abd.setLazyInit(true); } else { abd.addQualifier(new AutowireCandidateQualifier(qualifier)); } } } if (customizers ! = null) { for (BeanDefinitionCustomizer customizer : customizers) { customizer.customize(abd); } // Parse the mainconfig. Java configuration class. DefinitionHolder = new definitionHolder (abd, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this .registry); }Copy the code

 

Key is red, the other can skip, because our configuration is simple, direct see BeanDefinitionReaderUtils. RegisterBeanDefinition (definitionHolder, enclosing the registry).

We find registry. RegisterBeanDefinition (beanName, definitionHolder getBeanDefinition ()); Method, into the DefaultListableBeanFactory check method, this method before we have call once

Is at the time of registration ConfigurationClassPostProcessor, we need to be resolved as BeanDefinition put BeanDefinitionMap, here is the same, Parsed our configuration class MainConfig into BeanDefinition and put it into BeanDefinitionMap.

 

Where does this code fit into the framework? Parsed MainConfig to BeanDefinition in BeanDefinitionMap

The above two steps, one is to configure ConfigurationClassPostProcessor class post processor, namely parsing configuration utility class, parsed into BeanDefinition into BeanDefinitionMap

Another is to load our target configuration class MainConfig into memory and assemble BeanDefinition into BeanDefinitionMap.

 

So at this point, we’ve done two steps.

Step 1: prepare tools ConfigurationClassPostProcessor

Step 2: Prepare the configuration class MainConfig.

 

Next, it’s time to use the utility class to resolve the configuration class MainConfig

5. Call the bean factory rear processor invokeBeanFactoryPostProcessors (the beanFactory);

public AnnotationConfigApplicationContext(Class<? >... (componentClasses) {// Enter the constructor and call its constructor this(); // Call the superclass constructor this() before calling its own constructor; // Register (componentClasses); // Refresh the ioc container interface -- very important refresh(); }Copy the code

The refresh () there are a lot of steps, we focus on to see invokeBeanFactoryPostProcessors (the beanFactory);

 

/** * refresh is the core method of Spring, which includes the whole process of Spring IOC, including the whole process of Spring loading beans to destroy beans * * @throws BeansException * @Throws IllegalStateException */ @Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 1. Prepare to refresh the context prepareRefresh(); // Tell the subclass to refresh the internal bean factory. //2. Get bean factory tell subclass is initialized, different factory implementation ConfigurableListableBeanFactory the beanFactory = obtainFreshBeanFactory (); // Prepare the bean factory for use in this context. //3. The bean factory is populated with the prepareBeanFactory(beanFactory) property; try { // Allows post-processing of the bean factory in context subclasses. // 4. Leave a subclass to implement the interface postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. /* * * We used to read a lot of Genesis's PostProcessor in the Reader. So many genesis PostProcessor, only a PostProcessor * spring BeanFactoryPostProcessor is realized. The class is ConfigurationClassPostProcessor * had put ConfigurationClassPostProcessor in front to BeanDefinitionMap, * corresponding BeanDefinitionName internalConfigurationAnnotationProcessor is * * * * / invokeBeanFactoryPostProcessors(beanFactory); / / Register bean processors that intercept bean creation. / / registered beans rear processor registerBeanPostProcessors (the beanFactory); // Initialize message source for this context. // Initialize the internationalized resource handler initMessageSource(); / / Initialize event multicaster for this context, / / create the event more players initApplicationEventMulticaster (); // Initialize other special beans in specific context subclasses. // Initialize other special beans in specific context subclasses. Spring Boot also starts from this method onRefresh(); // Check for listener beans and register them. // registerListeners(); // Instantiate all remaining (non-lair-init) singletons. // Instantiate all remaining (non-lair-init) singletons. /** * To produce bean * / finishBeanFactoryInitialization (the beanFactory); Corresponding (); // Corresponding (); }... }Copy the code

 

invokeBeanFactoryPostProcessors(beanFactory); See the name, call the Bean factory post processor, analyzed above, initialization initialize the many spring native post processor, so many post processor, in fact, only a rear processor implements the spring BeanFactoryPostProcessor, It is ConfigurationClassPostProcessor, remember the chart above, to be taken, to look again.

 

Call here, native processor will only call ConfigurationClassPostProcessor

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { /** * Get the objects that hold the BeanFactoryPostProcessor in two places and pass them in for the next call * 1. The current bean plant * 2. And we call addBeanFacoryPostProcessor custom spring BeanFactoryPostProcessor * * parameters: GetBeanFactoryPostProcessors () and a rear processor's List of the factory, this time the List is empty * getBeanFactoryPostProcessors () in the value of the how? * by custom main method invokes the context. The addBeanFactoryPostProcessor (...). ; Public static void main(String[] args) { Reading a configuration from the AnnotationConfigApplicationContext class * AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class); * context.addBeanFactoryPostProcessor(...) ; * Car car = (Car) context.getBean("car"); * System.out.println(car.getName()); * context.close(); * } */ 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())); }... }Copy the code

 

This is where the bean factory’s post-processor is called. Look at the comments above. They are very clear.

In the call PostProcessorRegistrationDelegate. InvokeBeanFactoryPostProcessors (the beanFactory, getBeanFactoryPostProcessors ()); Called when the getBeanFactoryPostProcessors () method.

public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() { return this .beanFactoryPostProcessors; }Copy the code
GetBeanFactoryPostProcessors () returns a post processor of the List of the factory, this time the List is empty getBeanFactoryPostProcessors () in the value of the how? Through custom main method invokes the context. The addBeanFactoryPostProcessor (...). ; To add. That is through the main method manually add spring beanFactoryPostProcessor. As shown below.Copy the code

Public static void main(String[] args) { Reading a configuration from the AnnotationConfigApplicationContext class AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class); context.addBeanFactoryPostProcessor(...) ; Car car = (Car) context.getBean("car"); System.out.println(car.getName()); context.close(); }Copy the code

 

Now here’s the big deal. PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); Method implementation consists of two steps:

Step 1: call all realized BeanDefinitionRegistryPostProcessor bean definition of interface. (BeanDefinitionRegistryPostProcessor post processor with a registered function) the second step: Calls the rear processor of the BeanFactoryPostProcessor Bean factoryCopy the code

Step 1: call all realized BeanDefinitionRegistryPostProcessor bean definition of interfaces.

Take a look at how the source code is defined. Focus on the code comments, each part of the function is clearly marked, the comments are written in detail

 

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

        /**
         * 首先,调用BeanDefinitionRegistryPostProcessors的后置处理器
         * 定义已处理的后置处理器
         */
        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set<String> processedBeans = new HashSet<>();

        /**
         * 这里一共分为两大步:
         * 第一步: 调用所有实现了 BeanDefinitionRegistryPostProcessor 接口的bean定义. (BeanDefinitionRegistryPostProcessor带注册功能的后置处理器)
         * 第二步: 调用BeanFactoryPostProcessor Bean工厂的后置处理器
         */

        /**********************第一步: 调用所有实现了BeanDefinitionRegistryPostProcessor接口的bean定义  begin****************************/
        // 判断beanFactory是否实现了BeanDefinitionRegistry, 实现了该结构就有注册和获取Bean定义的能力
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                }
                else {
                    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.
            /**
             * 这是一个集合, 存马上即将要被调用的BeanDefinitionRegistryPostProcessor
             */
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
             // 第一步, 调用实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors // 在所有创世纪的后置处理器中, 只有 internalConfigurationAnnotationProcessor 实现了 BeanDefinitionRegistryPostProcessors 和 PriorityOrdered
            // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                // 判断beanFactory是否实现了PriorityOrdered接口. 如果实现了,是最优先调用.
                // 在整个加载过程中,会调用四次BeanDefinitionRegistryPostProcessor, 而实现了PriorityOrdered的接口最先调用
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    // 调用beanFactory.getBean实例化创世界的类ppName
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            /**
             * 第一次调用BeanDefinitionRegistryPostProcessors
             * 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor
             * 用于进行bean定义的加载 比如我们的包扫描 @import 等
             */ invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); // 处理完了,清空currentRegistryProcessors
            currentRegistryProcessors.clear();


             // 第二步: 调用实现 Ordered 的 BeanDefinitionRegistryPostProcessors。 // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                // 这时实现了PriorityOrdered.class的postProcessor就不会再被加载进来了, 因为processedBeans.contains(ppName) == true
                if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    // 将其放入到currentRegistryProcessors, 马上就要被调用
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }

            // 对所有的处理器进行排序. 调用了Ordered的方法, 会返回排序(一个数字), 然后根据数字排序即可
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);

            /**
             * 第二次调用BeanDefinitionRegistryPostProcessors
             * 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor
             * 用于进行bean定义的加载 比如我们的包扫描 @import 等
             */ invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); 
            currentRegistryProcessors.clear();


             // 第三步. 调用没有实现任何优先级接口的 BeanDefinitionRegistryPostProcessor // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
            boolean reiterate = true;
            while (reiterate) {
                reiterate = false;
                // 获取
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                for (String ppName : postProcessorNames) {
                    // 已处理过的postProcessor不再处理
                    if (!processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        reiterate = true;
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                /**
                 * 第三次调用BeanDefinitionRegistryPostProcessors
                 * 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor
                 * 用于进行bean定义的加载 比如我们的包扫描 @import 等
                 */ invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); 
                currentRegistryProcessors.clear();
            }

            // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
            /*
             * 第四步:调用bean工厂的后置处理器
             * registryProcessors: 带有注册功能的bean工厂的后置处理器
             * regularPostProcessors: 不带注册功能的bean工厂的后置处理器
             */ invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }

        else {
            /*
             * 如果当前的beanFactory没有实现BeanDefinitionRegistry 说明没有注册Bean定义的能力
             * 那么就直接调用 BeanDefinitionRegistryPostProcessor.postProcessBeanFactory方法
             */

            // Invoke factory processors registered with the context instance.
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }

        /**********************第一步: 调用所有实现了BeanDefinitionRegistryPostProcessor接口的bean定义  end****************************/

        /**********************第二步: 调用BeanFactoryPostProcessor Bean工厂的后置处理器  begin****************************/

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        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);

        // 第二, 调用实现了Ordered排序的后置处理器
        // 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);

        // 最后, 调用没有实现任何排序接口的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);

        /**********************第二步: 调用BeanFactoryPostProcessor Bean工厂的后置处理器  end****************************/
        // 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

 

 

 

 

Let’s analyze what is shown in the figure above.

1. Compare the source code and the figure above, let’s see the first call

/ / for the first time, call for PriorityOrdered BeanDefinitionRegistryPostProcessors / / in all genesis post processor, Only realized internalConfigurationAnnotationProcessor BeanDefinitionRegistryPostProcessors and PriorityOrdered / / First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); For (String ppName: postProcessorNames) {// Check whether beanFactory implements the PriorityOrdered interface. If implemented, it is the first call. / / in the whole loading process, is called four BeanDefinitionRegistryPostProcessor, An interface that implements PriorityOrdered calls if (beanFactory.istypematch (ppName, PriorityOrdered. Class)) {// Call beanFactory.getBean to instantiate the world class ppName currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); Call BeanDefinitionRegistryPostProcessors * / * * * for the first time Here is a typical BeanDefinitionRegistryPostProcessors ConfigurationClassPostProcessor * for bean definitions of load Such as our package scanning @ import * / invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); / / finished processing, empty currentRegistryProcessors currentRegistryProcessors. The clear ();Copy the code

 

First, to get all the post processor, has realized the BeanDefinitionRegistryPostProcessor We have done above matting, only rear ConfigurationClassPostProcessor realized BeanDefinitionRegistryPostProcessor processor

So here postProcessorNames filter out only one, is ConfigurationClassPostProcessor, next, determine whether the class implements the PriorityOrdered prioritization interface, if implemented, Then into the currentRegistryProcessors, will call later.

Next, execute invokeBeanDefinitionRegistryPostProcessors

This is the first call BeanDefinitionRegistryPostProcessors

 

2. The second callBeanDefinitionRegistryPostProcessors

The second step: / / calls to implement BeanDefinitionRegistryPostProcessors Ordered. // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : PostProcessorNames) {// The postProcessor that implements PriorityOrdered. Class will no longer be loaded, Processedbeans. contains(ppName) == true if (! ProcessedBeans. The contains (ppName) &&. The beanFactory isTypeMatch (ppName, Ordered. Class)) {/ / puts it into the currentRegistryProcessors, Is going to be called currentRegistryProcessors. Add (the beanFactory) getBean (ppName, BeanDefinitionRegistryPostProcessor. Class)); processedBeans.add(ppName); }} // Sort all processors. Calls to the method of Ordered will return sort (a number), then according to the digital sorting sortPostProcessors (currentRegistryProcessors, the beanFactory); registryProcessors.addAll(currentRegistryProcessors); Call BeanDefinitionRegistryPostProcessors * / * * * for the second time Here is a typical BeanDefinitionRegistryPostProcessors ConfigurationClassPostProcessor * for bean definitions of load Such as our package scanning @ import * / invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear();Copy the code

 

When the call the second time, still is to get all the implementation of the rear BeanDefinitionRegistryPostProcessor interface processor, and the processor does not implement a PriorityOrdered is not been above the call. The Ordered interface is implemented

This category is added to the currentRegistryProcessors collection, and then call invokeBeanDefinitionRegistryPostProcessors processing

This is the second time call BeanDefinitionRegistryPostProcessor

3. The third call BeanDefinitionRegistryPostProcessor

/ / the third step. Call don't implement any interface priority BeanDefinitionRegistryPostProcessor / / Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. boolean reiterate = true; while (reiterate) { reiterate = false; / / get postProcessorNames = the beanFactory. GetBeanNamesForType (BeanDefinitionRegistryPostProcessor. Class, true, false); For (String ppName: postProcessorNames) {// Processed postProcessor no longer processes if (! processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); Call BeanDefinitionRegistryPostProcessors * / * * * for the third time Here is a typical BeanDefinitionRegistryPostProcessors ConfigurationClassPostProcessor * for bean definitions of load Such as our package scanning @ import * / invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); }Copy the code

 

The third call is to a post-processor that has not implemented any sort interface. And put it in to the currentRegistryProcessors, then execute invokeBeanDefinitionRegistryPostProcessors

 

 

4. The fourth call

// Now, Invoke the postProcessBeanFactory callback of all processors handled so far. /* * RegularPostProcessors with registered bean factories Post processor for bean factories without registration */ // Call BeanDefinitionRegistryPostProcessor postProcessBeanFactory method - why is call BeanDefinitionRegistryPostProcessor? Because / / ConfigurationClassPostProcessor BeanDefinitionRegistryPostProcessor and BeanFactoryPostProcessors is realized invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); / / call spring BeanFactoryPostProcessor own (no) ConfigurationClassPostProcessor invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);Copy the code

 

ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor and BeanFactoryPostProcessors at the same time, Call is invokeBeanFactoryPostProcessors

 

Four calls were made

Summary: The priority processing is the post-processor that implements PriorityOrdered, then the call is made to the post-processor that implements the Order interface, and finally the call is made to the post-processor that does not implement any sort method. Finally, the factory class method is called.

 

Let’s detailed analysis invokeBeanFactoryPostProcessors (registryProcessors, the beanFactory);

5. Ask questions: Check to see if you have understood the four steps above

 

1. Which steps ConfigurationClassPostProcessor will call 1234? Because ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor and spring BeanFactoryPostProcessor PriorityOrdered, So 1,4, 2. Call 1234 if they defined a MyBeanFactoryPostProcessor that steps? package com.lxl.www.iocbeanlifecicle; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.stereotype.Component; @Component public class MyBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } } Because MyBeanFactoryPostProcessor is custom, don't implement any PriorityOrdered or Order, therefore, will be called three or fourCopy the code

2. Detailed study the fourth step, invokeBeanFactoryPostProcessors (registryProcessors, the beanFactory); The logic.

Let’s make a break point at this step, and then follow the break point and click in

 

 

This is registryProcessors only inside a rear processor, is ConfigurationClassPostProcessor.

And then into the ConfigurationClassPostProcessor. PostProcessBeanFactory (ConfigurableListableBeanFactory the beanFactory) method

@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { int factoryId = System.identityHashCode(beanFactory); if (this.factoriesPostProcessed.contains(factoryId)) { throw new IllegalStateException( "postProcessBeanFactory already called on this post-processor against " + beanFactory); } this.factoriesPostProcessed.add(factoryId); if (! this.registriesPostProcessed.contains(factoryId)) { // BeanDefinitionRegistryPostProcessor hook apparently not supported... // Simply call processConfigurationClasses lazily at this point then. processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory); } / / using additional proxy configuration class, because @ Bean method when the time comes to create the instance of the Bean. EnhanceConfigurationClasses (the beanFactory); beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory)); }Copy the code

 

Here see enhanceConfigurationClasses first (the beanFactory); A method of

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) { Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>(); for (String beanName : beanFactory.getBeanDefinitionNames()) { BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName); Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE); MethodMetadata methodMetadata = null; if (beanDef instanceof AnnotatedBeanDefinition) { methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata(); } if ((configClassAttr ! = null || methodMetadata ! = null) && beanDef instanceof AbstractBeanDefinition) { // Configuration class (full or lite) or a configuration-derived  @Bean method // -> resolve bean class at this point... AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef; if (! abd.hasBeanClass()) { try { abd.resolveBeanClass(this.beanClassLoader); } catch (Throwable ex) { throw new IllegalStateException( "Cannot load configuration class: " + beanDef.getBeanClassName(), ex); }}} /** * Only the full version of the configuration will create cglib agent ** When set to full, we will create a cglib dynamic proxy when we invoke it. * Dynamic proxy ensures that only one bean object is created at a time * * What is the essential difference between adding @configuration and no Configuration? * If @Configuration is added, a Cglib proxy will be created here. If @Configuration is added, a cglib proxy will be created. When the @bean method is called, it first checks to see if the Bean exists in the container. If it does not, it creates, There are used directly. * / if (ConfigurationClassUtils. CONFIGURATION_CLASS_FULL. Equals (configClassAttr)) {if (! (beanDef instanceof AbstractBeanDefinition)) { throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" + beanName + "' since it is not stored in an AbstractBeanDefinition subclass"); } else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) { logger.info("Cannot enhance @Configuration bean definition '" + beanName + "' since its singleton instance has been created too early. The typical cause " + "is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " + "return type: Consider declaring such methods as 'static'." ); } configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef); } } if (configBeanDefs.isEmpty()) { // nothing to enhance -> return immediately return; } ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer(); for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) { AbstractBeanDefinition beanDef = entry.getValue(); // If a @Configuration class gets proxied, always proxy the target class beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE); // Set enhanced subclass of the user-specified bean class Class<? > configClass = beanDef.getBeanClass(); Class<? > enhancedClass = enhancer.enhance(configClass, this.beanClassLoader); if (configClass ! = enhancedClass) { if (logger.isTraceEnabled()) { logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " + "enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName())); } beanDef.setBeanClass(enhancedClass); }}}Copy the code

 

The bold part is to determine whether a CGLIB agent is needed. A CGlib proxy is made if the value of the property configurationClass in beanDefinition is full. Only the full version configuration will create the CGLIb agent

So here are some questions:

Question 1: What is the full version configuration?

We’ve annotated this with @Configuration, and when we load it, we’ll set the configurationClass property to full. When set to full, we create a CGLIb dynamic proxy when we invoke it.

Question 2: Why create dynamic proxies?

Dynamic proxies ensure that only one bean object is created at a time

Question3: So what is the essential difference between @configuration and no Configuration?

When an @Bean is introduced into another Bean using a method in a Configuration class, without the @Configuration annotation, the Bean will be loaded repeatedly. If @Configuration is added, a CGlib proxy is created here. When @Bean is called, it checks for the presence of the Bean in the container, creates it if it does not exist, and uses it if it does.

Question 4: How does “full” come from?

This is in the above call invokeBeanDefinitionRegistryPostProcessors (currentRegistryProcessors, registry); The interface is marked full or Lite

Let’s look at the source code

 

In this step, whether the class is full or Lite is carried out

 

At this point meet the conditions of postProcessor only one, that is ConfigurationClassPostProcessor. Directly below see ConfigurationClassPostProcessor. PostProcessBeanDefinitionRegistry () method

 

Are some conditions in front of the judge, the key see processConfigBeanDefinitions (registry);

 

In this case, the method determines whether the class is full or Lite. So let’s go straight to the code

/** * Check whether the given bean definition is a candidate for a configuration class * (or a nested component class declared within a configuration/component class, * to be auto-registered as well), and mark it accordingly. * @param beanDef the bean definition to check * @param metadataReaderFactory the current factory in use by the caller * @return whether the candidate qualifies as (any kind of) configuration class */ public static boolean checkConfigurationClassCandidate( BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) { String className = beanDef.getBeanClassName(); if (className == null || beanDef.getFactoryMethodName() ! = null) { return false; } AnnotationMetadata metadata; If (beanDef instanceof AnnotatedBeanDefinition &&classname.equals (((AnnotatedBeanDefinition)) beanDef).getMetadata().getClassName())) { // Can reuse the pre-parsed metadata from the given BeanDefinition... metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata(); } else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) { // Check already loaded Class if present... // since we possibly can't even load the class file for this Class. Class<? > beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass(); if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) || BeanPostProcessor.class.isAssignableFrom(beanClass) ||  AopInfrastructureBean.class.isAssignableFrom(beanClass) || EventListenerFactory.class.isAssignableFrom(beanClass)) { return false; } metadata = AnnotationMetadata.introspect(beanClass); } else { try { MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className); metadata = metadataReader.getAnnotationMetadata(); } catch (IOException ex) { if (logger.isDebugEnabled()) { logger.debug("Could not find class file for introspecting configuration annotations: " + className, ex); } return false; } // Check whether the metadata contains the Configuration annotation Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName()); /** * determine if the proxyBeanMethods attribute is true. If true, it is a full class. The proxyBeanMethods configuration class is used to specify whether the @bean annotation method uses a proxy. * The default is true. * if set to false, that is, do not use annotations, each call @ Bean annotation method of access to the object and the IOC container is different, is a new object, so we can set this property to false to improve performance. */ if (config ! = null && ! Boolean.FALSE.equals(config.get("proxyBeanMethods"))) { beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL); } / / determines if @ Component, @ ComponentScan @ Import @ ImportResource @ Bean annotations, / / if these annotations, Configuration_class is a configuration class of type Lite else if (config! = null || isConfigurationCandidate(metadata)) { beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE); } else { return false; } // It's a full or lite configuration candidate... Let's determine the order value, if any. Integer order = getOrder(metadata); if (order ! = null) { beanDef.setAttribute(ORDER_ATTRIBUTE, order); } return true; }Copy the code

 

The above is to get metadata, and then determine whether there is a Configuration annotation in the metadata. If so, return its properties. We determine if proxyBeanMethods is true in its property, and if it is, we set it to full.

If the configuration has one of the @Component, @ComponentScan, @import, @ImportResource, @bean properties, set it to Lite.

 

Question 5: What does the CGLIb dynamic proxy do?

Without looking at the source code, the simple idea is to go to the IOC factory and query the ioc with getBean(“car”) to see if the object exists in ioc. If so, pull it out and do not create another one.

This is the essential difference between @Configuration and other annotations like @Component and @ComponentScan:

When an @Bean is introduced into another Bean using a method in a Configuration class, the Bean will be created repeatedly without the @Configuration annotation

If @Configuration is added, a CGlib proxy is created here. When @Bean is called, it checks for the presence of the Bean in the container, creates it if it does not exist, and uses it if it does.

 

Let’s do an example

Public class Car {private String name; private Tank tank; public String getName() { return name; } public void setName(String name) { this.name = name; } public Tank getTank() { return tank; } public void setTank(Tank tank) { this.tank = tank; } } public class Tank { private String name; Public Tank() {system.out.println (" create a Tank "); } public String getName() { return name; } public void setName(String name) { this.name = name; }}Copy the code

 

This is the base class for the car and tank defined

@Configuration @ComponentScan(basePackages = {"com.lxl.www.iocbeanlifecicle"}) public class MainConfig { @Bean( "car") public Car car() { Car car = new Car(); car.setName("zhangsan"); // The Tank class is called. Tank is injected via the @bean annotation. return car; } @Bean public Tank tank() { return new Tank(); }}Copy the code

 

When the Configuration class uses the @configuration annotation, run the main method

Public class MainStarter {public static void main(String[] args) { Reading a configuration from the AnnotationConfigApplicationContext class AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class); context.scan("package"); //context.addBeanFactoryPostProcessor(); Car car = (Car) context.getBean("car"); Car car2 = (Car) context.getBean("car"); System.out.println(car.getName()); context.close(); }}Copy the code

 

 

When the @Configuration annotation is removed and run again, we see that tanks are created twice

//@Configuration @ComponentScan(basePackages = {"com.lxl.www.iocbeanlifecicle"}) public class MainConfig { @Bean("car") public Car car() { Car car = new Car(); car.setName("zhangsan"); // The Tank class is called. Tank is injected via the @bean annotation. return car; } @Bean public Tank tank() { return new Tank(); }}Copy the code

 

 

(Car) context.getBean(” Car “) is called twice in the main method;

When an object is new, a new one is created each time if it is not fetched from the IOC container.

In the IOC container, there is only one CAR object, but when building the car, tank is called, and there is not necessarily only one copy of tank in the IOC container. Only @Configuration is used, indicating that the CGLIb dynamic proxy needs to be used to find the tank class, ensuring that only one is in the IOC container.