問題由來
我們平時常用的spring+tomcat的web專案是怎么啟動的呢?帶著這個疑問探索一下,
Tomact
查看tomcat下/conf/context.xml:
<Context>
<!-- Default set of monitored resources -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
</Context>
我們大概知道,默認的背景關系加載路徑是WEB-INF/web.xml,雖然我們沒看tomcat原始碼,在本文中,知道這個足夠了,這與我們的認知,web.xml是web專案的起點,是一致的
web.xml
看一個比較常見的web.xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>spring-action</display-name>
<!--定義contextConfigLocation的位置-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring/my-application-context.xml</param-value>
</context-param>
<!--背景關系啟動的監聽器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
啟動起點
1、我們看下org.springframework.web.context.ContextLoaderListener類,里面的contextInitialized方法,它是在listener初始化時呼叫的,
/**
* Initialize the root web application context.
*/
@Override
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
}
我們沿著initWebApplicationContext方法debug一下看看:
注意我標的代碼序號,下面會講:
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
if (this.context == null) {
// 1
this.context = createWebApplicationContext(servletContext);
}
// 2
if (this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
if (!cwac.isActive()) {
if (cwac.getParent() == null) {
// 3、我們現在沒有父容器,先不講
ApplicationContext parent = loadParentContext(servletContext);
cwac.setParent(parent);
}
// 4、開始配置和重繪當前容器
configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
return this.context;
}
我們創建了什么型別的容器,怎么看?
在代碼2處,我們看到context的型別為XmlWebApplicationContext,它是怎么確定的呢?
答案在代碼1處的createWebApplicationContext中,
里面有一段:
protected Class<?> determineContextClass(ServletContext servletContext) {
String contextClassName = servletContext.getInitParameter("contextClass");
if (contextClassName != null) {
return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
}
else {
contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
}
}
我們看到:具體我們創建什么型別的context背景關系有一個配置contextClass,你是可以配置web.xml檔案里的,我們現在沒有配,所以讀的就是默認的,默認的defaultStrategies是在靜態代碼塊里初始化的,如下:讀取的是ContextLoader.properties組態檔中的內容,
ClassPathResource resource = new ClassPathResource("ContextLoader.properties", ContextLoader.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
ContextLoader.properties中的內容就是XmlWebApplicationContext:
org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
現在我們知道這里創建的context為什么是xmlWebApplictionContext了,
容器是怎么創建的?
進入前面標的第4代碼段:configureAndRefreshWebApplicationContext()方法:
我們看到,讀取了配置的contextConfigLocation的位置,并設定進context背景關系中:

之后獲取一些配置的引數之后:
// 1、 在context refresh之前做一些自定義處理
customizeContext(sc, wac);
// 2、背景關系重繪
wac.refresh();
看到refresh()我們就激動了,這不就是進到AbstratApplicationContext#refresh()了嗎?是的,進來了:

在本例子中,就是按照xmlWebApplictionContext類進行背景關系創建,
小結
本文我們大概了解了,我們平時常用的web應用的初始化程序是怎樣,
進到refresh之后就是context的創建程序了,具體細節可以參看近期發布的文章,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/231013.html
標籤:其他
