Spring有两种方式加载配置,分别为xml文件、注解的方式,对于xml配置的方式相信大家都不陌生,往往通过new ClassPathXmlApplicationContext("*.xml")就能启动容器了,下面让我们来看看Spring的容器启动都做了哪些事情。
1、ClassPatchXmlApplicationContext的类图结构
从类图我们可以得到的信息:
1,ClassPatchXmlApplicationContext是一个容器 ,是BeanFactory的子类;
2,ClassPatchXmlApplicationContext是一个资源加载器,是ResourceLoader的子类。
2、ClassPatchXmlApplicationContext构造器
1 public ClassPathXmlApplicationContext( 2 String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) 3 throws BeansException { 4 // 调用父类构造方法 5 super(parent); 6 // 资源路径设置到当前上下文中 7 setConfigLocations(configLocations); 8 // 刷新容器 9 if (refresh) { 10 refresh(); 11 } 12 }
2.1、调用父类构造器
最终会调用到父类AbstractApplicationContext的构造方法。
1、初始化AbstractApplicationContext的资源路径解析器resourcePatternResolver 属性;
2、为当前上下文设置父上下文环境,若父上下文环境不为空,将父上下文环境合并到当前上下文环境中。
1 // 构造器 2 public AbstractApplicationContext(@Nullable ApplicationContext parent) { 3 this(); 4 setParent(parent); 5 } 6 // 初始化资源路径解析器 7 public AbstractApplicationContext() { 8 // 创建资源模式处理器 9 this.resourcePatternResolver = getResourcePatternResolver(); 10 } 11 // 设置父容器 12 public void setParent(@Nullable ApplicationContext parent) { 13 this.parent = parent; 14 // 若父容器不为空,则将父容器的环境配置合并到当前容器中 15 if (parent != null) { 16 Environment parentEnvironment = parent.getEnvironment(); 17 if (parentEnvironment instanceof ConfigurableEnvironment) { 18 getEnvironment().merge((ConfigurableEnvironment) parentEnvironment); 19 } 20 } 21 }
2.2、设置资源路径
对父类AbstractRefreshableConfigApplicationContext的configLocations做赋值,将配置资源配置文件位置设置到当前应用程序上下文中。
1 // 设置资源路径 2 public void setConfigLocations(@Nullable String... locations) { 3 if (locations != null) { 4 Assert.noNullElements(locations, "Config locations must not be null"); 5 this.configLocations = new String[locations.length]; 6 for (int i = 0; i < locations.length; i++) { 7 this.configLocations[i] = resolvePath(locations[i]).trim(); 8 } 9 } 10 else { 11 this.configLocations = null; 12 } 13 }
2.3、刷新容器 - Spring的IOC容器的核心启动流程
1 // 刷新容器的流程 2 @Override 3 public void refresh() throws BeansException, IllegalStateException { 4 synchronized (this.startupShutdownMonitor) { 5 // 容器刷新前的准备工作 6 prepareRefresh(); 7 // 创建容器对象DefaultListableBeanFactory,加载xml配置文件的属性值到当前工厂中 8 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 9 // beanFactory的准备工作,对各种属性进行填充 10 prepareBeanFactory(beanFactory); 11 12 try { 13 // 子类覆盖方法做额外的处理,web中的代码有具体实现 14 postProcessBeanFactory(beanFactory); 15 16 // 调用各种beanFactory处理器 17 invokeBeanFactoryPostProcessors(beanFactory); 18 19 // 注册bean处理器,这里只是注册功能,真正调用的地方在getBean方法 20 registerBeanPostProcessors(beanFactory); 21 22 // 为上下文初始化message源,即不同语言的消息体,国际化处理,在springmvc的有实际应用 23 initMessageSource(); 24 25 // 初始化事件监听多路广播器 26 initApplicationEventMulticaster(); 27 28 // 留给子类来初始化其他的bean 29 onRefresh(); 30 31 // 在所有注册的bean中查找listener bean,注册到消息广播器中 32 registerListeners(); 33 34 // 初始化剩下的单实例(非懒加载的) 35 finishBeanFactoryInitialization(beanFactory); 36 37 // 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知 38 finishRefresh(); 39 } 40 41 catch (BeansException ex) { 42 if (logger.isWarnEnabled()) { 43 logger.warn("Exception encountered during context initialization - " + 44 "cancelling refresh attempt: " + ex); 45 } 46 47 // 为防止bean资源占用,在异常处理中,销毁已经在前面过程中生成的单件bean 48 destroyBeans(); 49 50 // 重置active标志 51 cancelRefresh(ex); 52 53 throw ex; 54 } 55 finally { 56 // 重置缓存 57 resetCommonCaches(); 58 } 59 } 60 }
综上可见,Spring容器启动的核心方法,这些方法后序会做详细介绍
1、prepareRefresh()
刷新容器前的准备工作
2、obtainFreshBeanFactory()
创建容器,并加载配置并生成BeanDefinition,加载至缓存。为后续创建bean对象做准备工作。
3、prepareBeanFactory(beanFactory)
beanFactory的准备工作,主要是用来为容器填充属性
4、postProcessBeanFactory(beanFactory)
beanFactory容器的后置处理器
5、invokeBeanFactoryPostProcessors(beanFactory)
调用各种BeanFactoryPostProcessors的后置处理器,实例化BeanFactoryPostProcessor类型的bean对象,包括ConfigurationClassPosyProcessor类对注解的处理,也是SpringBoot自动配置的基础。
6、registerBeanPostProcessors(beanFactory)
调用各种BeanPostProcessor的后置处理器,实例化BeanPostProcessor类型的bean对象,包括对Spring AOP的自动代理创建器AspectJAwareAdvisorAutoProxyCreator的实例的创建。
7、finishBeanFactoryInitialization(beanFactory)
初始化定义的bean实例。
8、finishRefresh()
完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程