Spring核心IOC源码解读(一)获取BeanFactory

  在 AbstractApplicationContext.refresh(); 的过程中,第二步为获取BeanFactory -> obtainFreshBeanFactory()。在这个方法中,Spring先创建了BeanFactory,然后通过读取XML配置文件(或者扫描Java类)的方式初始化了BeanDefinition。这里面就包括Spring Bean的主要信息,例如依赖情况、作用域等等。

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // (1)Prepare this context for refreshing.
            prepareRefresh();

            // (2)Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            ......
    }    

一、 obtainFreshBeanFactory() 方法的具体内容

    /**
     * Tell the subclass to refresh the internal bean factory.
     * @return the fresh BeanFactory instance
     * @see #refreshBeanFactory()
     * @see #getBeanFactory()
     */
    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();
        return getBeanFactory();
    }

  注释上写的:告诉子类刷新内部的BeanFactory

    protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

   refreshBeanFactory() 、 getBeanFactory() 方法是抽象方法,由子类实现,这里的子类是 AbstractRefreshableApplicationContext ,它是 AbstractApplicationContext 的子类。(类图可以参考:大纲

二、关键在于 refreshBeanFactory() 方法

  看看 AbstractRefreshableApplicationContext 的实现:

    @Override
    protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
        //(1)初始化BeanFactory DefaultListableBeanFactory beanFactory
= createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory);
        //(2)读取BeanFefinition loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }

(1)  AbstractRefreshableApplicationContext.createBeanFactory() 

  创建 DefaultListableBeanFactory 对象,这个对象的类图关系如下

 

 

   不仅实现了BeanFactory,还实现了Registry相关接口,意味着和Bean的注册有很大关系

(2)  AbstractRefreshableApplicationContext.loadBeanDefinitions() 

   loadBeanDefinitions() 是一个抽象方法,由 AbstractXmlApplicationContext 实现,类图可参考:大纲

    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // (1)创建读取Xml的对象,和BeanFactory是依赖关系
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        // (2)这些都是一些初始化操作
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        // (3)真正的初始化操作发生在最后一步loadBeanDefinitions
        initBeanDefinitionReader(beanDefinitionReader);
        loadBeanDefinitions(beanDefinitionReader);
    }

   XmlBeanDefinitionReader 初始化的 beanFactory 对象是 BeanDefinitionRegistry 接口的实现

    public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
        super(registry);
    }

三、 loadBeanDefinitions(beanDefinitionReader); 通过Reader将XML Bean信息读取到BeanFactory中

  BeanFactory和Reader之间的关系是依赖关系

    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);
        }
    }

   reader.loadBeanDefinitions(configLocations) 方法中,将String类型的xml文件地址转为了Resource对象,下面就是通过流来读取👇

    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        ....

        try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
        }
        ....
    }

  层层抽丝剥茧之后,走到了 DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root); 中

    protected void doRegisterBeanDefinitions(Element root) {
        ...
        preProcessXml(root);
        //核心步骤
        parseBeanDefinitions(root, this.delegate);
        postProcessXml(root);

        this.delegate = parent;
        ...
    }

四、看看 DefaultBeanDefinitionDocumentReader 是如何解析Bean的

    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        //(1)将XML文件中类名、别名、属性值初始化到了BeanDefinition中,并初始化一些默认值,并依赖到了Holder对象中
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        //(2)装饰
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        //(3)这一步的操作就是将BeanDefinition放入DefaultListableBeanFactory对象的beanDefinitionMap属性中
        BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
    
        ...
        }
    }

  最重要的就是第一步将BeanDefinition初始化之后,第三步放入beanDefinitionMap中

 

posted on 2020-09-23 13:43  lyjlyjlyj  阅读(281)  评论(0编辑  收藏  举报

导航