美文网首页
Spring IOC容器初始化

Spring IOC容器初始化

作者: liu_c02c | 来源:发表于2018-07-04 21:20 被阅读0次

    IOC容器的初始化-一

    1、定位:

    定位,就是获取到配置文件从而获取到资源,即通过资源文件路径定位到具体的资源;Srping内部用Resource接口来定位资源,用户输入资源路径,然后通过ResourceLoader根据输入的资源路径返回对应的Resource

    2、加载:

    加载,就是将资源文件加载到内存中,形成一个具体的对象,最初是通过reader形成一个Document对象,然后再逐渐深入解析最终成为BeanDefinition(这个就是最终描述xml配置文件的对象)

    3、注册:

    IOC容器中的beanefition加载到map的过程中,就是注册的过程

    接下来跟随代码逐步解析IOC容器初始化过程:

     ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:applicationContext.xml");
    

    调用ClassPathXmlApplicationContext的构造方法:

    public ClassPathXmlApplicationContext(
                String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
                throws BeansException {
            /**
             *调用父类构造方法,获取资源位置解析器Resolver==》PathMatchingResourcePatternResolver
             */
            super(parent);
            /**
             * 设置资源路径
             */
            setConfigLocations(configLocations);
            /**
             * 刷新容器
             */
            if (refresh) {
                refresh();
            }
    }
    

    重点关注refresh()方法,这里是IOC初始化的入口

    由AbstractApplicationContext的refresh()完成,部分代码用伪代码做处理:

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        //进行容器初始化前的一些准备
        
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        
        //容器初始化后的一些准备
    
    }
        
    /**
     * 这里refreshBeanFactory委托给子类,于是跳到子类的refreshBeanFactory
     * @return the fresh BeanFactory instance
     * @see #refreshBeanFactory()
     * @see #getBeanFactory()
     */
    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }
    

    于是,实际上刷新容器的任务委托到了AbstractRefreshableApplicationContext的refreshBeanFactory()

    @Override
    protected final void refreshBeanFactory() throws BeansException {
        //将原来bean销毁并关闭原有的beanFactory
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            DefaultListableBeanFactory beanFactory = createBeanFactory();//由这里可得,DefaultListableBeanFactory才是真正干活的bean工厂
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            loadBeanDefinitions(beanFactory);//bean加载入口,这里也是使用了委托模式,由子类实现
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " +         getDisplayName(), ex);
    }
    

    于是,加载的任务委托给了AbstractXmlApplicationContext的loadBeanDefinitions

    /**
     * Loads the bean definitions via an XmlBeanDefinitionReader.
     * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
     * @see #initBeanDefinitionReader
     * @see #loadBeanDefinitions
     */
    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
       // Create a new XmlBeanDefinitionReader for the given BeanFactory.
       XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);//这里可以看出,XmlBeanDefinitionReader负责bean配置的加载
    
       // Configure the bean definition reader with this context's
       // resource loading environment.
       beanDefinitionReader.setEnvironment(this.getEnvironment());
       beanDefinitionReader.setResourceLoader(this);
       beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    
       // Allow a subclass to provide custom initialization of the reader,
       // then proceed with actually loading the bean definitions.
       initBeanDefinitionReader(beanDefinitionReader);
       loadBeanDefinitions(beanDefinitionReader);
    }
    
    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
            Resource[] configResources = getConfigResources();
            if (configResources != null) {
                reader.loadBeanDefinitions(configResources);
            }
            String[] configLocations = getConfigLocations();
            if (configLocations != null) {
                reader.loadBeanDefinitions(configLocations);//从这里可以看出,加载的任务交由XmlBeanDefinitionReader完成
            }
    }
    

    这里XmlBeanDefinitionReader的loadBeanDefinitions继续委托给了AbstractBeanDefinitionReader.loadBeanDefinitions

    public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
       ResourceLoader resourceLoader = getResourceLoader();//获取ResourceLoader,将资源文件路径转化为Resource
       //进行相应的判断,省略了部分代码。。。
       Resource resource = resourceLoader.getResource(location);
       int loadCount = loadBeanDefinitions(resource);
       return loadCount;
     }
    

    将loadBeanDefinitions继续委托给XmlBeanDefinitionReader

    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        //关键代码
        InputStream inputStream = encodedResource.getResource().getInputStream();
        try {
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
        }
        finally {
            inputStream.close();
        }
    }
    

    在spring的设计中,do开头的方法一般就是真正做事的方法,进行doLoadBeanDefinitions

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
          throws BeanDefinitionStoreException {
        //关键代码
         Document doc = doLoadDocument(inputSource, resource);//将resource转为dom对象
         return registerBeanDefinitions(doc, resource);
    }
    
    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
        int countBefore = getRegistry().getBeanDefinitionCount();
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));//BeanDefinitionDocumentReader对dom进行解析加载,该类将解析加载的任务委托给DefaultBeanDefinitionDocumentReader
        return getRegistry().getBeanDefinitionCount() - countBefore;
    }
    

    因此,见DefaultBeanDefinitionDocumentReader的registerBeanDefinitions

    @Override
    public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
       this.readerContext = readerContext;
       logger.debug("Loading bean definitions");
       Element root = doc.getDocumentElement();
       doRegisterBeanDefinitions(root);
    }
    
    /**
     * Register each bean definition within the given root {@code <beans/>} element.
     */
    protected void doRegisterBeanDefinitions(Element root) {
        //关键代码
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = createDelegate(getReaderContext(), root, parent);
        preProcessXml(root);
        parseBeanDefinitions(root, this.delegate);
        postProcessXml(root);
    
        this.delegate = parent;
    }
    
    /**
     * Parse the elements at the root level in the document:
     * "import", "alias", "bean".
     * @param root the DOM root element of the document
     */
    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {
            NodeList nl = root.getChildNodes();
            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);//循环遍历解析dom对象
                    }
                    else {
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
        else {
            delegate.parseCustomElement(root);
        }
    }
    
    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
            importBeanDefinitionResource(ele);
        }
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
            processAliasRegistration(ele);
        }
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
            processBeanDefinition(ele, delegate);//解析bean,由BeanDefinitionParserDelegate执行
        }
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
            // recurse
            doRegisterBeanDefinitions(ele);
        }
    }
    

    拿bean解析来看,解析之后由BeanDefinitionReaderUtils.registerBeanDefinition进行注册

    /**
     * Process the given bean element, parsing the bean definition
     * and registering it with the registry.
     */
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
       BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
       if (bdHolder != null) {
          bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
          try {
             // Register the final decorated instance.
             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));
       }
    }
    

    BeanDefinitionReaderUtils.registerBeanDefinition

    /**
     * Register the given bean definition with the given bean factory.
     * @param definitionHolder the bean definition including name and aliases
     * @param registry the bean factory to register with
     * @throws BeanDefinitionStoreException if registration failed
     */
    public static void registerBeanDefinition(
          BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
          throws BeanDefinitionStoreException {
    
       // Register bean definition under primary name.
       String beanName = definitionHolder.getBeanName();
       registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    
       // Register aliases for bean name, if any.
       String[] aliases = definitionHolder.getAliases();
       if (aliases != null) {
          for (String alias : aliases) {
             registry.registerAlias(beanName, alias);
          }
       }
    }
    

    由DefaultListableBeanFactory来进行注册

    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
          throws BeanDefinitionStoreException {
        //关键代码
        this.beanDefinitionMap.put(beanName, beanDefinition);//注册,由beneDefinitionMap做容器进行存储
    }
    

    相关文章

      网友评论

          本文标题:Spring IOC容器初始化

          本文链接:https://www.haomeiwen.com/subject/bnvyuftx.html