本文共 4957 字,大约阅读时间需要 16 分钟。
javaweb引用启动时会加载web.xml,并且会执行配置的listener,在这里注册一个监听器,在内部初始化applicationContext就可以了。这里监听的类是org.springframework.web.context.ContextLoaderListener
该类继承了ServletContextListener接口,web应用启动时会执行contextInitialized方法。public void contextInitialized(ServletContextEvent event) { this.initWebApplicationContext(event.getServletContext()); }
可以看到,该方法就是用来初始化applicationContext的。
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { if(servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) { throw new IllegalStateException("Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!"); } else { Log logger = LogFactory.getLog(ContextLoader.class); servletContext.log("Initializing Spring root WebApplicationContext"); if(logger.isInfoEnabled()) { logger.info("Root WebApplicationContext: initialization started"); } long startTime = System.currentTimeMillis(); try { if(this.context == null) { this.context = this.createWebApplicationContext(servletContext); } if(this.context instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)this.context; if(!cwac.isActive()) { if(cwac.getParent() == null) { ApplicationContext parent = this.loadParentContext(servletContext); cwac.setParent(parent); } this.configureAndRefreshWebApplicationContext(cwac, servletContext); } } servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); ClassLoader ccl = Thread.currentThread().getContextClassLoader(); if(ccl == ContextLoader.class.getClassLoader()) { currentContext = this.context; } else if(ccl != null) { currentContextPerThread.put(ccl, this.context); } if(logger.isDebugEnabled()) { logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]"); } if(logger.isInfoEnabled()) { long elapsedTime = System.currentTimeMillis() - startTime; logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms"); } return this.context; } catch (RuntimeException var8) { logger.error("Context initialization failed", var8); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var8); throw var8; } catch (Error var9) { logger.error("Context initialization failed", var9); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var9); throw var9; } } }
继续打开往下看,applicationContext是存在servletContext中的,key值为ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的值,可以看到是通过调用
createWebApplicationContext初始化的,内部调用determineContextClass获取具体的class,如果配置了contextClass变量,则使用该变量获取class,否则使用默认的初始化,这样applicationContext对象就创建完成了。 然后需要获取配置文件初始化bean。 具体是调用了configureAndRefreshWebApplicationContext方法,打开该方法可以看到:protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) { String configLocationParam; if(ObjectUtils.identityToString(wac).equals(wac.getId())) { configLocationParam = sc.getInitParameter("contextId"); if(configLocationParam != null) { wac.setId(configLocationParam); } else { wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath())); } } wac.setServletContext(sc); configLocationParam = sc.getInitParameter("contextConfigLocation"); if(configLocationParam != null) { wac.setConfigLocation(configLocationParam); } ConfigurableEnvironment env = wac.getEnvironment(); if(env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment)env).initPropertySources(sc, (ServletConfig)null); } this.customizeContext(sc, wac); wac.refresh(); }
可以看到,如果设置了contextConfigLocation初始化参数,则用该参数,否则使用默认参数,这样,application创建bean就齐全了。创建完成后设置进ServletContext中,后续使用只要从里面取出就可以了,key 为ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE。
转载地址:http://fhjqi.baihongyu.com/