获取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/
原文地址:https://www.cnblogs.com/wewill/p/5588738.html