IOC process analysis - instantiation and initialization

This content is to analyze all the rest of the core method, focusing on the instantiation and initialization of beans. Friends who are interested in the rest of the IOC content can jump directly according to the navigation bar at the end of the article.

Source code analysis

Then the last article (the last article is: [IOC Process Analysis-BeanFactoyPostProcessor and BeanPostProcessor](https://liwqtm.github.io/2022/03/14/Spring IOC-3/#more)), we still continue to read The core method of IOC is the content of the refresh method. This time I will mention two frequently asked questions in interviews: the difference between BeanFactory and FactoryBean, and the difference between FactoryBean and ordinary Bean. I will elaborate at the end of this article. Those who need an interview can directly skip to the end of the article to view it.

Initialize the message source, internationalization - initMessageSource method

After the registerBeanPostProcessors method mentioned in the previous article, here comes the initMessageSource method.

The initMessageSource method is not our focus, we will simply describe its main function here: initialize the message source, that is, internationalization, the purpose is to switch between multiple languages, and the execution result of the initMessageSource method is to collect singletonObjects in the singleton pool in the BeanFactory Added a bean, a complete bean object messageSource object.

Initialize the event broadcaster - initApplicationEventMulticaster method

The core method then goes down and sees the initApplicationEventMulticaster method. This method is also simple. It still adds a complete bean object to the singletonObjects collection of the singleton pool in the BeanFactory. If the event broadcaster is not configured, it will be created by default. is a SimpleApplicationEventMulticaster object.

Spring event propagation mechanism

This also needs to know a knowledge point: Spring event propagation mechanism. First of all, we need to know that the Spring event propagation mechanism is modified by referring to the listener mode. The normal listener mode is: the listener and the listener. When the listener changes, the change will be pushed to the listener. On this basis, spring adds an event broadcaster, which maintains the relationship between the listener and the listener, and also puts the listener into the collection list, and then corresponds to the relationship of the listener.

So here are three roles:

  • Event Listener (ApplicationListener)

  • Event publisher (ApplicationEventPublisher) Because ApplicationContext implements ApplicationEventPublisher, event publishing can directly use ApplicationContext

  • Event broadcaster (ApplicationEventMulticaster), where the system creates SimpleApplicationEventMulticaster by default

In addition, there is another one is the event itself (ApplicationEvent). When the event publisher publishes an event to the event broadcaster , it actually transmits an ApplicationEvent event object, and then the event broadcaster transmits it to each listener list again. Event listeners for this ApplicationEvent event object.

Let's talk about the event propagation mechanism first. Continue to talk about the core code.

Extension method - onRefresh method

The onRefresh method does not say this, this is an empty method, which can be used to implement some business logic by itself.

Register Listener - registerListeners method

Here is the listener registration of the event propagation mechanism mentioned above, or a complete bean object is added to the singletonObjects collection of the singleton pool in BeanFactory, and all objects that implement the ApplicationListener interface will also be obtained, and then the added broadcaster maintenance In the listener list collection, waiting for subsequent calls.

Instantiation and initialization methods - finishBeanFactoryInitialization method

Finally, we have reached the point of this time. After finishing the previous series of operations, we come to the key point of instantiating and initializing beans in the IOC flow chart. Let's review this part of the flow chart first. This is also the last step in the IOC process.

image-20220423204948988

Let's follow up the finishBeanFactoryInitialization method. You don't need to read the rest of the code. Here are some loaders and the like. Focus on the last sentence of this method.

// 5.实例化所有剩余(非懒加载)单例对象  重要===》
beanFactory.preInstantiateSingletons();	

Get the BeanDefinition and call the getBean method - preInstantiateSingletons method

Following up the preInstantiateSingletons method, the first thing to obtain is the collection of all BeanDefinition names. Note that the code we are currently executing is the BeanFactroy created before, so this collection of names can be obtained directly.

// 1.创建beanDefinitionNames的副本beanNames用于后续的遍历,以允许init等方法注册新的bean定义。
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

Then iterate through the collection and get specific objects by name.

// 2.遍历beanNames,触发所有非懒加载单例bean的初始化
for (String beanName : beanNames) {
    
    

  // 3.获取beanName对应的MergedBeanDefinition
  /*
			  Merged意义在于处理bean之间的父子继承关系,处理属性继承和覆盖(如果有的话)。
			 */
  RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

The next step is to judge whether to hand over the object to spring management, that is, whether to add the object to the BeanFcatory’s singleton pool attribute. There are three bases: whether the Bean instance corresponding to BeanDefinition is an abstract class, whether it is a singleton, Whether it is lazy loading, as long as one of the conditions is not met, the spring singleton pool will not be registered at present, that is to say, it must be a non-abstract class, non-lazy loading singleton object spring will register when it starts.

// 4.bd对应的Bean实例:不是抽象类 && 是单例 && 不是懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    
    

The next step is to classify these non-abstract classes and non-lazy-loaded singleton objects again, and judge whether the object implements the FactoryBean interface. FactoryBean will process the object name separately, and then register its object. Note that this is not the getObjeck of registering FactoryBean The object returned by the method.

The methods of FactoryBean interface registration and ordinary registration are the same, mainly because the beanName is processed, so we focus on the getBean method.

// 5.判断beanName对应的bean是否为FactoryBean
if (isFactoryBean(beanName)) {
    
    }
else {
    
    
  // 6.如果beanName对应的bean不是FactoryBean,只是普通Bean,通过beanName获取bean实例
  // 调用前置后置处理器、实例化、填充、反射,都藏在这个getBean里!
  //getBean---doGetBean---createBean---doCreateBean
  getBean(beanName);
}

getBean->doGetBean->createBean->doCreateBean

The future calls of the getBean method in spring are more complicated, but they only follow the main process, that is, the method logic of getBean->doGetBean->createBean->doCreateBean, and will not be lost. Let’s briefly introduce the previous ones here. The three methods, which are building beans and registering singleton pools, are still in the doCreateBean method.

The first is the call of the getBean method, which is quite simple here, that is, directly call the doGetBean method.

@Override
public Object getBean(String name) throws BeansException {
    
    
  // 获取name对应的bean实例,如果不存在,则创建一个
  return doGetBean(name, null, null, false);
}

Then there is the doGetBean method, there are more codes here, what we need to know is what is generally done in this method. Its main purpose is to call the createBean method.

  1. Determine whether the current object has been registered in the singleton pool of spring, and return it directly, which is why the singleton pool is also called the first-level cache.
  2. To solve circular dependencies, here we will look back when we talk about circular dependencies later.
  3. Then judge if there is a sub-container, and then go to the sub-container to judge whether there is a current object instance.
  4. Finally, the specific BeanDefinition object is obtained, and then it is judged whether the object is a singleton, because the singleton is a piece of logic here, and the multiple examples are another piece of logic, but in the end, the createBean method is called.

Then there is the createBean method. The content here is relatively simple. The most important thing is to call the doCreateBean method.

Really get the content of the complete object - doCreateBean method

Finally came to the top priority of this time, which is also the core of the IOC. After clarifying this process, the IOC interview is basically not a problem. The old rule is to focus on the key points and analyze bit by bit.

instantiate

The first is the instantiation of the bean, where the createBeanInstance method is called. The code in this method has nothing to delve into. It is to obtain the corresponding instance object through reflection. Note the first point: the object instanced here does not have any attribute values, it is just an object instanced by reflection.

if (instanceWrapper == null) {
    
    
  // 3.【bean实例化】根据beanName、mbd、args,使用对应的策略创建Bean实例,并返回包装类BeanWrapper【关键点】!!
  instanceWrapper = createBeanInstance(beanName, mbd, args);  // ===> 反射来创建实例
}

// 4.拿到创建好的Bean实例,这里已经实例化完成! 相当于new出来了
Object bean = instanceWrapper.getWrappedInstance();
initialization

Then look at the second key point: bean initialization. Here are two code calls, the first is attribute injection, and then the bean initialization. The main attribute injection belongs to the initialization process, not instantiation. The distinction here is for the understanding and resolution of circular dependencies later.

// 9.【属性注入】对bean进行属性填充;其中,可能存在依赖于其他bean的属性,则会递归初始化依赖的bean实例
populateBean(beanName, mbd, instanceWrapper);  // ===> instanceWrapper藏着我们的bean,给他灌属性

// 10.【bean初始化】(回调Bean的后置处理器等..)!
exposedObject = initializeBean(beanName, exposedObject, mbd);  // ====》
attribute injection

Follow up with the populateBean method first.

Here we look directly at the key point, the last sentence in the method. All of the above are some checks and the like, and we will not pay attention to them for the time being.

// 真正的注入在这里!!将属性注入到bean实例当中,这才是真正的属性赋值的地方【关键点】
applyPropertyValues(beanName, mbd, bw, pvs);

Continue with the applyPropertyValues ​​method.

Here we find the call of the resolveValueIfNecessary method. The above content is to obtain the attributes that need to be assigned to the current object and in order to build the valueResolver parser object, judge whether some are annotation injection, set injection, etc., and then build a specific parser object, we focus on the resolveValueIfNecessary method.

/*
 *  【重点】使用解析器解析不同类型的值(包括循环依赖的解决)
 */
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);

Continue to the resolveValueIfNecessary method.

At this point, we need to judge the type of the attribute that needs to be injected, and then call the specific assignment method. We will not focus on it here. When we will see the circular dependency later, we will look back at the specific method for object injection.

// 7. 解析List
else if (value instanceof ManagedList) {
    
    
  // May need to resolve contained runtime references.
  return resolveManagedList(argName, (List<?>) value);
}
// 8. 解析Set
else if (value instanceof ManagedSet) {
    
    
  // May need to resolve contained runtime references.
  return resolveManagedSet(argName, (Set<?>) value);
}
// 9. 解析Map
else if (value instanceof ManagedMap) {
    
    
  // May need to resolve contained runtime references.
  return resolveManagedMap(argName, (Map<?, ?>) value);
}
Activate all Aware methods

Then follow up with the initializeBean method.

Here you can see that the first thing is to activate all Aware methods, here is to judge whether the current object implements the BeanNameAware, BeanClassLoaderAware, BeanFactoryAware interface, and then plug the corresponding corresponding setBeanName, setBeanClassLoader, setBeanFactory methods.

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    
    
  // 1.激活Aware方法
  if (System.getSecurityManager() != null) {
    
    
    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    
    
      invokeAwareMethods(beanName, bean);
      return null;
    }, getAccessControlContext());
  }
  else {
    
    
    // 如果 bean 实现了 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 接口,回调
    invokeAwareMethods(beanName, bean);
  }
The Before method of the post-processor of all beans loaded

The next step is to call the Before method of the post-processor of all the Beans we loaded before. Here I am the IOC process analysis mentioned in the previous article-BeanFactoyPostProcessor and BeanPostProcessor . The call here is also very simple, that is, get the BeanPostProcessor in the BeanFactory Collection, and then call iteratively.

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
    
    
  // 2.在初始化前应用BeanPostProcessor的postProcessBeforeInitialization方法,允许对bean实例进行包装
  wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
  throws BeansException {
    
    

  Object result = existingBean;
  // 1.遍历所有注册的BeanPostProcessor实现类,调用postProcessBeforeInitialization方法
  for (BeanPostProcessor processor : getBeanPostProcessors()) {
    
    
    // 2.在bean初始化方法执行前,调用postProcessBeforeInitialization方法
    Object current = processor.postProcessBeforeInitialization(result, beanName);
    if (current == null) {
    
    
      return result;
    }
    result = current;
  }
  return result;
}
Execute the InitializingBean interface initialization method and custom initialization method

Continue to the invokeInitMethods initialization method. This step is to determine whether the init-method attribute is set in the bean configuration information tag. If so, execute the set custom initialization method, or determine whether the bean implements the InitializingBean interface. If so, call it afterPropertiesSet method. Note that the InitializingBean interface is taken, and then the custom method is taken.


try {
    
    
  // 3.调用初始化方法( 处理 bean 中定义的 init-method,或者如果 bean 实现了 InitializingBean 接口,调用 afterPropertiesSet() 方法)
  invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
    
    
  throw new BeanCreationException(
    (mbd != null ? mbd.getResourceDescription() : null),
    beanName, "Invocation of init method failed", ex);
}
Call the After method of all BeanPostProcessor post processors

Then finally call the After method of all BeanPostProcessor post-processors, which is still an iterative call here, which is no different from the Before method above. Finally, return the initialization completion result.

if (mbd == null || !mbd.isSynthetic()) {
    
    
  // 4.在初始化后应用BeanPostProcessor的postProcessAfterInitialization方法,允许对bean实例进行包装
  wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

// 5.返回wrappedBean
return wrappedBean;

You don’t need to look at the latter method, just understand it yourself. After the execution of this method is completed, we get a complete bean object, and then we return to the doGetBean method. There is a very interesting place here. I just forgot to say that the createBean method itself is not called in the doGetBean method. Let's look at it again Below the specific code.

Inject the complete object into the singleton pool

Note that the meaning here is: call the getSingleton method, and pass in a beanName and a function. That is to say, the doGetBean method calls the getSingleton method instead of the doGetBean method. Of course, the doGetBean method is called in the end. Our above idea is correct, that is, add a step in the middle.

// 9.1 scope为singleton的bean创建(新建了一个ObjectFactory,并且重写了getObject方法)
sharedInstance = getSingleton(beanName, () -> {
    
    
  try {
    
    
    // 9.1.1 创建Bean实例 ===》
    return createBean(beanName, mbd, args);  // ===> 重点看这里,真实的创建过程
  }
  catch (BeansException ex) {
    
    
    // Explicitly remove instance from singleton cache: It might have been put there
    // eagerly by the creation process, to allow for circular reference resolution.
    // Also remove any beans that received a temporary reference to the bean.
    destroySingleton(beanName);
    throw ex;
  }
});

Let's follow up the getSingleton method here. First, lock it to avoid repeated creation, then judge whether it exists in the first-level cache, that is, in the singleton pool, then do some preparatory work, and finally call the getObject method we just passed in the function, and turn back here Look at the fact that the input parameter is an ObjectFactory type object, and the function we just looked at is the rewriting of the getObject method.

Another thing to note here is that before calling the doCreateBean method, a property in the singletonsCurrentlyInCreation collection will be added here, which records that the current Bean is being created.

// 5.创建单例前的操作
beforeSingletonCreation(beanName);

// 6.执行singletonFactory的getObject方法获取bean实例
singletonObject = singletonFactory.getObject();
Function interface - ObjectFactory interface

Here is another little knowledge point. I don’t think much about it myself. Let’s speculate. First of all, the ObjectFactory interface mentioned above has only one method, which is getObject, but there is an annotation @FunctionalInterface provided by java. The literal understanding is Functional interface, as I understand it, is a functional interface, which can receive a functional method, which is only the same as the above implementation.

@FunctionalInterface
public interface ObjectFactory<T> {
    
    

	T getObject() throws BeansException;
}

Then after the previous step, the next step is to call the addSingleton method. This step is to store the newly created object in the singleton pool.

// 8.如果是新的单例对象,将beanName和对应的bean实例添加到缓存中(singletonObjects、registeredSingletons)
addSingleton(beanName, singletonObject);
protected void addSingleton(String beanName, Object singletonObject) {
    
    
  synchronized (this.singletonObjects) {
    
    
    // 1.添加到单例对象缓存(1级缓存)
    this.singletonObjects.put(beanName, singletonObject);
    // 2.将单例工厂缓存移除(已经不需要)
    this.singletonFactories.remove(beanName);
    // 3.将早期单例对象缓存移除(已经不需要)(2级缓存)
    this.earlySingletonObjects.remove(beanName);
    // 4.添加到已经注册的单例对象缓存
    this.registeredSingletons.add(beanName);
  }
}

So far, the content of IOC instantiation, initialization, and registration of the singleton pool is basically over.

Publishing events and clearing the context - finishRefresh method

Going back to the refresh core method, we still have the last step, which is to publish events and clear the context environment. It is also easy to understand here. Didn’t we build objects such as event broadcasters above, which are used to publish events to the broadcaster. Then it is pushed by the broadcaster to each listener in the listening list. As for the context and the like, we will talk about the content of MVC later.

protected void finishRefresh() {
    
    
  // Clear context-level resource caches (such as ASM metadata from scanning).
  //清除resourceCaches资源缓存中的数据
  clearResourceCaches();

  // Initialize lifecycle processor for this context.
  //注释1. 为此上下文初始化生命周期处理器
  initLifecycleProcessor();

  // Propagate refresh to lifecycle processor first.
  //注释2. 首先将刷新完毕事件传播到生命周期处理器(触发isAutoStartup方法返回true的SmartLifecycle的start方法)
  getLifecycleProcessor().onRefresh();

  // Publish the final event.
  //注释3. 推送上下文刷新完毕事件到相应的监听器
  publishEvent(new ContextRefreshedEvent(this));

  // Participate in LiveBeansView MBean, if active.
  LiveBeansView.registerApplicationContext(this);
}

Interview point: The difference between BeanFactory and FactoryBean and the difference between FactoryBean and ordinary Bean

The difference between BeanFactory and FactoryBean

Let's first talk about the difference between BeanFactory and FactoryBean. This is relatively simple. We already know BeanFactory well through these articles, so we only need to know FactoryBean now.

FactoryBean is a simple interface, in which there are three methods that need to be implemented, the most important one is getObject. It can be said that if an object implements the FactoryBean interface, then when the bean is obtained, it will no longer obtain its own object instance. That is to say, if A If the FactoryBean interface is implemented, then when applicationContext.getBean(A) is executed, what is obtained may not be A, but the object returned by the getObject method of FactoryBean.

public interface FactoryBean<T> {
    
    

	T getObject() throws Exception;

	Class<?> getObjectType();

	boolean isSingleton();

}

By the way, here we can also simply look at how FactoryBean gets the object. Still follow up the call with applicationContext.getBean(A).

After follow-up, it was found that there was a call back to the doGetBean method mentioned above.

public Object getBean(String name) throws BeansException {
    
    
  // 获取name对应的bean实例,如果不存在,则创建一个
  return doGetBean(name, null, null, false);
}

In fact, after the above registration, we can get the corresponding object instance in the singleton pool. Note that the instance here is still an instance of the A object, and then we can enter the judgment that we did not enter above, and call the getObjectForBeanInstance method.

// 2.尝试从缓存中获取beanName对应的实例, 循环依赖闭环可以拿到
		Object sharedInstance = getSingleton(beanName);

// 这里说下 args ,虽然看上去一点不重要。前面我们一路进来的时候都是 getBean(beanName),
// 所以 args 传参其实是 null 的,但是如果 args 不为空的时候,那么意味着调用方不是希望获取 Bean,而是创建 Bean
if (sharedInstance != null && args == null) {
    
    
  // 3.1 返回beanName对应的实例对象(主要用于FactoryBean的特殊处理,普通Bean会直接返回sharedInstance本身)
  bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

The method here is simpler. If it is not implemented by FactoryBean, return it directly, that is to say, an ordinary object, do not go through the following process, if it is, force the incoming instance object into a FactoryBean object, and then getObjectFromFactoryBean method to get the real returned instance object, this method is to call its getObject method. But the call is still in the doGetObjectFromFactoryBean method inside.

if (!(beanInstance instanceof FactoryBean)) {
    
    
  return beanInstance;
}

if (object == null) {
    
    
  // Return bean instance from factory.
  // 3.只有beanInstance是FactoryBean才能走到这边,因此直接强转
  FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
  // Caches object obtained from FactoryBean if it is a singleton.
  if (mbd == null && containsBeanDefinition(beanName)) {
    
    
    // 4.mbd为空,但是该bean的BeanDefinition在缓存中存在,则获取该bean的MergedBeanDefinition
    mbd = getMergedLocalBeanDefinition(beanName);
  }
  // 5.mbd是否是合成的(这个字段比较复杂,mbd正常情况都不是合成的,也就是false)
  boolean synthetic = (mbd != null && mbd.isSynthetic());
  // 6.从FactoryBean获取对象实例
  object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
// 7.返回对象实例
return object;

To sum up: BeanFactory is a Bean factory, including singleton pool, BeanDefinition, BeanPostProcessor, etc., and FactoryBean is an interface. As long as the interface is implemented, when obtaining its object, it is the object returned by the getObject method, not the object instance itself.

The difference between FactoryBean and ordinary Bean

In fact, this point has just been said. The difference between their swords is that when obtaining object instances, ordinary beans are returned after being obtained in the singleton pool, and objects that implement the FactoryBean interface continue to go until the end. Call the getObject method to return.

Summarize

To summarize the full text, this time I have finished all the calls of the core methods, the main focus is on the instantiation, initialization, registration, etc. of beans, and some content such as two method calls of beanPostProcessor, and if there are others, it is the event propagation of spring Mechanism, and finally I talked about two common interview points. The follow-up article will talk about the interview point: the resolution of circular dependencies.

Appendix Spring Source Code Analysis Series Articles

time article
2022-03-09 A brief introduction to the basic concepts of Spring and the IOC process
2022-03-11 IOC process analysis - creation of BeanFactory
2022-03-14 IOC process analysis - BeanFactoyPostProcessor and BeanPostProcessor
2022-03-15 IOC process analysis - instantiation and initialization
2022-03-17 IOC process analysis - circular dependency

Guess you like

Origin blog.csdn.net/qq_39339965/article/details/124416388