学习学习容器初始化,若有不对的地方,请指出更正,大家共同学习学习。
此篇幅主要围绕着 ContextLoaderListener加载容器,理解其中的原理。
ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。
因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。
ContextLoaderListener启动的上下文为根上下文,DispatcherServlet所创建的上下文的的父上下文即为此根上下文,可在FrameworkServlet中的initWebApplicationContext中看出。
通常在web.xml中如下配置:
层次结构
初始化root跟web上下文,initWebApplicationContext方法在其父类ContextLoader中提供实现。
根据提供的servlet上下文去初始化Spring的web应用上下文,在构造时使用当前应用上下文或者在web.xml中配置参数contextClass和contextConfigLocation去创建新的上下文。
初始化根上下文,
Web.xml中配置了contextClass就取其值,但必须是实现ConfigurableWebApplicationContext,
没有的就取默认值XmlWebApplicationContext。
ContextClass默认值和ContextLoader.properties如下:
其中loadParentContext
根据在web.xml中配置的locatorFactorySelector和parentContextKey来给根web应用上下设置父上下文,如果没配置的话,父上下文为空。
加载父上下文的主要原因是允许多重root web application contexts作为可共享的ERA context的子节点,或者对EJB可见的去交替共享同样的父上下文。For pure web applications, there is usually no need to worry about having a parent context to the root web application context。这句话明确告诉我们,对于纯粹的Web应用,通常不用担心root web application context的父上下文,也就是没有,为null。
在应用程序如何获取 WebApplicationContext 有多种方式,最简单的就是
1.WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
当前应用的WebApplicationContext就保存在 ContextLoader的currentContextPerThread属性当中
2.基于ServletContext上下文获取的方式
ServletContext sc = request.getSession().getServletContext();
ApplicationContext ac1 = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
ApplicationContext ac2 = WebApplicationContextUtils.getWebApplicationContext(sc);
WebApplicationContext wac1 = (WebApplicationContext) sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
3.还有一些更合适的,基于spring提供的抽象类或者接口,在初始化Bean时注入ApplicationContext
3.1:继承自抽象类ApplicationObjectSupport
说明:抽象类ApplicationObjectSupport提供getApplicationContext()方法,可以方便的获取到ApplicationContext。
Spring初始化时,会通过该抽象类的setApplicationContext(ApplicationContext context)方法将ApplicationContext 对象注入。
3.2:继承自抽象类WebApplicationObjectSupport
说明:类似上面方法,调用getWebApplicationContext()获取WebApplicationContext
3.3:实现接口ApplicationContextAware
说明:实现该接口的setApplicationContext(ApplicationContext context)方法,并保存ApplicationContext 对象。
总结:Context结构复杂,parentContext结构的作用,及如何的去加载bean工厂的逻辑原理。
根据在web.xml中配置的locatorFactorySelector和parentContextKey来给根web应用上下设置父上下文,如果没配置的话,父上下文为空。
1.WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
当前应用的WebApplicationContext就保存在 ContextLoader的currentContextPerThread属性当中
2.基于ServletContext上下文获取的方式
ServletContext sc = request.getSession().getServletContext();
ApplicationContext ac1 = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
ApplicationContext ac2 = WebApplicationContextUtils.getWebApplicationContext(sc);
WebApplicationContext wac1 = (WebApplicationContext) sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
3.还有一些更合适的,基于spring提供的抽象类或者接口,在初始化Bean时注入ApplicationContext
3.1:继承自抽象类ApplicationObjectSupport
说明:抽象类ApplicationObjectSupport提供getApplicationContext()方法,可以方便的获取到ApplicationContext。
Spring初始化时,会通过该抽象类的setApplicationContext(ApplicationContext context)方法将ApplicationContext 对象注入。
3.2:继承自抽象类WebApplicationObjectSupport
说明:类似上面方法,调用getWebApplicationContext()获取WebApplicationContext
3.3:实现接口ApplicationContextAware
说明:实现该接口的setApplicationContext(ApplicationContext context)方法,并保存ApplicationContext 对象。