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
过程分析
新建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); }
设置配置文件的位置,
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; } }
刷新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)
最后
读代码,如果条理清晰,是一件比较爽的工作,尽量不要急功近利,我们一步一步来,压力都会比较小一点。
作者:Real_man
链接:https://www.jianshu.com/p/2ce01125564f