Spring’s basic functionality is IoC and AOP, and our beans are all managed by Spring. So how does Spring IoC generate these beans and do AOP proxy enhancement for the beans you specify? The answer lies in the Spring startup process.

1. Spring IoC

1.1. Bird’s eye view of Spring IoC

For convenience, the annotated version is used here to start the Spring IoC container. The diagram below.

Here to summarize and explain the source code, first clarify the context and then in-depth details will not be lost in the details.

As shown in the figure above, the Spring startup process can be divided into two parts:

  • Step 1: Parse into BeanDefinition: The bean definition information is parsed into a BeanDefinition class. Whether the bean information is defined in XML or annotated with an @bean annotation, it can be converted to a BeanDefinition class using different BeanDefinitionReaders.
    • There are two beandefinitions, RootBeanDefintion and BeanDefinition. RootBeanDefinition, which is system-level, is the six beans that must be loaded to start Spring. BeanDefinition is the Bean we define.
  • Step 2: With reference to the class information defined by BeanDefintion, the BeanFactory generates bean instances and stores them in the cache.
    • The BeanFactoryPostProcessor here is an interceptor that can be modified after BeanDefinition is instantiated and before BeanFactory generates the Bean.
    • BeanFactory uses reflection to instantiate beans according to the BeanDefinition definition. The process of instantiating and initializing beans involves the Bean’s life cycle. The typical problem is the Bean’s cyclic dependency. Then, before the Bean is instantiated, it determines whether the Bean needs to be enhanced and decides which proxy to use to generate the Bean.

The life cycle of a Bean is shown in the following figure. To get an impression, go back to the source section and look at the life cycle of a Bean.

Spring IoC source code

I am currently using the source code of Spring 5.2.6, fully annotated version of Spring development.

The first step is to create a new container.

If you click on it, you can see that there are three main methods, remember these three methods, this(); register(componentClasses); refresh();

1.2.1. This () method

Click on this and see that the inner layer has registered six RootBeanDefinitions, which are system-level BeanDefinitions.

And if you go in there, you can see that registering a BeanDefinition is actually putting it in the BeanFactory cache.

ConfigurationClassPostProcessor class, for example, it is actually a spring BeanFactoryPostProcessor interceptors. Note that the code for this part of the callback is executed in Refresh (). So the following BeanFactoryPostProcessor does not execute yet, but instead executes in Refresh ().

ConfigurationClassPostProcessor he is intercepted configuration class and parse the Bean definition of inside. Its intercepting method checks whether the class is a configuration class.

The configuration class is then parsed.

Parse @import and @bean

1.2.2. Register (componentClasses) method

This method is mainly to register the new AnnotationConfigApplicationContext xxxConfiguration. Class); Of the configuration class passed in.

1.3. The refresh () method

This is the most important method in Spring startup. Click in and have a look. Including invokeBeanFactoryPostProcessor so the name implies is to call the BeanFactory post processor. Rear registerBeanPostProcessors (the beanFactory) registered bean processors, beans rear processor is widely applied in the Spring, he can intercept the processor in the process of bean creation, BeanFactoryPostProcessor is also an interceptor.

Points into this method, finishBeanFactoryInitialization (the beanFactory). It is an important method for initializing beans. Beans can either be defined by @Beans or initialized by factoryBeans.

Click getBean(beanName) to see how a bean is created, which is also the life cycle of the bean.

See the createBean(beanName, MBD, args) method

Bean creation can be done in two steps: Instantiation and Initialization. Instantiation refers to the creation of bean instances, and initialization refers to populating bean instance properties (assigning values to properties). ResolveBeforeInstantiation () method is performed before haven’t bean instantiation. Provide the Bean backend processor with an opportunity to return the proxy, and when you invoke the proxied Bean, you are actually executing the enhanced proxy object.

Click the doCreateBean method. This is the life cycle of the bean, as shown in the diagram at the beginning.

For the bean’s life cycle, you can see that the instance is created in the first step

Click createBeanInstance to see that the bean object is finally created using Java reflection.

Click on the initializeBean method and you can see that it matches the diagram of the life cycle above. Check the Aware interface, go to the pre-processing method of the Bean post-processor, and then call the initialization method.

The life cycle of the bean

This concludes the tutorial on the IoC container function startup process for beans.

Spring AOP

Spring agent enhancements, we saw in the IoC container above part instantiation beans before, actually had to judge whether the bean needs to strengthen, the method for resolveBeforeInstantiation (beanName, mdbToUse), Note that this method is done before the bean is instantiated, that is, it determines whether a proxy needs to be created. If not, the bean will be created; otherwise, a proxy object will be created.

Late at night, to be continued. I’ll write about the AOP section tomorrow.

Let me update it.

Spring Aop, then, is how to create an agent, we’ll look at resolveBeforeInstantiation (beanName bdbToUse) method.

Can see that it is called InstantiationAwareBeanPostProcessor the Bean method of post processor, look from the class name he is interceptor Bean instantiation phase, rather than the initialization phase. Point in to look at, can find him is by calling InstantiationAwareBeanPostProcessor callback method to generate bean object.

Call postProcessBeforeInstantiation method to generate the object.

So let’s stop here. Let’s take a look at how we use Spring Aop in general.

We’ll write an @Aspect annotation to the Aspect class and use the @EnableAspectJAutoProxy annotation to enable the proxy.

In can be found, it imports the a class AspectJAutoProxyRegistrar into the Spring container.

This class is a ImportBeanDefinitionRegistrar class, the search can be found that ImportBeanDefinitionRegistrar class will call registerBeanDefinitions method when parsing the configuration class.

The method to the container into a AnnotationAwareAspectJAutoProxyCreator Bean definitions of a class.

A InstantiationAwareBeanPostProcessor AnnotationAwareAspectJAutoProxyCreator class is.

At this point, as the above agreement, instantiate the beans now perform InstantiationAwareBeanPostProcessor, if there is a return object, use the object, or to create an instance. So the action of the @ EnableAspectJAutoProxy annotation is to add a container InstantiationAwareBeanPostProcessor class, intercept bean is created and generated proxy objects.

The interceptor handler creates a proxy object and returns it as follows.

If you click createProxy(beanClass, beanName, specificInterceptor, targetSource) and trace the underlying code, you can see that there are two ways to create dynamic proxies. If this class is an interface, use JDK dynamic proxies. Otherwise, the Cglib proxy is used.

At this point, the Aop part of the code to explain the end.

Among them, IoC’s circular dependency problem and Aop interceptor chain design interested can be recommended to look at the source code.