启动流程
- Spring的启动流程主要是定位 -> 加载 -> 注册 -> 实例化:
- 定位:获取配置文件路径。
- 加载:把配置文件读取成BeanDefinition。
- 注册:存储BeanDefinition。
- 实例化:根据BeanDefinition创建实例。
- 所谓的IOC容器其实就是BeanFactory,BeanFactory 是一个接口,有很多对应的实现类。
- IOC容器的关键入口方法是refresh()。
Web容器
Web应用中使用的容器是XmlWebApplicationContext,其类图如下,可以看出最终是一个实现了 BeanFactory的类。
对于Web项目存在一个web.xml,其关键是要配置一个 ContextLoaderListener 和一个 DispatcherServlet。
1 | <web-app> |
在Java Web容器中相关组件的启动顺序是ServletContext -> listener -> filter -> servlet,listener是优于servlet启动的,所以我们先看一看ContextLoaderListener的内容。
1 | public class ContextLoaderListener extends ContextLoader implements ServletContextListener { |
当Listener启动时会调用contextInitialized
方法,而ContextLoaderListener中该方法的内容是继续调用initWebApplicationContext
方法,于是我们再跟踪initWebApplicationContext(ContextLoaderListener是ContextLoader的子类,所以其实是调用了父类的initWebApplicationContext
方法)。
1 | public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { |
此处我们关心的是createWebApplicationContext
方法。
1 | protected WebApplicationContext createWebApplicationContext(ServletContext sc) { |
从代码可知,方法中的逻辑主要是调用determineContextClass获取contextClass,然后根据contextClass创建IOC容器实例。所以,contextClass的值将是关键。
1 | protected Class<?> determineContextClass(ServletContext servletContext) { |
可以看到,contextClassName是从defaultStrategies中获取的,而关于defaultStrategies的赋值需要追溯到ContextLoader类中的静态代码块。