一、properties文件读取思路
在web环境下,Spring的ApplicationContext
是容器管理的(不仅管理been,还有properties属性文件),通过ContextLoaderListener
载入。要获取ApplicationContext
需要先得到ServletContext
,而得到ServletContext
又要先获取session
。而且每一个要使用ApplicationContext
的地方都要这么做。
但是,通过扩展ContextLoaderListener
,我们可以很方便的获取到ApplicationContext
。
原理十分简单,ContextLoaderListener
类里面有一个叫做contextlnitialized
的方法,这个方法用于初始化context
。
二、操作步骤
我们自己写一个SpringPropertyResourceReader
工具类,里面有一个静态变量applicationContext
,用来存放web环境下的ApplicationContext
的引用,getProperty(key)
的方法就可以读取Spring中加载属性文件的内容了。
1、先写SpringPropertyResourceReader类:
public class SpringPropertyResourceReader {
private static ApplicationContext applicationContext;
//private static ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
static Properties properties = new Properties();
public static ApplicationContext getContext() {
return applicationContext;
}
public static void setContext(ApplicationContext aContext) {
applicationContext = aContext;
}
private static void init() {
AbstractApplicationContext abstractContext = (AbstractApplicationContext) applicationContext;
try {
// get the names of BeanFactoryPostProcessor
String[] postProcessorNames = abstractContext.getBeanNamesForType(BeanFactoryPostProcessor.class,
true, true);
for (String ppName : postProcessorNames) {
// get the specified BeanFactoryPostProcessor
BeanFactoryPostProcessor beanProcessor = (BeanFactoryPostProcessor) abstractContext.getBean(ppName,
BeanFactoryPostProcessor.class);
// check whether the beanFactoryPostProcessor is
// instance of the PropertyResourceConfigurer
// if it is yes then do the process otherwise continue
if (beanProcessor instanceof PropertyResourceConfigurer) {
PropertyResourceConfigurer propertyResourceConfigurer = (PropertyResourceConfigurer) beanProcessor;
// get the method mergeProperties
// in class PropertiesLoaderSupport
Method mergeProperties = PropertiesLoaderSupport.class.getDeclaredMethod(
"mergeProperties");
// get the props
mergeProperties.setAccessible(true);
Properties props = (Properties) mergeProperties.invoke(propertyResourceConfigurer);
// get the method convertProperties
// in class PropertyResourceConfigurer
Method convertProperties = PropertyResourceConfigurer.class.getDeclaredMethod("convertProperties",
Properties.class);
// convert properties
convertProperties.setAccessible(true);
convertProperties.invoke(propertyResourceConfigurer, props);
properties.putAll(props);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static String getProperty(String propertyName) {
if ((applicationContext != null) && properties.isEmpty()) {
init();
}
if (applicationContext == null) {
return null;
}
return properties.getProperty(propertyName);
}
}
2、然后再写ContextLoaderListener的扩展类MyContextLoaderListener
public class MyContextLoaderListener extends ContextLoaderListener {
@Override
public void contextInitialized(ServletContextEvent event) {
super.contextInitialized(event);
ServletContext context = event.getServletContext();
// 获取web环境下的ApplicationContext
ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
// 将ApplicationContext,set到SpringPropertyResourceReader的静态变量context
SpringPropertyResourceReader.setContext(ctx);
}
}
3、在web.xml里面配置spring监听器,用我们刚刚扩展好的MyContextLoaderListener替换以前的ContextLoaderListener:
yourpackage.MyContextLoaderListener
4、在applicationContext.xml中配置加载属性文件的代码
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:scan/job.properties</value>
</list>
</property>
</bean>