Detailed Spring IoC container

A, Spring IoC container Overview

  1. Dependency Inversion (DI): to obtain a dependent object is reversed.

  If the reference or dependency partner of the management carried out by specific objects, can lead to high coupling and reduces code testability, which is designed for complex object-oriented system is very unfavorable.

  In Spring, the IoC container inversion control is implemented based on the pattern carrier, which may be generated in the subject or directly injected into the object initialization, the injection may also be injected into the reference object by way of the object data field the method relies call. This dependence is recursive, the object is implanted layer by layer.

  Dependent on how the inversion control, the control of the business objects transit find particular platform or framework, object-oriented system design is to reduce the complexity and increase an effective solution for object-oriented system testability. It promotes the development of IoC design pattern is the IoC container to solve the core problem.

  Specific dependency injection main ways: interface injection (Type 1 IoC), setter injection (Type 2 IoC), constructor injection (the Type. 3 IoC) , in IoC design in Spring, setter injection and constructor injection is the main injection manner, relatively speaking, the use of Spring setter injection is a common way of injection, and in order to prevent abnormal injection, Spring IoC container also provides a check of the specific dependency.

Second, the design and implementation of IoC container series: BeanFactory and ApplicationContext

  BeanFactory simple container Series: This series container only achieve the most basic functions of the container;

  ApplicationContext container High Series: ApplicationContext application context, as an advanced form of the same period of existence. Application context on the basis of a simple container, adds a number of features of the framework-oriented application environment while doing a lot of adaptation.

  IoC container is used to manage the object dependencies for IoC container is, the BeanDefinition object dependency inversion mode is managed in dependence relation of data abstraction, the container is implementation-dependent data structure of the core inversion function, dependent inversion function revolves around the handling of this BeanDefinition done.

The figure is the interface design IoC container, we can see from the chart, there are two main design IoC container path:

1. BeanFactory from the interface to HierarchicalBeanFactory, then ConfigurableBeanFactory, is a major design BeanFactory path. In this design the interface paths, BeanFactory interface defines a basic specification IoC container. In the interface definition, it includes the getBean () method of such basic IoC container (Bean can be obtained by this method from the vessel).

2. The second main interface design is to ApplicationContext context interface application interface design as the core, the main interface design involved here are, from BeanFactory to ListableBeanFactory, then ApplicationContext, and then we used WebApplicationContext or ConfigurableApplicationContext interface. For ApplicationContext interface, which through inheritance MessageSource, ResourceLoader, ApplicationEventPublisher interfaces, based on BeanFactory simple IoC container adds a lot of support for the advanced characteristics of the container.

(A), BeanFactory

  BeanFactory interface defines the most basic form of IoC container, and provides a basic service contract IoC container should be observed, at the same time, which is why we use IoC container to be followed by the bottom and basic programming specification, these interface definitions tick the basic outline of IoC.

  FactoryBean BeanFactory and high frequency of use are based in Spring. They are very similar in spelling. It is a Factory, i.e. IoC container or object factory; is a Bean. In Spring, Bean are all to be managed by the BeanFactory (ie IoC container). But FactoryBean is concerned, this is not a simple Bean Bean, but can produce a generation of factory or modify objects Bean, similar to its implementation and design model of the factory model and modified mode.

BeanFactory Source:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";

    Object getBean(String var1) throws BeansException;

    <T> T getBean(String var1, @Nullable Class<T> var2) throws BeansException;

    Object getBean(String var1, Object... var2) throws BeansException;

    <T> T getBean(Class<T> var1) throws BeansException;

    <T> T getBean(Class<T> var1, Object... var2) throws BeansException;

    boolean containsBean(String var1);

    boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;

    boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, @Nullable Class<?> var2) throws NoSuchBeanDefinitionException;

    @Nullable
    Class<?> getType(String var1) throws NoSuchBeanDefinitionException;

    String[] getAliases(String var1);
}

By defining BeanFactory interface, the user can perform the following operations:

  1. getBean Bean acquired through the interface method, can also be checked by the type parameter Bean method;

  2. The method containsBean through the interface allows users to determine whether the container containing the name of the Bean developed;

  3. isSingleton whether to query interface method specified by name is Singleton Bean type Bean. For Singleton attribute, the user can specify the BeanDefinition;

  4. Does isPrototype through the interface method to query the specified name Bean is a prototype. Like Singleton property that may be specified by the user in BeanDefinition;

  5. The method isTypeMatch through an interface to query specifies the name of the Bean Class type is a specific type Class. The type may be specified by a user Class;

  6. getType to query the name specified by the interface method Class type of Bean;

  7. getAliases to query specifies the name of all the aliases Bean through the interface methods, these aliases are user-defined in BeanDefinition;

These interface methods defined by an outline of the basic characteristics IoC container.

  In order to more clearly understand the BeanFactory works as a container, we look at the source code of a BeanFanctory XmlBeanFactory the implementation class:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.beans.factory.xml;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.io.Resource;

/** @deprecated */
@Deprecated
public class XmlBeanFactory extends DefaultListableBeanFactory {
    private final XmlBeanDefinitionReader reader;

    public XmlBeanFactory(Resource resource) throws BeansException {
        this(resource, (BeanFactory)null);
    }

    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
        super(parentBeanFactory);
        this.reader = new XmlBeanDefinitionReader(this);
        this.reader.loadBeanDefinitions(resource);
    }
}

  We see XmlBeanFactory is used as the base class DefaultListableBeanFactory, DefaultListableBeanFactory IoC is very important to realize, in other IoC containers, such as ApplicationContext, the basic principles of its realization and XmlBeanFactory, just as to access to basic or extended by holders of DefaultListableBeanFactory function IoC container.

  XmlBeanFactory reference implementation, we programmatically using DefaultListableBeanFactory. We can see that some of the basic processes IoC container to use.

package com.xyfer.controller;

import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;

public class IoCDemo {
    public static void main(String[] args) {
        ClassPathResource res = new ClassPathResource("demo.xml");
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
        reader.loadBeanDefinitions(res);
    }
}

  In this way, we can use this DefaultListableBeanFactory IoC container by factory object. In use IoC container, you require the following steps:

  1. Create an abstract resource IoC configuration file, this abstract information resource contains the definition of BeanDefinition;

  2. Create a BeanFactory, used here DefaultListableBeanFactory;

  3. Create a loaded BeanDefinition reader, used here XmlBeanDefinitionReader to load an XML file in the form of BeanDefinition, BeanFactory configured to pass a callback;

  4. From the position defined resource configuration information is read, the specific parsing process carried out by XmlBeanDefinitionReader. After completing the entire registration and loading Bean definitions needed IoC container was built up. This time we can directly use the IoC container.

(二)、ApplicationContext

  In addition to providing container ApplicationContext BeanFactory provides the basic functions, but also provides users with the following additional services, so that ApplicationContext is an advanced form of meaningful IoC container.

 ApplicationContext from inheritance, we can see ApplicationContext BeanFactory on the basis of different additional features added by implementing different interfaces.

  1. Support different sources of information. ApplicationContext extends MessageSource interfaces extend the functionality of these information sources to support internationalization, providing services for the development of multi-language version of the application.

  2. access to resources. This feature is reflected in the support for ResourceLoader and Resource, so that we can get the Bean definition of resources from different places.

  3. Support application events. Inherited interfaces ApplicationEventPublisher, thereby introducing a mechanism in the event context. The combination of these events and the life cycle of Bean Bean has facilitated the management.

  4. The additional services provided ApplicationContext. These services enable basic functions IoC container richer. ApplicationContext is generally recommended as a basic form of IoC container in the development of applications.

Third, the initialization process IoC container

  In simple terms, the initialization IoC container is made refresh () start method, this method mark the official launch of IoC container. Specifically, this includes start BeanDefinition's Resource positioning, loading and registered three basic processes .

  1.Resource定位过程。Resource定位指的是BeanDefinition的资源定位,它由ResourceLoader通过统一的Resource接口来完成,这个Resource对各种形式的BeanDefinition的使用都提供来统一的接口。在文件系统中的Bean定义信息可以使用FileSystemResource来进行抽象;在类路径中的Bean定义信息可以使用ClassPathResource来抽象。

  2.BeanDefinition的载入。这个载入过程是把用户定义好的Bean表示成IoC容器内部的数据结构,而这个容器内部的数据结构就是BeanDefinition。具体来说,这个BeanDefinition实际上就是POJO对象在IoC容器中的抽象,通过这个BeanDefinition定义的数据结构,使IoC容器能够方便地对POJO对象也就是Bean进行管理。

  3.向IoC容器注册这些BeanDefinition的过程。这个过程是通过调用BeanDefinitionRegistry接口的实现来完成的。这个注册过程把载入过程中解析得到的BeanDefinition向IoC容器进行注册。通过分析,我们可以看到,在IoC容器内部将BeanDefinition注入到一个HashMap中去,IoC容器就是通过这个HashMap来持用这些BeanDefinition数据的。

  这里谈的是IoC容器初始化过程,这个过程一般不包含Bean依赖注入的实现。在Spring IoC的设计中,Bean定义的载入和依赖注入是两个独立的过程。依赖注入一般发生在应用第一次通过getBean向容器索取Bean的时候。但是又一个例外的配置,在使用IoC容器时有一个预实例化的配置,通过这个预实例化的配置(具体来说,可以通过为Bean定义信息中的lazyinit属性),可以对容器初始化过程做一个微小的控制,从而改变这个被设置了lazyinit属性的Bean的依赖注入过程。举例来说,如果我们对某个Bean设置了lazyinit属性,那么这个Bean的依赖注入在IoC容器初始化时就预先完成了,而不需要等到整个初始化完成以后,第一次使用getBean时才会触发。

四、IoC容器的依赖注入

  IoC容器的初始化过程完成的主要工作在IoC容器中建立BeanDefinition数据映射。但是在此过程中IoC容器并没有对Bean的依赖关系进行注入。

  当IoC容器已经载入了用户定义的Bean信息,容器中的BeanDefinition数据已经建立好的前提下,依赖注入的过程是在用户第一次向IoC容器索要Bean时触发的,也就是第一次调用getBean的时候触发,当然也有例外,就是当在BeanDefiniton中设置lazyinit属性来让容器完成对Bean的预实例化。这个预实例化实际上也是一个完成依赖注入的过程,但是这个依赖注入的过程是在初始化的过程中完成的。

  getBean是依赖注入的起点,之后会调用createBean,Bean对象会依据BeanDefinition定义的要求生成。createBean不但生成了需要的Bean,还对Bean初始化进行了处理,比如实现了在BeanDefinition中的init-method属性定义,Bean后置处理器等。CGLIB是一个常用的字节码生成器的类库,它提供了一系列的API来提供生成和转换JAVA的字节码的功能。在Spring AOP中也使用CGLIB对JAVA的字节码进行增强。在IoC容器中,Spring通过默认类SimpleInstantiationStrategy类来生成Bean对象,它提供了两种实例化Java对象的方法,一种是通过BeanUtils,它使用了JVM的反射功能,一种是通过CGLIB来生成。

  在实例化Bean对象生成的基础上,接下来就是各种依赖关系的处理。通过对BeanDefinition中的对象、value值、List、Map等进行解析,然后使用反射对属性进行注入。

  在Bean的创建和对象依赖注入的过程中,使用递归在上下文体系中查找需要的Bean和创建Bean;在依赖注入时,通过递归调用容器的getBean方法,得到当前Bean的依赖Bean,同时也触发对依赖Bean的创建和注入。在对Bean的属性进行依赖注入时,解析的过程也是递归的过程。这样,根据依赖关系,一层一层地完成Bean的创建和注入,直到最后完成当前Bean的创建。有了这个顶层Bean的创建和对它的属性依赖注入的完成,意味着和当前Bean相关的整个依赖链的注入也完成了。

五、IoC容器的其他相关特性

  1.ApplicationContext和Bean的初始化及销毁

    Bean的生命周期

    (1)Bean实例的创建

    (2)为Bean实例设置属性

    (3)调用Bean的初始化方法

    (4)应用可以通过IoC容器使用Bean

    (5)当容器关闭时,调用Bean的销毁方法

  2.lazy-init属性和预实例化

  3.FactoryBean的实现

  4.BeanPostProcessor的实现

  5.autowiring(自动依赖装配)的实现

    配置autowiring属性,IoC容器会根据这个属性的配置,使用反射自动查找属性的类型或者名字,然后基于属性的类型或名字来自动匹配IoC容器中的Bean,从而自动地完成依赖注入。

  6.Bean的依赖检查

    Spring通过依赖检查特性,帮助应用检查是否所有的属性都已经被正确设置。在Bean定义时设置dependency-check属性来指定依赖检查模式即可。属性可以设置为none、simple、object、all四种模式,默认的模式是none。

Guess you like

Origin www.cnblogs.com/xyfer1018/p/12170569.html