In the previous chapter, we introduced the loading and registration of configuration resources, at which point the Spring container manages all the Bean definition data. Next comes the creation of Bean instances and dependency injection (DI). DI(Dependency Injection) means that the object passively receives the dependent class instead of finding it. In other words, the object does not look for its dependent class from the container. Instead, the container actively injects the dependent class into the object when it instantiates the object.

Looking for the entrance

Bean instance creation and dependency injection are triggered in two cases:

  1. The first call by the usergetBean()Method, the IoC container triggers dependency injection.
  2. whenBeanThe lazy load property of isfalseWhen the container is initialized, dependency injection is automatically triggered. It’s still going to callgetBean()Methods.

As a result,BeanThe entry point for instance creation and dependency injection is heregetBean()Methods. In the last chapter, we talked about whetherClassPathXmlApplicationContextorAnnotationConfigApplicationContextholdDefaultListableBeanFactoryInstance. And theirgetBean()It’s called directlyBeanFactorythegetBean()Methods.DefaultListableBeanFactorythegetBean()It’s the real entrance.getBean(String)In its abstract parent classAbstractBeanFactory, the source code is as follows:

What is actually called isdoGetBean()Methods:

Analyzing the above code, we found five key points:

  1. Get it from the singleton cache firstBeanInstance, if obtained, no object needs to be created.
  2. Create current firstBeanDependent on allBean.
  3. If it is a singleton, the object is created and placed in the cache.
  4. In the case of a prototype, a new object is created on each call.
  5. If it is customscope, the custom is usedscopeTo manage the scope in which objects are created.

Either way, you end up with the createBean() method called.

Start instantiating

AbstractBeanFactorythecreateBean()Finally calledAbstractAutowireCapableBeanFactoryImplementation, the source code is as follows:

The implementation of doCreateBean() consists of four main steps:

  1. createBeanInstance.
  2. If it is a singleton, cache the singleton object and hold references as early as possible to resolve circular dependencies.
  3. fillBeanProperty, where dependency injection occurs.
  4. Initialize theBean, includingafterPropertiesSet()Method and custom initialization methods.

The following steps describe the implementation of creating a Bean instance, populating Bean properties, and initializing the Bean.

createBeanThe instance

createBeanThe instance callscreateBeanInstance()Methods:

In the createBeanInstance() implementation, instantiation is performed in four different cases:

  1. Call the callback method instantiation that created the Bean.
  2. Call factory method instantiation.
  3. Invoke the matching constructor instantiation using the container’s autowire feature
  4. Instantiated using the default no-parameter constructor

The first three methods are simple, simply calling the matched method instantiation. However, the most commonly used default no-parameter constructors need to be instantiated using the appropriate instantiation policy (JDK reflection mechanism or CGLib) in the methodgetInstantiationStrategy().instantiate()Use the corresponding policy to instantiate the object for the concrete implementation class. The source code is as follows:

Finally calledSimpleInstantiationStrategytheinstantiate()Methods:

ifBeanIf no method is overridden (meaning not subclassed), it is instantiated using the JDK’s reflection mechanism, otherwise, it is instantiated using CGLib.instantiateWithMethodInjection()The method callSimpleInstantiationStrategyA subclass ofCGLibSubclassingInstantiationStrategyUsing CGLib to instantiate, the source code is as follows:

CGLib is a common class library for bytecode generators. It provides a series of apis to generate and transform Java bytecode. As we all know from studying dynamic proxy in the JDK, dynamic proxy in the JDK can only be used for interfaces, and if a class does not implement any interfaces, CGLib is the only way to dynamically proxy it.

fillBeanattribute

When creating aBeanOnce the instance is complete, the next step is to fillBeanProperty, often referred to as the dependency injection phase.populateBean()The source code is as follows:

Before formal dependency injection, it first callsBeanInstantiate the postprocessor to perform the instantiated postlogic. For automatically injected properties, the injection can be done by name or type, respectively. Finally, call unifiedapplyPropertyValues()Method to complete attribute assignment.

There are two ways to inject attributes:

  1. When the attribute value type does not need to be cast, the attribute value does not need to be resolved and is directly prepared for dependency injection.
  2. When a property value needs to be cast, such as a reference to another object, the property value first needs to be resolved and then dependency injection is performed on the parsed property value.

On the interpretation of the attribute values are in BeanDefinitionValueResolver resolveValueIfNecessary in class () method, the dependency injection on the value of an attribute by bw. SetPropertyValues () method, Before we look at dependency injection of attribute values, let’s look at the process of parsing attribute values.

When the container is doing dependency injection on a property, it finds that the property value needs to be cast if it is another value in the containerBeanFor instance object reference, the container first needs to resolve the referenced object according to the value of the attribute, and then the reference object can be injected into the target instance object attribute, the attribute is resolved byresolveValueIfNecessary()Method, its source code is as follows:

In the above implementation, Spring resolves attributes such as reference types, inner classes, and collection types, depending on the situation. Once parsing is complete, dependency injection is ready. The process of dependency injection is to set the Bean object instance to the Bean object properties that it depends on. Dependency injection is essentially assigning values to attributes, which is expanded here.

Initialize theBean

I’ve already created thatBeanExample and also completed the attribute injection, the next step is to call the initialization method to do some initialization operations, source code as follows:

The initialization method consists of four parts:

  1. callAwaremethods. Spring has a lot to offerAwareInterface, ifBeanTo achieve theAwareInterface, then some will be called during the initialization phaseAwareMethods. The things that will be called here areBeanNameAware,BeanClassLoaderAwareandBeanFactoryAwareMethods.
  2. callBeanPost-processor, do some processing before initialization. Spring has a lot to offerBeanPostProcessorInterface, used inBeanCustom logic is woven into each lifecycle of the This is going to execute the applicationBeanPostProcessorthepostProcessBeforeInitialization()Methods.
  3. Call the initialization method. includingInitializingBeanOf the interfaceafterPropertiesSet()And custom initialization methods.
  4. callBeanThe post-processor, after initialization, does some processing. This is going to execute the applicationBeanPostProcessorthepostProcessAfterInitialization()Methods.

conclusion

The Spring container starts in two major phases. The first phase is the loading and registration of configuration resources, and the second phase is the instantiation, dependency injection, and initialization of beans. In the first phase, the focus is on BeanDefinition, which is eventually parsed into a BeanDefinition object, whether configured in XML or annotations, and registered in the container. After the first phase is complete, the container has the configuration information for all the beans. The second phase relies on the BeanDefinition handled in the first phase, which implements Bean instantiation, dependency injection, and initialization. In addition, Spring provides a variety of callback inlets throughout the container startup process, allowing users to inject custom processing logic at various stages of execution.

It is not easy to be original. If you think you have written a good article, click 👍 to encourage you

Welcome to my open source project: a lightweight HTTP invocation framework for SpringBoot