Spring IoC容器初始化过程

IoC容器是什么?
IoC文英全称Inversion of Control,即控制反转,我么可以这么理解IoC容器:
  把某些业务对象的的控制权交给一个平台或者框架来同一管理,这个同一管理的平台可以称为IoC容器。

我们刚开始学习spring的时候会经常看到的类似下面的这代码:

ApplicationContext appContext = new ClassPathXmlApplicationContext("cjj/models/beans.xml");
Person p = (Person)appContext.getBean("person");

  上面代码中,在创建ApplicationContext实例对象过程中会创建一个spring容器,该容器会读取配置文件"cjj/models/beans.xml",并统一管理由该文件中定义好的所有bean实例对象,如果要获取某个bean实例,使用getBean方法就行了。例如我们只需要将Person提前配置在beans.xml文件中(可以理解为注入),之后我们可以不需使用new Person()的方式创建实例,而是通过容器来获取Person实例,这就相当于将Person的控制权交由spring容器了,差不多这就是控制反转的概念。

  那在创建IoC容器时经历了哪些呢?为此,先来了解下Spring中IoC容器分类,继而根据一个具体的容器来讲解IoC容器初始化的过程。
Spring中有两个主要的容器系列:1、实现BeanFactory接口的简单容器;2、实现ApplicationContext接口的高级容器。
ApplicationContext比较复杂,它不但继承了BeanFactory的大部分属性,还继承其它可扩展接口,扩展的了许多高级的属性,其接口定义如下:

public interface ApplicationContext extends EnvironmentCapable,                   ListableBeanFactory,    //继承于BeanFactory                  HierarchicalBeanFactory,//继承于BeanFactory
                  MessageSource, //                  ApplicationEventPublisher,//                  ResourcePatternResolver  //继承ResourceLoader,用于获取resource对象

  在BeanFactory子类中有一个DefaultListableBeanFactory类,它包含了基本Spirng IoC容器所具有的重要功能,开发时不论是使用BeanFactory系列还是ApplicationContext系列来创建容器基本都会使用到DefaultListableBeanFactory类,可以这么说,在spring中实际上把它当成默认的IoC容器来使用。下文在源码实例分析时你将会看到这个类。

  

  回到本文正题上来,关于Spirng IoC容器的初始化过程在《Spirng技术内幕:深入解析Spring架构与设计原理》一书中有明确的指出,IoC容器的初始化过程可以分为三步:

  1. Resource定位(Bean的定义文件定位)
  2. 将Resource定位好的资源载入到BeanDefinition
  3. 将BeanDefiniton注册到容器中
  • 第一步 Resource定位

  Resource是Sping中用于封装I/O操作的接口。正如前面所见,在创建spring容器时,通常要访问XML配置文件,除此之外还可以通过访问文件类型、二进制流等方式访问资源,还有当需要网络上的资源时可以通过访问URL,Spring把这些文件统称为Resource,Resource的体系结构如下:

常用的resource资源类型如下:
  FileSystemResource:以文件的绝对路径方式进行访问资源,效果类似于Java中的File;
  ClassPathResourcee:以类路径的方式访问资源,效果类似于this.getClass().getResource("/").getPath();
  ServletContextResource:web应用根目录的方式访问资源,效果类似于request.getServletContext().getRealPath("");
  UrlResource:访问网络资源的实现类。例如file: http: ftp:等前缀的资源对象;
  ByteArrayResource: 访问字节数组资源的实现类。

那如何获取上图中对应的各种Resource对象呢?
  Spring提供了ResourceLoader接口用于实现不同的Resource加载策略,该接口的实例对象中可以获取一个resource对象,也就是说将不同Resource实例的创建交给ResourceLoader的实现类来处理。ResourceLoader接口中只定义了两个方法:

Resource getResource(String location); //通过提供的资源location参数获取Resource实例ClassLoader getClassLoader(); // 获取ClassLoader,通过ClassLoader可将资源载入JVM

注:ApplicationContext的所有实现类都实现RecourceLoader接口,因此可以通过直接调用getResource(参数)获取Resoure对象。不同的ApplicatonContext实现类使用getResource方法取得的资源类型不同,例如:FileSystemXmlApplicationContext.getResource获取的就是FileSystemResource实例;ClassPathXmlApplicationContext.gerResource获取的就是ClassPathResource实例;XmlWebApplicationContext.getResource获取的就是ServletContextResource实例。

在资源定位过程完成以后,就为资源文件中的bean的载入创造了I/O操作的条件,如何读取资源中的数据将会在下一步介绍的BeanDefinition的载入过程中描述。

  • 第二步 通过返回的resource对象,进行BeanDefinition的载入

1.什么是BeanDefinition? BeanDefinition与Resource的联系呢?

  官方文档中对BeanDefinition的解释如下:
  A BeanDefinition describes a bean instance, which has property values, constructor argument values, and further information supplied by concrete implementations.
  它们之间的联系从官方文档描述的一句话:Load bean definitions from the specified resource中可见一斑。

  /**
     * Load bean definitions from the specified resource.
     * @param resource the resource descriptor
     * @return the number of bean definitions found
     * @throws BeanDefinitionStoreException in case of loading or parsing errors
     */
    int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException;

  总之,BeanDefinition相当于一个数据结构,这个数据结构的生成过程是根据定位的resource资源对象中的bean而来的,这些bean在Spirng IoC容器内部表示成了的BeanDefintion这样的数据结构,IoC容器对bean的管理和依赖注入的实现都是通过操作BeanDefinition来进行的。

2.如何将BeanDefinition载入到容器?
  在Spring中,配置文件主要格式是XML,对于用来读取XML型资源文件来进行初始化的IoC 容器而言,该类容器会使用到AbstractXmlApplicationContext类,该类定义了一个名为loadBeanDefinitions(DefaultListableBeanFactory beanFactory) 的方法用于获取BeanDefinition,此方法在具体执行过程中首先会new一个与容器对应的BeanDefinitionReader型实例对象,然后将生成的BeanDefintionReader实例作为参数,传入loadBeanDefintions(XmlBeanDefinitionReader)继续往下执行载入BeanDefintion的过程。例如FileSystemXmlApplicationContext容器会在此方法中new一个XmlBeanDefinitionReader对象,这个对象专门用来载入所有的BeanDefinition。下面以XmlBeanDefinitionReader对象载入BeanDefinition为例,使用源码说明载入BeanDefinition的过程:

//该方法属于AbstractXmlApplicationContect类中的一个方法protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
        Resource[] configResources = getConfigResources();//获取所有定位到的resource资源位置
        if (configResources != null) {
            reader.loadBeanDefinitions(configResources);//载入BeanDefinitions
        }
        String[] configLocations = getConfigLocations();//获取所有配置文件的位置
        if (configLocations != null) {
            reader.loadBeanDefinitions(configLocations);//载入BeanDefinitions
        }
    }

通过上面代码中的reader.loadBeanDefinitions(configLocations)访问到AbstractBeanDefinitionReader类中的方法具体定义如下:

public int loadBeanDefinitions(Resource[] resources) throws BeanDefinitionStoreException {
        Assert.notNull(resources, "Resource array must not be null");
        int counter = 0;
        for (int i = 0; i < resources.length; i++) {
            counter += loadBeanDefinitions(resources[i]);//该方法的在AbstractBeanDefinitionReader中并没有实现,仍然预留                                 //但在XmlBeanDefinitionReader中实现了
        }
        return counter;
    }

XmlBeanDefinitionReader类实现了BeanDefinitionReader接口中的loadBeanDefinitions(Resource)方法,XmlBeanDefinitionReader类中几个方法的源码:

 //XmlBeanDefinitionReader 继承于 AbstractBeanDefinitionReader  //AbstractBeanDefinitionReader implements BeanDefinitionReader 

  public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
        return loadBeanDefinitions(new EncodedResource(resource));
    }

    /**
     * Load bean definitions from the specified XML file.*/
    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        Assert.notNull(encodedResource, "EncodedResource must not be null");
        if (logger.isInfoEnabled()) {
            logger.info("Loading XML bean definitions from " + encodedResource.getResource());
        }

        try {       //通过resource对象得到XML文件,并为IO的InputSource做准备
            InputStream inputStream = encodedResource.getResource().getInputStream();
            try {          // Create a new input source with a byte stream.
                InputSource inputSource = new InputSource(inputStream);if (encodedResource.getEncoding() != null) {
                    inputSource.setEncoding(encodedResource.getEncoding());
                }         //开始准备 load bean definitions from the specified XML file
                return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
            }
            finally {
                inputStream.close();
            }
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException(
                    "IOException parsing XML document from " + encodedResource.getResource(), ex);
        }
    }

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {
        try {
            int validationMode = getValidationModeForResource(resource);//获取指定资源的验证模式

       // 从资源对象中加载DocumentL对象,大致过程为:将resource资源文件的内容读入到document中       // DocumentLoader在容器读取XML文件过程中有着举足轻重的作用!       // XmlBeanDefinitionReader实例化时会创建一个DefaultDocumentLoader型的私有属性,继而调用loadDocument方法            // inputSource--要加载的文档的输入源
            Document doc = this.documentLoader.loadDocument(
                    inputSource, this.entityResolver, this.errorHandler, validationMode, this.namespaceAware);       
            return registerBeanDefinitions(doc, resource);//将document文件的bean封装成BeanDefinition,并注册到容器
        }
        catch ...(略)
    }

DefaultDocumentLoader大致了解即可,感兴趣可继续深究,其源码如下:

/* Simply loads documents using the standard JAXP-configured XML parser. */

public class DefaultDocumentLoader implements DocumentLoader {
  //JAXP解析XML的三种基本接口为:文档型的DOM接口,简单型的SAX接口以及XML流接口
    private static final String SCHEMA_LANGUAGE_ATTRIBUTE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
    private static final String XSD_SCHEMA_LANGUAGE = "http://www.w3.org/2001/XMLSchema";
    protected final Log logger = LogFactory.getLog(getClass());

    public Document loadDocument(
            InputSource inputSource, EntityResolver entityResolver,
            ErrorHandler errorHandler, int validationMode, boolean namespaceAware)
            throws Exception {
     //创建DocumentBuilder工场
        DocumentBuilderFactory factory =
                        createDocumentBuilderFactory(validationMode, namespaceAware);
        if (logger.isDebugEnabled()) {
            logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
        }     // DOM解析器被称作DocumentBuilder,通过工场的方式获取DocumentBuilder实例对象
        DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
        return builder.parse(inputSource);//把文件或解析流转化成Document对象
    }

    protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware)
                    throws ParserConfigurationException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(namespaceAware);

        if (validationMode != XmlBeanDefinitionReader.VALIDATION_NONE) {
            factory.setValidating(true);        //是否使用jaxp接口提供的XML Schema验证
            if (validationMode == XmlBeanDefinitionReader.VALIDATION_XSD) {
                factory.setNamespaceAware(true);
                try {
                    factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE);
                }
                catch (IllegalArgumentException ex) {
                    throw new BeanDefinitionStoreException(
                            "Unable to validate using XSD: Your JAXP provider [" + factory +
                            "] does not support XML Schema. Are you running on Java 1.4 or below with " +
                            "Apache Crimson? Upgrade to Apache Xerces (or Java 1.5) for full XSD support.");
                }
            }
        }
        return factory;
    }

    protected DocumentBuilder createDocumentBuilder(
            DocumentBuilderFactory factory, EntityResolver entityResolver, ErrorHandler errorHandler)
            throws ParserConfigurationException {

        DocumentBuilder docBuilder = factory.newDocumentBuilder();
        if (errorHandler != null) {
            docBuilder.setErrorHandler(errorHandler);
        }
        if (entityResolver != null) {
            docBuilder.setEntityResolver(entityResolver);
        }
        return docBuilder;
    }

}

上面代码分析到了registerBeanDefinitions(doc, resource)这一步,也就是准备将Document中的Bean按照Spring bean语义进行解析并转化为BeanDefinition类型,这个方法的具体过程如下:

//该方法属于XmlBeanDefinitionReader类,返回找到的bean definition的总数量public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        // 为后向兼容性支持老版本XmlBeanDefinitionParser SPI.
        if (this.parserClass != null) {
            XmlBeanDefinitionParser parser =
                    (XmlBeanDefinitionParser) BeanUtils.instantiateClass(this.parserClass);
            return parser.registerBeanDefinitions(this, doc, resource);
        }
        // 基于新的BeanDefinitionDocumentReader SPI版本读取document.
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();//该过程会获取到DefaultBeanDefinitionDocumentReader实例
        int countBefore = getBeanFactory().getBeanDefinitionCount();//获取容器中bean的数量
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
        return getBeanFactory().getBeanDefinitionCount() - countBefore;
    }

通过XmlBeanDefinitionReader类中的私有属性private Class documentReaderClass = DefaultBeanDefinitionDocumentReader.class 以及createBeanDefinitionDocumentReader() 方法可以获得一个DefaultBeanDefinitionDocumentReader实例对象,这个实例对象的registerBeanDefinitions方法定义如下:

//DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReaderpublic void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
        this.readerContext = readerContext;

        logger.debug("Loading bean definitions");     //获取root节点,通过该节点能够访问所有的子节点
        Element root = doc.getDocumentElement();
     //处理beanDefinition的过程委托给BeanDefinitionParserDelegate实例对象来完成
        BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
     // Default implementation is empty.        // Subclasses can override this method to convert custom elements into standard Spring bean definitions
        preProcessXml(root);
        parseBeanDefinitions(root, delegate);
        postProcessXml(root);
    }

上面出现的BeanDefinitionParserDelegate类非常非常重要,Spirng BeanDefinition的解析就是在这个类下完成的,此类包含了各种对符合Spring Bean语义规则的处理,比如<bean></bean>、<import></import>、<alias><alias/>等的检测。parseBeanDefinitions(root, delegate)方法如下:

    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {
            NodeList nl = root.getChildNodes();       // 遍历所有节点,做对应解析工作,如遍历到<import>标签节点就调用importBeanDefinitionResource(ele)方法对应处理
            // 遍历到<bean>标签就调用processBeanDefinition(ele,delegate)方法对应处理       for (int i = 0; i < nl.getLength(); i++) {
                Node node = nl.item(i);
                if (node instanceof Element) {
                    Element ele = (Element) node;
                    if (delegate.isDefaultNamespace(ele)) {
                        parseDefaultElement(ele, delegate);
                    }
                    else {
                        delegate.parseCustomElement(ele); //对应用户自定义节点处理方法
                    }
                }
            }
        }
        else {
            delegate.parseCustomElement(root);
        }
    }

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {     //解析<import>标签
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
            importBeanDefinitionResource(ele);
        }     //解析<alias>标签
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
            processAliasRegistration(ele);
        }     //解析<bean>标签,最常用,过程最复杂
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
            processBeanDefinition(ele, delegate);
        }     //解析<beans>标签
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
            // recurse
            doRegisterBeanDefinitions(ele);
        }
    }

这里针对常用的<bean>标签中的方法做简单介绍,其他标签的加载方式类似:

  /** Process the given bean element, parsing the bean definition and registering it with the registry.   */
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {    //该对象持有beanDefinition的name和alias,可以使用该对象完成beanDefinition向容器的注册
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
            try {
                //注册最终被修饰的bean实例
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
            }
            catch (BeanDefinitionStoreException ex) {
                getReaderContext().error("Failed to register bean definition with name ‘" +
                        bdHolder.getBeanName() + "‘", ele, ex);
            }
            // Send registration event.
            getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
    }

这里public BeanDefinitionHolder parseBeanDefinitionElement(Element ele)方法会调用parseBeanDefinitionElement(ele, null)方法并将值返回,这个方法将会对给定的<bean>标签进行解析,如果在解析<bean>标签的过程中出现错误则返回空值,需要强调一下的是在该方法中产生了一个抽象类型的BeanDefinition实例,这也是我们首次看到直接定义BeanDefinition的地方,parseBeanDefinitionElement(ele, null)方法会产生一个BeanDefinition对象,并将<bean>标签中的内容解析到BeanDefinition中,之后再将BeanDefinition与beanName,Alias等封装到BeanDefinitionHolder 对象中,该部分源码如下:

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
        String id = ele.getAttribute(ID_ATTRIBUTE);
        String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
          ...
        String beanName = id;         ...     // 从上面按过程走来,首次看到直接定义BeanDefinition !!!     // 该方法会对<bean>节点以及所有子节点如<property>、<List>、<Set>等做出解析,具体过程本文不做分析(太多太长)
        AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
        if (beanDefinition != null) {
           ....
            }
            String[] aliasesArray = StringUtils.toStringArray(aliases);
            return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
        }

        return null;
    }
  • 第三步,将BeanDefiniton注册到容器中

  最终Bean配置会被解析成BeanDefinition并与beanName,Alias一同封装到BeanDefinitionHolder中,之后beanFactory.registerBeanDefinition(beanName, bdHolder.getBeanDefinition()),注册到DefaultListableBeanFactory.beanDefinitionMap中。之后客户端如果要获取Bean对象,XmlBeanFactory会根据注册的BeanDefinition信息进行实例化。

BeanDefinitionReaderUtils类:

public static void registerBeanDefinition(
            BeanDefinitionHolder bdHolder, BeanDefinitionRegistry beanFactory) throws BeansException {

        // Register bean definition under primary name.
        String beanName = bdHolder.getBeanName();     // 注册beanDefinition!!!
        beanFactory.registerBeanDefinition(beanName, bdHolder.getBeanDefinition());

        // Register aliases for bean name, if any.
        String[] aliases = bdHolder.getAliases();
        if (aliases != null) {
            for (int i = 0; i < aliases.length; i++) {
                beanFactory.registerAlias(beanName, aliases[i]);
            }
        }
    }

上面调用BeanDefinitionRegistry接口实例获得的beanFactory对象是由DefaultBeanDefinitionRegistry.registerBeanDefinition(beanName, bdHolder.getBeanDefinition())获得,具体方法如下:

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException {

        Assert.hasText(beanName, "Bean name must not be empty");
        Assert.notNull(beanDefinition, "Bean definition must not be null");

        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
                ((AbstractBeanDefinition) beanDefinition).validate();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Validation of bean definition failed", ex);
            }
        }
         //beanDefinitionMap是个HashMap类型数据,用于存放beanDefinition,它的key值是beanName
        Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
        if (oldBeanDefinition != null) {
            if (!this.allowBeanDefinitionOverriding) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Cannot register bean definition [" + beanDefinition + "] for bean ‘" + beanName +
                        "‘: there‘s already [" + oldBeanDefinition + "] bound");
            }
            else {
                if (logger.isInfoEnabled()) {
                    logger.info("Overriding bean definition for bean ‘" + beanName +
                            "‘: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
                }
            }
        }
        else {
            this.beanDefinitionNames.add(beanName);
        }     // 将获取到的BeanDefinition放入HashMap中,容器操作使用bean时通过这个HashMap找到具体的BeanDefinition
        this.beanDefinitionMap.put(beanName, beanDefinition);// Remove corresponding bean from singleton cache, if any.
        // Shouldn‘t usually be necessary, rather just meant for overriding
        // a context‘s default beans (e.g. the default StaticMessageSource
        // in a StaticApplicationContext).
        removeSingleton(beanName);
    }

   本文可看做本人看书笔记学习,其中大部分参考《Spirng技术内幕:深入解析Spring架构与设计原理》以及结合网上博客等仓促而作,作此文只希望自己的技术不断提高,同时记录自己学习过程中的点点滴滴,其中肯定有许多不足之处,望谅解与指出。

时间: 2024-10-05 21:50:44

Spring IoC容器初始化过程的相关文章

Spring IOC的初始化过程——基于XML配置(一)

前言:在面试过程中,Spring IOC的初始化过程,基本上属于必答题,笔者的亲身经历.因此本文基于Spring的源码对其IOC的初始化过程进行总结. 注:spring版本为4.3.0. 1.调试前准备 在spring源码中,添加如下内容(有关spring源码如何导入idea,请查询相关资料): 说明: ①User为简单bean,含有name和gender两个属性. ②User.xml为spring配置文件,仅仅对User进行简单的配置. ③SpringIoCDebug为测试类. 先看执行结果:

03.Spring IoC 容器 - 初始化

基本概念 Spring IoC 容器的初始化过程在监听器 ContextLoaderListener 类中定义. 具体由该类的的 configureAndRefreshWebApplicationContext 方法实现,它包含了两个过程: 配置过程 刷新过程 原理分析 下面来看 configureAndRefreshWebApplicationContext 方法的具体实现: // 表示容器的标识 public static final String CONTEXT_ID_PARAM = "c

Spring之IOC容器初始化过程

Ioc容器的初始化是由refresh()方法来启动的,这个方法标志着Ioc容器的正式启动. 具体来说这个启动过程包括三个基本过程: 1.BeanDifinition的Resource定位 2.BeanDifinition的载入与解析 3.BeanDifinition在Ioc容器中的注册 需要注意的是,Spring把这三个过程分开,并使用不同的模块来完成,如使用相应的ResourceLoader.BeanDifinitionReader等模块,通过这样的实际方式,可以让用户更加灵活的对这三个过程进

Spring Boot IoC 容器初始化过程

1. 加载 ApplicationContextInializer & ApplicationListener 2. 初始化环境 ConfigurableEnvironment & 加载配置文件 3. 构建应用上下文 ApplicationContext 4. 注册源文件 source 5. 通过 ApplicationListener 注册 BeanFactoryPostProcessor 6. 初始化 BeanFactoryPostProcessor 到 IoC 容器 7. 通过 Be

springmvc web.xml配置之SpringMVC IOC容器初始化

SpringMVC IOC容器初始化 首先强调一下SpringMVC IOC容器初始化有些特别,在SpringMVC中除了生成一个全局的spring Ioc容器外,还会为DispatcherServlet生成一个容器,具体的下一篇有讲述. 我们知道spring中单纯使用main函数就可以生成一个容器,如下: public class MainTest { public static void main(String[] args){ ApplicationContext appContext =

【spring源码分析】IOC容器初始化(一)

前言:spring主要就是对bean进行管理,因此IOC容器的初始化过程非常重要,搞清楚其原理不管在实际生产或面试过程中都十分的有用.在[spring源码分析]准备工作中已经搭建好spring的环境,并利用xml配置形式对类进行了实例化.在test代码中有一个非常关键的类ClassPathXmlApplicationContext,在这个类中实现了IOC容器的初始化,因此我们从ClassPathXmlApplicationContext入手开始研究IOC的初始化过程. 1.ClassPathXm

IOC容器初始化

参考:https://www.cnblogs.com/ITtangtang/p/3978349.html 一.Ioc/DI 控制反转,把原先代码里需要实现的对象的创建.依赖的代交给容器帮忙实现.所以需要创建一个容器,同时需要一种描述让容器知道需要创建的对象与对象之间的关系. 对象与对象之间的关系通过 xml, properties 文件等语义化配置文件表示.文件存放位置:类路径,文件系统,URL,servletContext等. 不同的配置文件对对象的描述不一样,所以内部需要一个统一的关于对象的

详解Spring IoC容器

一.Spring IoC容器概述 1.依赖反转(依赖注入):依赖对象的获得被反转了. 如果合作对象的引用或依赖关系的管理由具体对象来完成,会导致代码的高度耦合和可测试性的降低,这对复杂的面向对象系统的设计是非常不利的. 在Spring中,IoC容器是实现依赖控制反转这个模式的载体,它可以在对象生成或者初始化时直接将数据注入到对象中,也可以通过将对象引用注入到对象数据域中的方式来注入对方法调用的依赖.这种依赖是可以递归的,对象被逐层注入. 关于如何反转对依赖的控制,把控制权从具体业务对象中转交到平

Spring IoC容器的初始化过程

Spring IoC容器的初始化包括 BeanDefinition的Resource定位.载入和注册 这三个基本的过程.IoC容器的初始化过程不包含Bean依赖注入的实现.Bean依赖的注入一般会发生在第一次通过getBean向容器索取Bean的时候. 先看以下代码: ApplicationContext context = new ClassPathXmlApplicationContext("ioc.xml"); Car car = (Car) context.getBean(&q