美文网首页技术干货探索Spring
Spring Bean的生命周期-实例化ApplicationC

Spring Bean的生命周期-实例化ApplicationC

作者: Real_man | 来源:发表于2018-10-03 20:19 被阅读10次

    Spring Bean的生命周期往深入去看,不是简单的几句话能讲完,早就想写相关的内容,但一直觉得工作量不会低,就没有动笔写。拆成几篇来写,这样也不好给自己太大的压力。

    image.png

    主要分析,Spring容器的初始化过程,然后如何获取Bean,到最终销毁Bean整个过程经历了什么东西。

    代码

    主要为了分析,更多的是深入源代码中,代码写的就简单一些

    //SpringApp.java文件
    public class SpringApp {
        public static void main(String[] args) {
            ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("app.xml");
            HelloWorld hello = (HelloWorld) applicationContext.getBean("hello");
            hello.sayHello();
            applicationContext.close();
        }
    }
    
    //HelloWorld 文件
    public class HelloWorld {
        public void sayHello(){
            System.out.println("hello World");
        }
    }
    
    //app.xml文件
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="hello" class="me.aihe.HelloWorld">
    
        </bean>
    </beans>
    

    文件结构就是这个简单,如下

    image.png

    过程分析

    1. 新建ClassPathXmlApplicationContext实例的时候,最终实例化的构造方法如下
    • configLocations配置文件位置,支持字符串数组
    • refresh是否自动的刷新上下文,否则在配置之后要手动的调用refresh方法
    • parent 父级的上下文
    
    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
                throws BeansException {
    
            super(parent);
            setConfigLocations(configLocations);
            if (refresh) {
                refresh();
            }
        }
            
    

    其最终的实例化的父类为:

       //创建AbstractApplicationContext
        public AbstractApplicationContext() {
            this.resourcePatternResolver = getResourcePatternResolver();
        }
    
        public AbstractApplicationContext(ApplicationContext parent) {
            this();
            setParent(parent);
        }
        
        protected ResourcePatternResolver getResourcePatternResolver() {
            return new PathMatchingResourcePatternResolver(this);
        }
    
    1. 设置配置文件的位置, setConfigLocation(String location)
       //支持可变参数,如果locations不存在,那么默认为null
        public void setConfigLocations(String... locations) {
            if (locations != null) {
                Assert.noNullElements(locations, "Config locations must not be null");
                this.configLocations = new String[locations.length];
                //处理配置文件的位置,稍作处理
                for (int i = 0; i < locations.length; i++) {
                    this.configLocations[i] = resolvePath(locations[i]).trim();
                }
            }
            else {
                this.configLocations = null;
            }
        }
    
    
    1. 刷新Context, 调用refresh()方法,这里先贴出来整个方法, Refreash方法是容器中非常重要的一个方法,一时间这里不好完全讲说明白,先把每个方法的用途注释写上,接下来我们再一起看看其内部是怎么回事
    public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                // 准备刷新的Context.
                prepareRefresh();
    
                // Tell the subclass to refresh the internal bean factory.
                // 告诉子类刷新内部的Bean Factory
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
                // Prepare the bean factory for use in this context.
                // 准备好Context使用的Bean Factory
                prepareBeanFactory(beanFactory);
    
                try {
                    // Allows post-processing of the bean factory in context subclasses.
                    // 设置Bean的 postPorcess
                    postProcessBeanFactory(beanFactory);
    
                    // Invoke factory processors registered as beans in the context.
                    // 调用BeanFactory的 postProcess
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                    // Register bean processors that intercept bean creation.
                    // 注册Bean的PostProcess
                    registerBeanPostProcessors(beanFactory);
    
                    // Initialize message source for this context.
                    //对上下文中的消息源进行初始化
                    initMessageSource();
    
                    // Initialize event multicaster for this context.
                    //初始化上下文的事件机制
                    initApplicationEventMulticaster();
    
                    // Initialize other special beans in specific context subclasses.
                    //初始化其它特殊的beans
                    onRefresh();
    
                    // Check for listener beans and register them.
                    //检查这些Bean,并且向容器注册
                    registerListeners();
    
                    // Instantiate all remaining (non-lazy-init) singletons.
                    //实例化所有的非懒加载的 Singleton
                    finishBeanFactoryInitialization(beanFactory);
    
                    // Last step: publish corresponding event.
                    // 发布相关的事件
                    finishRefresh();
                }
    
                catch (BeansException ex) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Exception encountered during context initialization - " +
                                "cancelling refresh attempt: " + ex);
                    }
    
                    // Destroy already created singletons to avoid dangling resources.
                    // 销毁已经创建的singletons避免对资源产生不好的影响
                    destroyBeans();
    
                    // Reset 'active' flag.
                    //重置 active 标志
                    cancelRefresh(ex);
    
                    // Propagate exception to caller.
                    throw ex;
                }
    
                finally {
                    // Reset common introspection caches in Spring's core, since we
                    // might not ever need metadata for singleton beans anymore...
                    //重置所有的caches
                    resetCommonCaches();
                }
            }
        }
    
    涉及到类
    • PathMatchingResourcePatternResolver
    • StandardEnvironment
    TODO
    • AbstractRefreshableConfigApplicationContext.resolvePath,其中涉及到了Environment.resolveRequiredPlaceholders(String path)

    最后

    读代码,如果条理清晰,是一件比较爽的工作,尽量不要急功近利,我们一步一步来,压力都会比较小一点。

    参考

    相关文章

      网友评论

        本文标题:Spring Bean的生命周期-实例化ApplicationC

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