spring-BeanDefinition流程源码分析

找入口

AbstractRefreshableApplicationContext类的refreshBeanFactory方法中第13行代码:

protected final void refreshBeanFactory() throws BeansException {
        // 如果之前有IoC容器,则销毁
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            // 创建IoC容器,也就是DefaultListableBeanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            // 加载BeanDefinition对象,并注册到IoC容器中(重点)
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

流程解析

  • 进入AbstractXmlApplicationContext的loadBeanDefinitions方法:
    • 创建一个XmlBeanDefinitionReader,通过阅读XML文件,真正完成BeanDefinition的加载和注册。
    • 配置XmlBeanDefinitionReader并进行初始化。
    • 委托给XmlBeanDefinitionReader去加载BeanDefinition。
 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) 
                                                throws BeansException, IOException {
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        // 创建一个BeanDefinition阅读器,通过阅读XML文件,真正完成BeanDefinition的加载和注册
        XmlBeanDefinitionReader beanDefinitionReader = new 
                                            XmlBeanDefinitionReader(beanFactory);

        // 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);
        // 委托给BeanDefinition阅读器去加载BeanDefinition
        loadBeanDefinitions(beanDefinitionReader);
    }

    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws 
                                                    BeansException, IOException {
        // 获取资源的定位
        // 这里getConfigResources是一个空实现,真正实现是调用子类的获取资源定位的方法
        // 比如:ClassPathXmlApplicationContext中进行了实现
        //      而FileSystemXmlApplicationContext没有使用该方法
        Resource[] configResources = getConfigResources();
        if (configResources != null) {
            // XML Bean读取器调用其父类AbstractBeanDefinitionReader读取定位的资源
            reader.loadBeanDefinitions(configResources);
        }
        // 如果子类中获取的资源定位为空,则获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源
        String[] configLocations = getConfigLocations();
        if (configLocations != null) {
            // XML Bean读取器调用其父类AbstractBeanDefinitionReader读取定位的资源
            reader.loadBeanDefinitions(configLocations);
        }
    }
  • loadBeanDefinitions方法经过一路的兜兜转转,最终来到了XmlBeanDefinitionReaderdoLoadBeanDefinitions方法:
    • 一个是对XML文件进行DOM解析;
    • 一个是完成BeanDefinition对象的加载与注册
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {
        try {
            // 通过DOM4J加载解析XML文件,最终形成Document对象
            Document doc = doLoadDocument(inputSource, resource);
            // 通过对Document对象的操作,完成BeanDefinition的加载和注册工作
            return registerBeanDefinitions(doc, resource);
        }
        //省略一些catch语句
        catch (Throwable ex) {
            ......
        }
    }
  • 此处我们暂不处理DOM4J加载解析XML的流程,我们重点分析BeanDefinition的加载注册流程
  • 进入XmlBeanDefinitionReaderregisterBeanDefinitions方法:
    • 创建DefaultBeanDefinitionDocumentReader用来解析Document对象。
    • 获得容器中已注册的BeanDefinition数量
    • 委托给DefaultBeanDefinitionDocumentReader来完成BeanDefinition的加载、注册工作。
    • 统计新注册的BeanDefinition数量
public int registerBeanDefinitions(Document doc, Resource resource) throws 
                                        BeanDefinitionStoreException {
        // 创建DefaultBeanDefinitionDocumentReader用来解析Document对象
        BeanDefinitionDocumentReader documentReader = 
                                    createBeanDefinitionDocumentReader();
        // 获得容器中注册的Bean数量
        int countBefore = getRegistry().getBeanDefinitionCount();
        //解析过程入口,BeanDefinitionDocumentReader只是个接口
        //具体的实现过程在DefaultBeanDefinitionDocumentReader完成
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
        // 统计注册的Bean数量
        return getRegistry().getBeanDefinitionCount() - countBefore;
    }
  • 进入DefaultBeanDefinitionDocumentReaderregisterBeanDefinitions方法:
    • 获得Document的根元素标签
    • 真正实现BeanDefinition解析和注册工作
 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext
    {
        this.readerContext = readerContext;
        logger.debug("Loading bean definitions");
        // 获得Document的根元素<beans>标签
        Element root = doc.getDocumentElement();
        // 真正实现BeanDefinition解析和注册工作
        doRegisterBeanDefinitions(root);
    }
  • 进入DefaultBeanDefinitionDocumentReaderdoRegisterBeanDefinitions方法:
    • 这里使用了委托模式,将具体的BeanDefinition解析工作交给了BeanDefinitionParserDelegate去完成
    • 在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性
    • 委托给BeanDefinitionParserDelegate,从Document的根元素开始进行BeanDefinition的解析
    • 在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性
 protected void doRegisterBeanDefinitions(Element root) {
        // Any nested <beans> elements will cause recursion in this method. In
        // order to propagate and preserve <beans> default-* attributes correctly,
        // keep track of the current (parent) delegate, which may be null. Create
        // the new (child) delegate with a reference to the parent for fallback purposes,
        // then ultimately reset this.delegate back to its original (parent) reference.
        // this behavior emulates a stack of delegates without actually necessitating one.
        
        // 这里使用了委托模式,将具体的BeanDefinition解析工作交给了BeanDefinitionParserDelegate去完成
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = createDelegate(getReaderContext(), root, parent);

        if (this.delegate.isDefaultNamespace(root)) {
            String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
            if (StringUtils.hasText(profileSpec)) {
                String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                        profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
                if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                                "] not matching: " + getReaderContext().getResource());
                    }
                    return;
                }
            }
        }
        // 在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性
        preProcessXml(root);
        // 委托给BeanDefinitionParserDelegate,从Document的根元素开始进行BeanDefinition的解析
        parseBeanDefinitions(root, this.delegate);
        // 在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性
        postProcessXml(root);

        this.delegate = parent;
    }

 

posted @ 2017-11-25 20:55  Emyin  阅读(503)  评论(0编辑  收藏  举报