一、properties文件讀取思路
在web環(huán)境下,Spring的ApplicationContext是容器管理的(不僅管理been,還有properties屬性文件),通過ContextLoaderListener載入。要獲取ApplicationContext需要先得到ServletContext,而得到ServletContext又要先獲取session。而且每一個要使用ApplicationContext的地方都要這么做。
但是,通過擴展ContextLoaderListener,我們可以很方便的獲取到ApplicationContext。
原理十分簡單,ContextLoaderListener類里面有一個叫做contextlnitialized的方法,這個方法用于初始化context。
二、操作步驟
我們自己寫一個SpringPropertyResourceReader工具類,里面有一個靜態(tài)變量applicationContext,用來存放web環(huán)境下的ApplicationContext的引用,getProperty(key)的方法就可以讀取Spring中加載屬性文件的內(nèi)容了。
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環(huán)境下的ApplicationContext
ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
// 將ApplicationContext,set到SpringPropertyResourceReader的靜態(tài)變量context
SpringPropertyResourceReader.setContext(ctx);
}
}
3、在web.xml里面配置spring監(jiān)聽器,用我們剛剛擴展好的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>