How does the Ioc container work

After introducing the structure and relationships of Core, Bean, and Context components, let’s take a look at how they work from a consumer perspective, and how we make Spring perform various functions, what functions Spring can have, and how they are derived.

How to create a BeanFactory factory

As illustrated in Figure 2, the Ioc container is actually the Context component that combines the other two components to build a Bean network. How is this network built? The entrance of the building is in the refresh method of AbstractApplicationContext classes. The code for this method is as follows:

Listing 1. AbstractApplicationContext. Refresh

 

public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; }}}Copy the code

This approach is the complete code for building the entire Ioc container, and understanding every line of code in it will give you a pretty good idea of how Spring works and what it does.

This code consists of the following steps:

  • Build a BeanFactory to produce the actors you need
  • Register events that may be of interest
  • Create a Bean instance object
  • Triggers the event being listened on

The following is a code analysis of these processes.

The second and third sentences create and configure the BeanFactory. This is refresh, which is to refresh the configuration, and I told you that Context has subclasses that can be updated, and this is exactly what we’re doing, updating the BeanFactory if it already exists, creating a new BeanFactory if it doesn’t exist. Here is the method code to update the BeanFactory:

Listing 2. AbstractRefreshableApplicationContext. RefreshBeanFactory

protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException( "I/O error parsing bean definition source for " + getDisplayName(), ex); }}Copy the code

This method implements AbstractApplicationContext refreshBeanFactory abstraction method, the code clearly illustrate the BeanFactory creation process. Note the changes in the type of the BeanFactory object. As mentioned earlier, it has many subclasses. It is important to know when to use different subclasses. The BeanFactory primitive objects is DefaultListableBeanFactory, this is critical, because his design to face a variety of operation of the object, after have a look at the class inheritance hierarchy class diagram below:

 

In addition to the classes related to BeanFactory, the diagram also shows a register related to the Bean. A line loadBeanDefinitions(beanFactory) in the refreshBeanFactory method will find the answer, and the method will start loading and parsing the Bean definitions. That is to convert the user-defined data structure into a specific data structure in the Ioc container.

Created after the BeanFactory, it follows that add some Spring itself need some tools, this operation done in AbstractApplicationContext prepareBeanFactory method.

AbstractApplicationContext in the next three lines of code to the function of the Spring extensibility played a vital role. The first two lines allow you to make changes to the configuration of the BeanFactory you have built now, and the second line allows you to add custom actions to the Bean instance objects you create later. So they all extend the functionality of Spring, so we must understand this part to learn to use Spring.

Among them in invokeBeanFactoryPostProcessors method is mainly for realization of spring BeanFactoryPostProcessor interfaces subclass. And execute its postProcessBeanFactory method, which is declared as follows:

BeanFactoryPostProcessor.postProcessBeanFactory

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
    throws BeansException;
Copy the code

Its parameters is the beanFactory that can make changes to the beanFactory, pay attention to this is the beanFactory ConfigurableListableBeanFactory type here, This also confirms the previous introduction of different BeanFactory used in different occasions, here can only be configurable BeanFactory, to prevent some data by the user to modify.

RegisterBeanPostProcessors method also can get a subclass of the realization of the user to define the BeanPostProcessor interface, and implement them to register the BeanFactory object beanPostProcessors variable. BeanPostProcessor declared in two methods: postProcessBeforeInitialization, postProcessAfterInitialization respectively for the Bean object initialization time. You can perform user-defined operations.

The next few lines of code initialize the listener event and register other listeners on the system, which must be a subclass of ApplicationListener.

How do I create Bean instances and build a network of beans

This is a list of the Bean instantiation code, starts from the finishBeanFactoryInitialization method.

AbstractApplicationContext.finishBeanFactoryInitialization

protected void finishBeanFactoryInitialization(
    ConfigurableListableBeanFactory beanFactory) {

    // Stop using the temporary ClassLoader for type matching.
    beanFactory.setTempClassLoader(null);

    // Allow for caching all bean definition metadata, not expecting further changes.
    beanFactory.freezeConfiguration();

    // Instantiate all remaining (non-lazy-init) singletons.
    beanFactory.preInstantiateSingletons();
}
Copy the code

You can see from the above code that the Bean instantiation takes place in the BeanFactory. The code for the preInstantiateSingletons method is as follows:

DefaultListableBeanFactory.preInstantiateSingletons

public void preInstantiateSingletons() throws BeansException { if (this.logger.isInfoEnabled()) { this.logger.info("Pre-instantiating singletons in " + this); } synchronized (this.beanDefinitionMap) { for (String beanName : this.beanDefinitionNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (! bd.isAbstract() && bd.isSingleton() && ! bd.isLazyInit()) { if (isFactoryBean(beanName)) { final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX+  beanName); boolean isEagerInit; if (System.getSecurityManager() ! = null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged( new PrivilegedAction() { public Boolean run() { return ((SmartFactoryBean) factory).isEagerInit(); } }, getAccessControlContext()); } else { isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit(); } if (isEagerInit) { getBean(beanName); } } else { getBean(beanName); } } } } }Copy the code

So there’s a very important Bean here, FactoryBean, and you can say that half the functionality of Spring’s extension is related to this Bean, so it’s a special Bean, it’s a FactoryBean, it’s a Bean that produces beans, By producing a Bean, I mean an instance of a Bean, and if a class inherits FactoryBean, the user can simply implement his getObject method and define the method that produces the instance object. Inside Spring, however, the instance object of this Bean is FactoryBean, which gives Spring great extensibility by calling the getObject method on this object to get the custom generated object. Spring gets the objects of FactoryBean itself by prefixing &.

The following is a flowchart of how to create Bean instance objects and how to build the relationship between Bean instance objects, which is one of Spring’s core keys.

If it is a normal Bean, create an instance of it directly, by calling the getBean method

Extension points for the Ioc container

There is still the question of how to make these Bean objects extensible enough to allow users to do things. So what are the extension points? How does Spring call these extension points?

For Spring’s Ioc container, there are a few. Spring BeanFactoryPostProcessor BeanPostProcessor. They are called when building the BeanFactory and when building the Bean object, respectively. There are InitializingBean and DisposableBean, which are called when the Bean instance is created and disposed of, respectively. Users can implement the methods defined in these interfaces, and Spring will call them when appropriate. And then there’s FactoryBean which is a special Bean that can be more controlled by the user.

These extension points are often where we use Spring for our specific tasks. Mastering Spring depends on how well you know what Spring extension points are and how to use them. To know how to use them, you have to understand their inherent mechanisms. It can be explained by the following analogy.

We think of the Ioc container as a box that has molds for several balls that can be used to make many different kinds of balls, and a machine for making these balls, which produces the ball molds. The BeanFactory is the machine that makes the ball mold, the ball mold is the Bean, and the ball mold is an instance of the Bean. Where are the extension points mentioned earlier? BeanFactoryPostProcessor corresponds to the idea that when the mold is built, you will have the opportunity to make appropriate modifications, i.e. it will help you modify the mold. InitializingBean and DisposableBean are at the beginning and end of the ball molding, so you can do some preparatory and cleanup work. BeanPostProcessor allows you to make the appropriate modifications to the ball modeled by the ball. Finally, there’s FactoryBean, which is a magic ball model. The ball is not set in advance, but you determine its shape for him, and since you can determine the shape of the ball, of course the ball he makes is the ball you want, so you can find all the balls you want in the box.

How can I use the Ioc container

What can Spring do for us, and what can Spring’s Ioc container do for us? To use Spring, you must first build the Ioc container. Spring cannot work without it. Applicatoncontext. XML is the default CONFIGURATION file for the Ioc container. Consider AOP, which I’ll cover later.

Ioc actually builds a rubik’s cube for you, and Spring builds the skeleton architecture for you. What good things can be produced by this rubik’s cube? You must be involved in this. So how do we get involved? This is what I said earlier about knowing which extension points Spring has, and how to change Spring’s general behavior by implementing those extension points. Spring has many examples of how to implement extension points to get the desired personalized results, and AOP implementations where Spring itself implements its extension points to achieve the desired feature functionality can be referenced.

# Spring Core component detail beans,Context,Core (2)

Original address :blog.51cto.com/u_15127644/…