Spring配置文件解析(一)ClassPathXmlApplicationContext源码分析

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取 2000+ 道 Java 面试题

1 概述

针对前面的SpringIOC的源码分析,我们看见了在整个Spring容器初始化的时候,配置文件的解析是相当重要的,所以从这篇文章开始,我们将对配置文件的解析进行深入的分析。
这里我们仅仅拿ClassPathXmlApplicationContext类来进行分析,因为FileSystemXmlApplicationContext的配置文件解析的过程和ClassPathXmlApplicationContext是相同的。

2 详细分析

在我们的测试当中使用到了如下的代码。

    ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring_test.xml");
    Animal animal = (Animal) ctx.getBean("animal");
    animal.eat();

这里调用了ClassPathXmlApplicationContext类的构造函数。

    public ClassPathXmlApplicationContext(String configLocation) throws BeansException {

            //这里支持自动刷新Spring容器
        this(new String[] {configLocation}, true, null);
    }

而在这个构造函数中又调用了下面这个构造函数。

    public ClassPathXmlApplicationContext(
            String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
            throws BeansException {

        super(parent);

        //设置配置文件地址
        setConfigLocations(configLocations);
        if (refresh) {

            //刷新容器,至此,我们可以猜想配置文件的加载其实是在这个函数里面实现的。
            refresh();
        }
    }

那么refresh()函数中又干了什么呢?针对refresh函数我们前面已经分析过,其实这里只需要关注下面这行代码就行了,

    public void refresh() throws BeansException, IllegalStateException {
        ... ...

        //告述子类刷新内部bean工厂
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        ... ...
    }

刷新bean工厂后返回,然后再对bean工厂进行其余的处理。

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {

        //这是一个抽象函数,具体实现留给子类
        refreshBeanFactory();

        //这里的getBeanFactory也是一个抽象函数
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }

上面的代码,我们可以猜想getBeanFactory函数返回的就是refreshBeanFactory刷新的Bean工厂。下面我们继续来看refreshBeanFactory函数的源码。

    protected final void refreshBeanFactory() throws BeansException {

        //有bean工厂
        if (hasBeanFactory()) {

        //这里其实就是删除了所有单列bean(其实就是置空了和bean相关的缓存)。
        destroyBeans();

        //这里其实就是将bean工厂设置成了null
        closeBeanFactory();
        }
        try {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);

        //真正的加载配置文件是在这一步完成的
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
        }
        catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

接下来继续看loadBeanDefinitions(beanFactory);这一步的源码。

    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
        initBeanDefinitionReader(beanDefinitionReader);
        loadBeanDefinitions(beanDefinitionReader);
    }

上面的函数其实是生成XmlBeanDefinitionReader对象后调用了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。
简单来说在ApplicationContext中所做的操作是初始化了一个BeanFactory和XmlBeanDefinitionReader,针对XmlBeanDefinitionReader这个类的分析,我们接下来会继续,欢迎交流!


来源:http://ddrv.cn/a/88268

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Spring配置文件解析(一)ClassPathXmlApplicationContext源码分析

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏