This is the seventh day of my participation in the First Challenge 2022. For details: First Challenge 2022.

preface

Yesterday’s article mentioned the Bean loading process and how to obtain beans, today continues to source interpretation. Again, look at the sequence diagram loaded by the Bean and enter the theme. First is the Bean creation, which calls the getObject() method of the ObjectFactory and returns the createBean() method directly inside the method.

@ 1.3.1.1 createBean
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
    RootBeanDefinition mbdToUse = mbd;
    //@1.3.1.1 locks the class based on the class attribute setClass<? > resolvedClass = resolveBeanClass(mbd, beanName);if(resolvedClass ! =null&&! mbd.hasBeanClass() && mbd.getBeanClassName() ! =null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }
    // TODO Prepare method overrides. Validate and prepare the override method
    try {
        / / @ 1.3.1.2
        mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {}
    try {
        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        //@1.3.1.3 returns a proxy instead of the real instance
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if(bean ! =null) {
            returnbean; }}catch (Throwable ex) {}
    try {
        //@1.3.1.4 Highlight create Bean
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isDebugEnabled()) {
            logger.debug("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {}
    catch (Throwable ex) {}
}
Copy the code

To summarize the function of this method:

1. Interpret the class according to the class attribute or beanName in RootBeanDefinition
2. Handle the override attribute
3. Post-processor before initialization (also AOP’s core implementation)
4. Create the bean’s concrete logic
@ 1.3.1.2 handle override properties mbdToUse. PrepareMethodOverrides ()

Ps: Here attention ha, version is not the same, there are some methods are transformed, so sometimes encountered errors or difficult to solve the problem, you can think about whether the version of the problem, I personally because of the version of the problem also eat a lot of losses.

As we can see from the code above, get the list of overloaded methods of the class and iterate through them, one by one. Specifically, the properties are lookup-method and replace-method. The configurations resolved in this step will be stored in the methodOverrides property of beanDefinition to prepare for instantiation later. Excerpted from Deep Analysis of Spring source Code

@1.3.1.3 Pre-processing before instantiation, Pay attention to two important points applyBeanPostProcessorsBeforeInstantiation (preposition) and applyBeanPostProcessorsAfterInitialization (rear)

Method is intended to short-circuit the Bean before calling doCreateBean(). If the post-processing succeeds, the Bean is returned as no longer executing, which is AOP’s core logic. When it comes to AOP, everyone knows that it is nothing more than dependency injection, which implements hot-plug functions such as logging, permissions and so on, but in fact AOP can do a lot of things. If time is sufficient, then WE can also interpret the source code of AOP. Without further ado, we continue to look at the source code.

@1.3.1.4 doCreateBean() bean creation logic

In Spring’s source code, the do method does the real work (as anyone who knows and uses servlets to write code should know). Of course, the bean creation is done in the doCreateBean() method. Here is the source code parsing. General process combing:

1. The cache of a singleton needs to be cleared
2. Create an instance of the Bean and convert the BeanDefinition to the wrapper class BeanWrapper
3. The post-processor modifies the definition of the merged bean: The processing of the bean after the merge, which the Autowired annotation formally implements such things as pre-parsing of the type
4. Dependency handling
5. Attribute population
6. Cyclic dependency checking
Register to DisposableBean(execute destroy() when bean is destroyed)
8. Complete the creation and return

Because this method does too many things and is very complex, I will only pick out the key points to analyze.

Create an instance of the Bean, class createBeanInstance

General process combing:

1. Determine if there is a factory method, and if so, create the bean directly using the factory method
2. No factory method is created using constructors, because a Class may have multiple constructors, so it is necessary to distinguish the specific constructor based on the parameters.
3. Use the default constructor if neither the factory nor the parameterized constructor exists.

Move on to the next step

@1.3.1.4.2 Handling of loop dependencies

Spring does this by adding ObjectFactory to singletonFactories before Bean instantiation is complete. @1.1 shows ObjectFactory is the factory used to create objects. When the object is instantiated, it will determine whether the dependent object has been created by checking whether the ObjectFactory of the dependent object is in the singleton cache. If not, it will create the dependent object first, and then put the ObjectFactory into the singleton cache. If there is a cyclic dependency, it needs to be exposed in advance so that the dependent party can find and instantiate it normally.

@1.3.1.4.2 Property injection, method populateBean(), not to be described here

General process combing:

1. Call InstantiationAwareBeanPostProcessor processor postProcessAfterInstantiation method, to determine whether a control program to continue attributes
2. According to the injection type (byName/byType), extract the dependent bean and store it in PropertyValues. However, most of them are in the form of annotations, neither of these methods will be implemented
3. Determine whether BeanPostProcessor and dependency checks are required. This step is to start injecting beans
4. Fill all parsed properties in PropertyValues into BeanWrapper.
In this method, properties are populated based on the different injection types, processed by the post-call handler, and eventually applied to the bean. Way too much content, also not in detail, mainly under the said circular dependencies, in step 2 according to the properties of injection time, assuming A need to inject B, happen to also need to inject A, B both autowireByName/autowireByType postProcessPropertyVal at this moment The UES eventually calls the getBean method to create Bean B. In this case, getSingleton() is used to get the ObjectFactory that A put into the cache at @1.3.1.4.2, and getObject is used to get the bean of A, which solves the problem of loop dependence.
Initialize the bean

The general process of this method is that beans are divided into two types: one is FactoryBean, and the other is ordinary Bean. Ordinary Bean will return directly, and FactoryBean will delegate to getObjectFromFactoryBean to fetch. Spring has BeanFactory and FacotryBean.

1. The implementation class of the BeanFactory interface is a container, which is also the basic specification of IOC.
2. What beans are returned by the implementation class of the FacotryBean interface is determined by the implementation class’s getObject() return.

Conclusion: The previous two articles combined sequence diagrams and source code to help you gain a deeper understanding of Spring’s Bean loading process. At the same time have to sigh Spring source code to write good, the logical breakdown is really too strong, the author every once in a while to see a small module of the source will always have some new understanding, but personal ability is temporarily limited, if there is anything wrong with the place hope to add corrective! Thank you! The next series is amway, a handy open source software series.