ContextLoader中setContextInitializers(ApplicationContextInitializer<?>... initializers)的思考
2016-06-22 17:12
519 查看
最近查看了ContextLoader的源代码,涉及到了contextInitializerClasses参数,由于自己的项目没有用到该参数,对此产生了好奇,参考网上资料,整理一下:
ContextLoader中部分代码:
举个例子:
XmlWebApplicationContext.setAllowBeanDefinitionOverriding()其默认值为true。如果把此值设置为false,怎么解决?
有两个思路:
1、写org.springframework.web.context.ContextLoaderListener和org.springframework.web.servlet.DispatcherServlet的子类:
在相应的方法中进行设置context.setAllowBeanDefinitionOverriding(false);
这种方法如果处理不好,会引起很多麻烦,不推荐。
2、根据ApplicationContextInitializer接口的说明,通过参数配置来改变applicationContext的行为:
1)首先定义一个ApplicationContextInitializer的子类:
2)在配置文件中引用
由ContextLoaderListener调用的配置方式:
由DispatcherServlet调用的配置方式
ContextLoader中部分代码:
public class ContextLoader { public static final String CONTEXT_ID_PARAM = "contextId"; public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation"; public static final String CONTEXT_CLASS_PARAM = "contextClass"; public static final String CONTEXT_INITIALIZER_CLASSES_PARAM = "contextInitializerClasses"; public static final String GLOBAL_INITIALIZER_CLASSES_PARAM = "globalInitializerClasses"; public static final String LOCATOR_FACTORY_SELECTOR_PARAM = "locatorFactorySelector"; public static final String LOCATOR_FACTORY_KEY_PARAM = "parentContextKey"; private static final String INIT_PARAM_DELIMITERS = ",; \t\n"; private static final String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties"; public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { ...... //初始化时调用此方法 configureAndRefreshWebApplicationContext(cwac, servletContext); ...... } protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) { ...... //使用contextConfigLocation参数配置 String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM); if (configLocationParam != null) { wac.setConfigLocation(configLocationParam); } ...... //ContextLoader创建ConfigurableWebApplicationContext customizeContext(sc, wac); wac.refresh(); } protected void customizeContext(ServletContext sc, ConfigurableWebApplicationContext wac) { //处理ApplicationContextInitializer的地方 List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> initializerClasses = determineContextInitializerClasses(sc); for (Class<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerClass : initializerClasses) { ...... this.contextInitializers.add(BeanUtils.instantiateClass(initializerClass)); } AnnotationAwareOrderComparator.sort(this.contextInitializers); for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : this.contextInitializers) { initializer.initialize(wac); } } //返回由globalInitializerClasses和contextInitializerClasses定义的ApplicationContextInitializer列表 protected List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> determineContextInitializerClasses(ServletContext servletContext) { List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> classes = new ArrayList<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>>(); //globalInitializerClasses String globalClassNames = servletContext.getInitParameter(GLOBAL_INITIALIZER_CLASSES_PARAM); if (globalClassNames != null) { for (String className : StringUtils.tokenizeToStringArray(globalClassNames, INIT_PARAM_DELIMITERS)) { classes.add(loadInitializerClass(className)); } } //contextInitializerClasses String localClassNames = servletContext.getInitParameter(CONTEXT_INITIALIZER_CLASSES_PARAM); if (localClassNames != null) { for (String className : StringUtils.tokenizeToStringArray(localClassNames, INIT_PARAM_DELIMITERS)) { classes.add(loadInitializerClass(className)); } } return classes; } @SuppressWarnings("unchecked") private Class<ApplicationContextInitializer<ConfigurableApplicationContext>> loadInitializerClass(String className) { try { Class<?> clazz = ClassUtils.forName(className, ClassUtils.getDefaultClassLoader()); Assert.isAssignable(ApplicationContextInitializer.class, clazz); return (Class<ApplicationContextInitializer<ConfigurableApplicationContext>>) clazz; } catch (ClassNotFoundException ex) { throw new ApplicationContextException("Failed to load context initializer class [" + className + "]", ex); } } }涉及到的ApplicationContextInitializer类:
package org.springframework.context; /** * Callback interface for initializing a Spring {@link ConfigurableApplicationContext} * prior to being {@linkplain ConfigurableApplicationContext#refresh() refreshed}. * * <p>Typically used within web applications that require some programmatic initialization * of the application context. For example, registering property sources or activating * profiles against the {@linkplain ConfigurableApplicationContext#getEnvironment() * context's environment}. See {@code ContextLoader} and {@code FrameworkServlet} support * for declaring a "contextInitializerClasses" context-param and init-param, respectively. * * <p>{@code ApplicationContextInitializer} processors are encouraged to detect * whether Spring's {@link org.springframework.core.Ordered Ordered} interface has been * implemented or if the @{@link org.springframework.core.annotation.Order Order} * annotation is present and to sort instances accordingly if so prior to invocation. * * 回调接口,用于ConfigurableApplicationContext.refresh()刷新前,初始化 * Spring的ConfigurableApplicationContext。 * * 通常用在web应用程序中需要对应用程序上下文做一些程序初始化时。例如:注册property资源文件或者 * 激活对上下文环境的环境配置文件。分别参见ContextLoader和FrameworkServlet,分别通过在<context-param> * 和<init-param>中声明contextInitializerClasses参数来的支持。 * * ApplicationContextInitializer处理器检测是否实现了Ordered接口或者是否有@Order注解的实例存在,以此 * 按声明的顺序进行调用。 * * @author Chris Beams * @since 3.1 * @see org.springframework.web.context.ContextLoader#customizeContext * @see org.springframework.web.context.ContextLoader#CONTEXT_INITIALIZER_CLASSES_PARAM * @see org.springframework.web.servlet.FrameworkServlet#setContextInitializerClasses * @see org.springframework.web.servlet.FrameworkServlet#applyInitializers */ public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> { /** * 初始化给定的应用程序上下文。 * @param applicationContext the application to configure */ void initialize(C applicationContext); }由此可知,可以通过ApplicationContextInitializer更改ConfigurableApplicationContext子类的行为。
举个例子:
XmlWebApplicationContext.setAllowBeanDefinitionOverriding()其默认值为true。如果把此值设置为false,怎么解决?
有两个思路:
1、写org.springframework.web.context.ContextLoaderListener和org.springframework.web.servlet.DispatcherServlet的子类:
在相应的方法中进行设置context.setAllowBeanDefinitionOverriding(false);
这种方法如果处理不好,会引起很多麻烦,不推荐。
2、根据ApplicationContextInitializer接口的说明,通过参数配置来改变applicationContext的行为:
1)首先定义一个ApplicationContextInitializer的子类:
public class MyApplicationContextInitializer implements ApplicationContextInitializer<XmlWebApplicationContext> { public void initialize(XmlWebApplicationContext applicationContext) { //XmlWebApplicationContext是ConfigurableApplicationContext的子类 //由此可以改变applicationContext的默认行为。 applicationContext.setAllowBeanDefinitionOverriding(false); } }
2)在配置文件中引用
由ContextLoaderListener调用的配置方式:
<context-param> <param-name>contextClass</param-name> <param-value>org.springframework.web.context.support.XmlWebApplicationContext</param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:applicationContext.xml</param-value> </context-param> <context-param> <param-name>contextInitializerClasses</param-name> <param-value>MyApplicationContextInitializer</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
由DispatcherServlet调用的配置方式
<servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-servlet.xml</param-value> </init-param> <init-param> <param-name>contextInitializerClasses</param-name> <param-value>MyApplicationContextInitializer</param-value> </init-param> </servlet>通过这种方式,可以改变XmlWebApplicationContext其他的属性,如果有必要的话。
相关文章推荐
- 一个jar包里的网站
- 一个jar包里的网站之文件上传
- 一个jar包里的网站之返回对媒体类型
- Spring和ThreadLocal
- Spring Boot 开发微服务
- Spring AOP动态代理-切面
- Spring整合Quartz(JobDetailBean方式)
- Spring整合Quartz(JobDetailBean方式)
- 模拟Spring的简单实现
- Spring整合WebSocket应用示例(上)
- spring+html5实现安全传输随机数字密码键盘
- Spring中属性注入详解
- 监听器获取Spring配置文件的方法
- Java利用Sping框架编写RPC远程过程调用服务的教程
- springmvc 发送ajax出现中文乱码的解决方法汇总
- SpringMVC框架下JQuery传递并解析Json格式的数据是如何实现的
- 详解Java的MyBatis框架和Spring框架的整合运用
- struts2 spring整合fieldError问题
- spring的jdbctemplate的crud的基类dao