首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

Spring跟Web容器整合的内部实现

2012-06-29 
Spring和Web容器整合的内部实现Spring和Web应用的整合配置如下?context-param?????? param-namecontex

Spring和Web容器整合的内部实现

Spring和Web应用的整合配置如下

?

<context-param>

?????? <param-name>contextConfigLocation</param-name>

?????? <param-value>classpath:applicationContext.xml</param-value>

<listener>

??? <listener-class>

? ? ? org.springframework.web.context.ContextLoaderListener

? ?</listener-class>

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {private ContextLoader contextLoader;public void contextInitialized(ServletContextEvent event) {this.contextLoader = createContextLoader();if (this.contextLoader == null) {this.contextLoader = this;}this.contextLoader.initWebApplicationContext(event.getServletContext());}protected ContextLoader createContextLoader() {return null;}public ContextLoader getContextLoader() {return this.contextLoader;}public void contextDestroyed(ServletContextEvent event) {if (this.contextLoader != null) {this.contextLoader.closeWebApplicationContext(event.getServletContext());}ContextCleanupListener.cleanupAttributes(event.getServletContext());}}

?

public class ContextLoader {public static final String CONTEXT_CLASS_PARAM = "contextClass"; public static final String CONTEXT_ID_PARAM = "contextId"; public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation"; public static final String LOCATOR_FACTORY_SELECTOR_PARAM = "locatorFactorySelector"; public static final String LOCATOR_FACTORY_KEY_PARAM = "parentContextKey"; private static final String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties"; private static final Properties defaultStrategies;static {try {ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);}catch (IOException ex) {throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage());}}//指定了一个类加载器只能实例化一个Spring容器private static final Map<ClassLoader, WebApplicationContext> currentContextPerThread =new ConcurrentHashMap<ClassLoader, WebApplicationContext>(1);private static volatile WebApplicationContext currentContext;private WebApplicationContext context; //ContextLoaderListener类中就是调用了这个方法public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {try {ApplicationContext parent = loadParentContext(servletContext);// Store context in local instance variable, to guarantee that// it is available on ServletContext shutdown.this.context = createWebApplicationContext(servletContext, parent);servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);ClassLoader ccl = Thread.currentThread().getContextClassLoader();return this.context;}protected WebApplicationContext createWebApplicationContext(ServletContext sc, ApplicationContext parent) {Class<?> contextClass = determineContextClass(sc);if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {throw new ApplicationContextException("Custom context class [" + contextClass.getName() +"] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");}ConfigurableWebApplicationContext wac =(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);wac.setParent(parent);wac.setServletContext(sc);wac.setConfigLocation(sc.getInitParameter(CONFIG_LOCATION_PARAM));customizeContext(sc, wac);wac.refresh();return wac;}protected Class<?> determineContextClass(ServletContext servletContext) {String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);if (contextClassName != null) {try {return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());}catch (ClassNotFoundException ex) {throw new ApplicationContextException("Failed to load custom context class [" + contextClassName + "]", ex);}}else {contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());try {return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());}catch (ClassNotFoundException ex) {throw new ApplicationContextException("Failed to load default context class [" + contextClassName + "]", ex);}}}}?

?

? ? ? 在这个类的静态代码块里面加载了同路径下的ContextLoader.properties这个属性文件,代开它,里面只有一条

org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContex

t,这个是指定了Spring容器的具体实现类,要整合Web,自然是要XmlWebApplicationContext了。

? ? ? 看initWebApplicationContext方法,接着调用createWebApplicationContext(servletContext, parent)方法中,创建出WebApplicationContext,在这个方法里面,determineContext——确定Spring容器的具体实现类,然后使用BeanUtils.instantiateClass()来初始化XmlWebApplicationContext类,注意,这里只是初始化这个类,并没有启动Spring容器,要启动容器,还需要一个非常关键的东西,那就是配置文件。在createWebApplicationContext的最后又几条红色加深的代码,非常关键,

?

? ??wac.setServletContext(sc);//将当前的ServletContext传给即将启动的Spring容器

? ? ?wac.setConfigLocation(sc.getInitParameter(CONFIG_LOCATION_PARAM));//设置容器启动时加载的 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?spring配置文件,在这里就是要使用web.xml中配置的contextConfigLocation参数所指定的配 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?置文件位置了

? ? customizeContext(sc, wac);

wac.refresh();//在这里启动Spring容器,这里其实是调用父类AbstractApplicationContext的refresh()方法

?

?

综上所述,Spring和Web应用的整合这是在web应用启动的时候通过一个监听器去启动了XmlWebApplicationContext Spring容器,并将这个容器实例放入到ServletContext的Map里,Map里以WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,对于的字符串也就是WebApplicationContext.class.getName() + ".ROOT";也就是"org.springframework.web.context.WebApplicationContext.ROOT",在Servlet环境下可以通过这个来访问Spring容器,同样Spring中当然也可以访问ServletContext。

?

?

?

?

热点排行