I.Spring源碼分析之web入口

web.xml css

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
	http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<display-name>Archetype Created Web Application</display-name>
	<!-- 初始化 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>
	<!-- 監聽器 -->
	<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
	<!-- 定義struts2的核心filter -->
	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>
			org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
		</filter-class>
	</filter>
	<!-- 讓struts定義的核心filter攔截全部請求 -->
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>*.do</url-pattern>
	</filter-mapping>

	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>

	<!-- druid數據庫監控 -->
	<filter>
		<filter-name>DruidWebStatFilter</filter-name>
		<filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
		<init-param>
			<param-name>exclusions</param-name>
			<param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>DruidWebStatFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<servlet>
		<servlet-name>DruidStatView</servlet-name>
		<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>DruidStatView</servlet-name>
		<url-pattern>/druid/*</url-pattern>
	</servlet-mapping>

	<!-- 項目歡迎界面 -->
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
	<error-page>
		<error-code>404</error-code>
		<location>/404.html</location>
	</error-page>
	<error-page>
		<error-code>500</error-code>
		<location>/500.html</location>
	</error-page>
	<error-page>
		<error-code>502</error-code>
		<location>/502.html</location>
	</error-page>
	<error-page>
		<error-code>504</error-code>
		<location>/504.html</location>
	</error-page>
</web-app>

 

Spring 的入口 org.springframework.web.context.ContextLoaderListener html

這個類繼承了  org.springframework.web.context.ContextLoader java

實現了javax.servlet.ServletContextListener接口 web

在ContextLoader中有一個靜態語句塊 spring

static {
		// Load default strategy implementations from properties file.
		// This is currently strictly internal and not meant to be customized
		// by application developers.
		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());
		}
	}

注意這個private static final String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties"; shell

我找了一下這個文件 數據庫

是在ContextLoader.class一個目錄下 apache

來看看這個文件 api

# Default WebApplicationContext implementation class for ContextLoader.
# Used as fallback when no explicit context implementation has been specified as context-param.
# Not meant to be customized by application developers.

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

 

註釋:默認的WebApplicationContext接口的實現類 app

在上面的靜態語句塊的做用是把這個文件讀到Properties(defaultStrategies)對象裏

ContextLoaderListener實現了ServletContextListener接口 

那麼啓動服務的入口是這個方法contextInitialized

ContextLoader#initWebApplicationContext(ServletContext servletContext)

--》configureAndRefreshWebApplicationContext(cwac, servletContext);

注意看這一行代碼String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);

public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";

這個就是獲取web.xml中的內容

<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>

獲取配置文件的內容 找到spring文件的路徑

接下來看wac.setConfigLocation(configLocationParam);

咱們直接進這2個方法發現了一個嚴重的問題   2個方法的實現裏面都是直接拋出異常的!!!

說明這個是被禁止調用的?

我再看了下ConfigurableWebApplicationContext    這是一個接口

再回來看到了ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;  這個

接着向上找  this.context = createWebApplicationContext(servletContext);

也就是咱們找到了建立 wac具體實例的地方

Class<?> contextClass = determineContextClass(sc);
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);
			}
		}
	}

最重要的是這一行代碼:

contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());

咱們上面提到在靜態語句塊裏面解析了ContextLoader.properties

獲得了

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

根據代碼咱們知道XmlWebApplicationContext就是

wac.setConfigLocation(configLocationParam);

中wac的實例

果真咱們在它的父類的父類(AbstractRefreshableConfigApplicationContext)中找到了setConfigLocation方法的實現

看裏面的實現是把路徑解析到configLocations中

AbstractApplicationContext#refresh()

開始加載解析和加載相關的文件

相關文章
相關標籤/搜索