獲取spring容器要小心的坑

情景:

今天想把一個web應用中的上傳路勁更改一下

於是就在配置文件作了如下變動:

<bean id="uploadServelt" class="com.xxxx.servlet.UploadServlet" scope="request" autowire="byType"> <property name="savePath" ><value>"C:\\Users\\admin\\Desktop\\upload"</value></property> </bean>

然後savePath這個變量仍然沒有生效

然後就想,會不會是沒有關聯到配置文件

ApplicaitonContext的幾種生成方法

一、ClassPathXmlApplicationContext

這種方式是通過類名路徑去找到配置文件,所以配置文件只能放在項目內部

二、FileSystemXmlApplicationContext

這個跟java.io.File差不多,所以配置文件可以放在項目外部

三、WebApplicationContextUtils

有兩種方法去得到ApplicationContext

  1. getRequiredWebApplicationContext(ServletContext)
  2. getWebApplicationContext(ServletContext)

推薦第一種方法,因爲第一種方法當獲取失敗的時候會拋出異常,第二種只會返回null

原因

重點來了!!爲什麼第三種方法會有可能獲取失敗呢??

注意,這兩種方法的參數都是ServletContext,所以推測,ApplicationContext是放在ServletContext裏面

查一查源碼

        String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
	public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
		return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
	}
	public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) {
		Assert.notNull(sc, "ServletContext must not be null");
		Object attr = sc.getAttribute(attrName);
		if (attr == null) {
			return null;
		}
		if (attr instanceof RuntimeException) {
			throw (RuntimeException) attr;
		}
		if (attr instanceof Error) {
			throw (Error) attr;
		}
		if (attr instanceof Exception) {
			throw new IllegalStateException((Exception) attr);
		}
		if (!(attr instanceof WebApplicationContext)) {
			throw new IllegalStateException("Context attribute is not of type WebApplicationContext: " + attr);
		}
		return (WebApplicationContext) attr;
	}

從源碼看,ApplicationContext果然是放在ServletContext裏面的,所以在獲取之前,如果ServletContext裏面沒有ApplicationContext,那麼就會拋出異常

ApplicationContext儲存在ServletContext的默認屬性名是"org.springframework.web.context.WebApplicationContext.ROOT"

然而,平時的慣性思維都以爲,這種獲取ApplicaitonContext的方法是spring自動完成的,不需要我們new

解決方案

先在ApplicationListener初始化的時候,用方法一或者方法二創建一個ApplicaitonContext,然後set到ServletContext裏面去,然後之後就可以用第三種方法獲取了,注意set的時候的屬性名稱,可以自定義也可以用默認的"org.springframework.web.context.WebApplicationContext.ROOT"

如果是自定義的話,就要用這個方法去獲取ApplicationContext了

WebApplicationContext.getWebApplicationContext(ServletContext sc, String attrName)

更正

之前說的有點不對 如果是web應用 當spring的ContextLoaderListener啓動的時候,會將WebApplicationContext放入ServletContext裏面去, 所以我們就大膽的使用方法三來獲取吧



查看原文:http://139.129.55.235/2016/05/30/%e8%8e%b7%e5%8f%96spring%e5%ae%b9%e5%99%a8%e8%a6%81%e5%b0%8f%e5%bf%83%e7%9a%84%e5%9d%91/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章