【spring源码分析】之启动

spring应该是java中最常用的开源框架,引入spring可以降到应用开发的复杂性。平常大家更关注于spring的应用,本文就和各位一起来分析一下spring的源码。

spring发展到今天,已然是个十分庞大的框架,往往不知从何处下手,本文就从spring的加载过程入手。

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        applicationContext.getBean("name");

上面这段简单的代码就是spring的启动方式之一,通过对于ClassPathXmlApplicationContext的实例化就可以完成spring的加载过程。先给出ClassPathXmlApplicationContext的继承关系图,诸如spring的框架,结构都较复杂,列一下继承的关系,对于我们的理解很有帮助,图如下:
《【spring源码分析】之启动》

ClassPathXmlApplicationContext的构造函数

    public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[] {configLocation}, true, null);
    }
    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
            throws BeansException {

        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
            refresh();
        }
    }

构造函数的功能:加载指定的xml文件并且刷新上下文内容。

从以上贴的代码来看很简单,就是做了三件事:

1.super(parent)

设置父级的ApplicationContext,这里设置了null

2.setConfigLocations(configLocations)

设置spring配置文件的路径,并且对于路径中的占位置进行转换

3.refresh()

refresh()是spring加载的核心内容,通过xml、properties、database对于context加载和刷新,完成对于所有单例类的初始化工作。

refresh()方法

上文已经提到refresh()方法是整个spring的加载的核心,这也是我们本次需要提到的重点内容,先展示refresh()的完整代码如下:

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

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

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }
        }
    }

首先spring的refresh()方法的一些特点:

1.方法从开始到结束都使用了对于this.startupShutdownMonitor的加锁处理

1).避免了多线程同时刷新spring配置

2).close()和refresh()都对startupShutdownMonitor进行加锁,close()的作用和refresh()是相反的:关闭context,销毁所有的bean。避免了2者的同时执行,产生冲突。

2.refresh()方法中没有具体的对于业务逻辑处理的代码,而是分成了若干个子方法,方便项目维护和代码拓展。

本文先讲到这里,下一篇开始,对于refresh()中的各个子方法进行详细的梳理

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/gagewang1/article/details/78255729
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞