Spring mvc项目通过listener初始化spring IOC容器过程
方法太多太深,没法一一追到位
graph TD;
ContextLoaderListener#contextInitialized-->ContextLoader#initWebApplicationContext
-->servletContext#getAttribute(获取servletContext中的org.springframework.web.context.WebApplicationContext.ROOT属性)
-->success{判断这个属性是否为空}
success-->|否|抛IllegalStateException异常
success-->|是|记录开始时间-->ContextLoader#context{判断ContextLoader#contwext是否为空}ContextLoader#context-->|空|createWebApplicationContext(为这个加载器实例化根WebApplicationContext)
-->determineContextClass(确定ContextClass)
--> BeanUtils.instantiateClass(创建一个ConfigurableWebApplicationContext对象即web容器)
-->instantiateClass(通过这个工具使用无参构造器创建对象实例)
-->ConfigurableWebApplicationContextContextLoader#context-->|不空|ConfigurableWebApplicationContext(判断这个容器是否为ConfigurableWebApplicationContext)
-->设置该容器的parentContext为null
-->configureAndRefreshWebApplicationContext(配置并刷新webApplicationContext)
-->给这个root容器设置一个id
-->setServletContext(把servletContext配置到WebApplicationContext中)
-->getInitParameter#contextConfigLocation{获取servlet中的contextConfigLocation参数}
-->|如果在servlet中设置了配置文件的路径|setConfigLocation(把该路径配置到webApplicatonContext中)
-->获取webApplicationContext中的环境变量信息(getEnvironment)
-->WebApplicationContextUtils.initServletPropertySources(初始化配置信息 这个对象是standardServletEnvironment中 这个其实就是读取指定的配置文件信息)
-->指定servletContextInitParams对应的配置文件
-->指定servletConfigInitParams对应的配置文件
-->customizeContext(定制容器)
-->determineContextInitializerClasses(确定容器初始化使用的ApplicationContextInitializer<ConfigurableApplicationContext>列表)
-->走进determineContextInitializerClasses这个方法
-->获取参数{从servletContext容器中获取初始化参数#globalInitializerClasses}
获取参数-->|如果设置了ServletContextInitParameter之globalInitializerClasses|将该配置对应的字符串分解为独立的字符串并组成数组添加到返回值list中
-->再次获取参数{从servletContext容器中获取初始化参数#contextInitializerClasses}
再次获取参数-->|如果设置了ServletContextInitParameter之contextInitializerClasses|将该配置对应的字符串分解为独立的字符串并组成数组再次添加到返回值list中
-->返回列表并结束determineContextInitializerClasses这个方法
-->遍历返回的列表分别执行以下操作
-->resolveTypeArgument(解析ApplicationContextInitialize对应的范型的具体类型)
-->initializerContextClass.isInstance(wac这里的参数是webApplicationContext)
initializerContextClass.isInstance-->|如果没有对应的具体类型或者webApplicationContext没有对这个Initiallize进行继承或实现的话|直接抛ApplicationContextException
initializerContextClass.isInstance-->|条件成立|实力化对应的initializer并加入到ContextLoader中的contextIntializers列表中
-->对ContextLoader中的contextInitializers进行排序
-->然后对这个列表中的initializer调用initialize方法进行初始化入参为webApplicationContext
-->到此customizeContext方法执行完成(定制容器方法结束)
-->webApplication.refresh(刷新容器)
-->从这里开始进入到AbstractApplicationContext
-->整个refresh过程是一个代码同步块synchronized包装的
-->AbstractApplicationContext.applicationStartup#start(实际上就是标记一下刷新步骤)
-->prepareRefresh(刷新容器准备阶段)
-->设置一些状态并打印一些日志信息
-->initPropertySources(web.context.support.StandardServletEnvironment#initPropertySources和前面的一样)
-->getEnvironmentz#validateRequiredProperties(验证必要的属性都是可解析的)
-->AbstractApplicationContext.earlyApplicationListeners{判断pre-refresh applicationListeners是否为空}
AbstractApplicationContext.earlyApplicationListeners-->|为空|pre-refresh监听器为空则用AbstractApplicationContext.applicationListeners的内容覆盖-->AbstractApplicationContext.earlyApplicationEevents
AbstractApplicationContext.earlyApplicationListeners-->|非空|AbstractApplicationContext.applicationListeners清空后用AbstratcApplicationContext.earlyApplicationListeners覆盖
-->AbstractApplicationContext.earlyApplicationEevents(创建earlyApplicationEevents容器LinkedHashSet)
-->prepareRefresh结束
-->obtainFreshBeanFactory(通知子类刷新内部BeanFactory)
-->refreshBeanFactory(进入到refreshBeanFactory内部看过程)
-->org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory(刷新BeanFactory)
-->如果已经存在的BeanFactory则清理掉-->创建DefaultListableBeanFactory(执行createBeanFactory方法)
-->创建DefaultListableBeanFactory的对象实例并指定ParentBeanFactory
-->给该BeanFactory设置序列化ID
-->定制BeanFactory
-->如果AbstractRefreshableApplicationContext中的allowBeanDefinitionOverriding属性不为空{ApplicationContext是否设置了allowBeanDefinitionOverriding属性}
如果AbstractRefreshableApplicationContext中的allowBeanDefinitionOverriding属性不为空-->|非空|标记BeanFactory为可以覆盖beanDefinition-->如果AbstractRefreshableApplicationContext中的allowCircularReferences属性不为空{ApplicationContext是否设置了allowCircularReferences属性}
如果AbstractRefreshableApplicationContext中的allowCircularReferences属性不为空-->|非空|标记BeanFactory为可以循环刷新-->将beanDefinition加载到BeanFactory中(org.springframework.context.support.AbstractRefreshableApplicationContext#loadBeanDefinitions 有多种实现#PropertiesbeanDefinitionReader XmlBeanDefinitionReader 有待研究实现细节)
-->将这个BeanFactory赋值给AbstractRefreshApplicationContext的beanFactory属性
-->返回容器中的beanFactory
-->prepareBeanFactory(配置这个beanFactory的信息)
-->setBeanExpressionResolver(设置SpEl表达式解析器)
-->addPropertyEditorRegistrar(添加属性解析器它的作用就是解析各种配置信息到需要的地方)
-->addBeanPostProcessor(添加Bean初始化的后置处理器之ApplicationContextAwareProcessor)
-->ignoreDependencyInterface#EnvironmentAware(忽略EnvironmentAware的实现 避免使用set进行依赖注入)
-->ignoreDependencyInterface#EmbeddedValueResolverAware(忽略EmbeddedValueResolverAware的实现 避免使用set进行依赖注入)
-->ignoreDependencyInterface#ResourceLoaderAware(忽略ResourceLoaderAware的实现 避免使用set进行依赖注入)
-->ignoreDependencyInterface#ApplicationEventPublisherAware(忽略ApplicationEventPublisherAware的实现 避免使用set进行依赖注入)
-->ignoreDependencyInterface#MessageSourceAware(忽略MessageSourceAware的实现 避免使用set进行依赖注入)
-->ignoreDependencyInterface#ApplicationContextAware(忽略ApplicationContextAware的实现 避免使用set进行依赖注入)
-->ignoreDependencyInterface#ApplicationStartupAware(忽略ApplicationStartupAware的实现 避免使用set进行依赖注入)
-->解决自动注入将容器中的beanFactory注入到BeanFactory的实现类
-->解决自动注入将容器注入到ResourceLoader实现类
-->解决自动注入将容器注入到ApplicationEventPublisher的实现类
-->解决自动注入将容器注入到ApplicationContext的实现类
-->addBeanPostProcessor(添加Bean初始化的后置处理器之ApplicationListenerDetector)
-->检测是否设置了org.graalvm.nativeimage.imagecode这个技术很牛逼但是不了解
-->向容器中添加environment对象
-->向容器中添加systemProperties对象
-->向容器中添加systemEnvironment对象
-->向容器中添加applicationStartup对象
-->prepareBeanFactory结束
-->执行模版方法postProcessBeanFactory(执行钩子方法对前面的步骤进行补充可以继续添加对象到容器或添加后置处理器)
-->打印日志'spring.context.beans.post-process'
-->org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(执行BeanFactory的后置处理器 这个方法很重待深入研究)
-->registerBeanPostProcessors(注册Bean的后置处理)
-->initMessageSource(初始化容器的initMessageSource国际化处理)
-->initApplicationEventMulticaster(初始化容器的initApplicationEventMulticaster事件广播)
-->onRefresh(容器的钩子方法)
-->registerListeners(容器注册监听器和earlyApplicatonEvents关联)
-->finishBeanFactoryInitialization(完成BeanFactory初始化)
-->设置setConversionService转换服务
-->addEmbeddedValueResolver(如果没有BeanFactoryPostProcessor设置一个嵌入式的解析器)
-->创建LoadTimeWeaverAware实例
-->setTempClassLoader(停止使用临时的classLoader进行加载)
-->冻结beanFactory中对应的bean的原数据禁止修改
-->preInstantiateSingletons(实例化剩余的对象实例 lazy的除外)
-->finishBeanFactoryInitialization结束-->finishRefresh(完成刷新)
-->clearResourceCaches(清理资源缓存)
-->initLifecycleProcessor(初始化生命周期处理器 待研究)
-->initLifecycleProcessor#onRefresh(创建bean加入treeMap)
-->publishEvent(广播一个ContextRefreshedEvent事件)
-->LiveBeansView.registerApplicationContext(将liveBean托管给MBeanServer)
-->最后层层返回将这个webApplicationContext注册到servletContext中