1. Spring’s IOC container

In the design of Spring IoC containers, there are two families of containers that can be viewed as concrete representations of containers:

BeanFactory simple container: implement the basic functions of containers, such as getBean, containsBean, isSingleton;

ApplicationContext: Adds context features to a simple container.

Interpretation: Why two collections instead of one? This comes down to the pattern of architecture design, with core processes defined at the bottom and extended functionality implemented at the top, with high cohesion and low coupling. In architectural design, such layering is necessary and can be replaced at any time by a layer of abstraction.

Spring manages various objects in spring-based applications and their interdependencies by defining BeanDefinitions. BeanDefinition abstracts our definition of beans and is the primary data type that makes containers work. IoC container is used to manage object dependencies. BeanDefinition is the data abstraction of object dependencies managed in dependency inversion mode, and it is also the core data structure of container to realize dependency inversion function. Dependency inversion function is completed around the processing of this BeanDefinition.

Interpretation: BeanDefinition is actually what the Bean definition looks like at run time. Whether the beans are xmL-configured, annotated, or custom scanned, they are ultimately hosted by BeanDefinition. If there is a custom XML tag, BeanDefinition is also generated after parsing and registered in IOC. Designed this way, IOC only needs to care about BeanDefinition, greatly increasing scalability and flexibility. When we get the Bean, if the Bean is not already initialized, the container finds the BeanDefinition and initializes the Bean and its dependencies based on the BeanDefinition.

2. Design of springIOC container

The interface design of IoC container is shown in the figure below:

The BeanFactory defines the basic IoC container specification, including the getBean method. HierarchicalBeanFactory The HierarchicalBeanFactory interface adds the getParentBeanFactory method after inherits the BeanFactory, giving the BeanFactory the management capabilities of a parent IoC container. In the following ConfigurableBeanFactory, we define some configuration functions for the BeanFactory, such as setting the parent IoC container through the setParentBeanFactory method. Configure the Bean backend processor with the addBeanPostProcessor method.

Reading:

As you can see, the BeanFactory defines only the basic functionality and is a core container interface definition. Spring extends the container’s capabilities layer by layer through inheritance on top of BeanFactory. To understand so many factory interfaces is to understand Spring’s design pattern, where inheritance is also an architectural layering, as mentioned earlier. Through inheritance and extension, the BeanFactory series interface is basically defined in ConfigurableBeanFactory. Of course, after the interface is layered, the specific implementation of each layer of BeanFactory is also layered, which will be explained in detail later. You can see here that interface oriented development greatly improves scalability and flexibility.

In the family of interfaces centered around ApplicationContext, The ListableBeanFactory and HierarchicalBeanFactory interfaces connect the BeanFactory interface definition to the interface definition of the ApplicationConext application context.

In the ListableBeanFactory interface, many BeanFactory interface functions are refined, such as the getBeanDefinitionNames interface method. For ApplicationContext interface, it through inheritance MessageSource, ResourceLoader, ApplicationEventPublisher interface, on the basis of the BeanFactory added support for advanced container features.

Reading:

ApplicationContext inherits the BeanFactory interface to provide the basic functions of a container and, depending on the context, extends them with the ListableBeanFactory interface. The primary difference between context and container, or reflect on container advanced features, such as MessageSource realize the internationalization, ResourceLoader to realize the resource loading, ApplicationEventPublisher event mechanism was realized. Therefore, we use a little more context in our daily work, and generally do not use the BeanFactory simple container directly.

3.FactoryBean

In BeanFactory, beans are obtained through a FactoryBean. A FactoryBean is a FactoryBean that generates instances of a type of Bean. One of its greatest benefits is that it allows you to customize the Bean creation process. The escape character “&” is used to get the FactoryBean itself, to distinguish between getting objects produced by the FactoryBean through the container and getting the FactoryBean itself.

Reading:

FactoryBean and BeanFactory, one is the Factory (IOC container Factory), and the other is a characteristic type of Bean. All beans are managed by the BeanFactory. A FactoryBean is a FactoryBean that produces or modifies the generation of objects. Its implementation is similar to the factory and decorator patterns in the design pattern. These two types have similar names and can be confused by many people, as long as you remember the distinction between the endings, one is a factory and the other is a Bean.

4. Design principle of BeanFactory container

BeanFactory provides a specification for using IoC containers. On this basis, Spring also provides a series of container implementations conforming to the IoC container interface for developers to use. The implementation of XmlBeanFactory is used as an example to illustrate the design principle of a simple IoC container.

Reading:

The XmlBeanFactory here is an XML-based container implementation. As can be seen from the class diagram, the container implementation is also layered. Each layer of interface has its corresponding implementation, and each implementation only does things within its scope of responsibility, forming a multi-level container structure through inheritance. If we were to define our own container implementation, we would simply inherit and implement it as needed. It is important to understand what layering means in order to design a better implementation.

DefaultListableBeanFactory actually contains the basic of the IoC container have important function, in the Spring, is actually the DefaultListableBeanFactory as a default function complete the IoC container to use. XmlBeanFactory in inherited DefaultListableBeanFactory vessel function at the same time, increased the new function, is a can read the definitions in the XML file way BeanDefinition IoC container.

Reading:

In inheritance system, DefaultListableBeanFactory realize the important function of the container. XmlBeanFactory takes care of parsing XML files and registering the parsed Bean definitions in the container. This is a layer by layer implementation design, after inheriting the default implementation, only need to customize according to their own scenarios, each layer of implementation is not complex.

In XmlBeanFactory, an XmlBeanDefinitionReader is initialized to read beanDefinitions defined in XML. XML, as a Resource file, encapsulates I/O operations through the Resource class. After XmlBeanDefinitionReader is initialized, call the loadBeanDefinitions method to load the BeanDefinition from the Resource.

Reading:

A truly complete container does several things during startup:

Find Bean definitions such as XML, annotations, etc. If it is a Resource file, it can be wrapped with the Resource class, supporting ClassPath, JAR, URL, etc.

Initialize Reader for Resource injection. The BeanDefinitionReader interface defines parsed methods. Spring provides many implementation classes by default.

The Reader parses the BeanDefinition, initializes it and registers it in the container.

5. Design principle of ApplicationContext container

In the realization of the commonly used FileSystemXmlApplicationContext, for example. Main function has been realized in AbstractXmlApplicationContext, in FileSystemXmlApplicationContext, as a specific application context, only need to implement and its design related to the two functions.

If applications use FileSystemXmlApplicationContext directly, for instance the support of this application context, at the same time start the IoC container refresh () process. This refresh() process involves a complex set of operations initiated by the IoC container that are similar for different container implementations, so they are encapsulated in the base class. So, what we see in the design of FileSystemXml is just a simple call.

Reading:

Refresh is an important operation of context. Start the Spring container, initialize some resources necessary for container start, BeanFactory creation and initialization, Bean creation, initialization, registration, non-lazy loading, register and set up the internationalization utility class MessageSource, register and set up the event, A series of procedures are called in this Refresh method. The implementation of Refresh will be explained in a later article, which I won’t go into here for space.

FileSystemXmlApplicationContext is loaded from a file system XML context, therefore

The function of loading XML from the file system is designed.

Reading:

As you can see, the implementation and inheritance of Spring’s internal context is complex and difficult to understand. In fact, it’s easier to think of it as a layer of implementation, with each layer implementing only its own related functionality. Similar or common capabilities are precipitated down to the underlying base capabilities, and the upper level implementation just makes calls. Look at the source code, to have a global view, which is common capabilities, which is this level of custom functions, so it will be better to understand a bit.