spring配置文件标签中resource使用${}占位符获得配置文件的属性值(补充修改版)

一般情况下我们在Spring的配置文件中使用标签是这样的,


因项目需要(最后将这种配置的好处),要配成


其中suffix的值是从application.properties里面获取。

#application.properties文件配置
suffix = name
如果是直接这种写法,在启动时spring报错,无法解析suffix,原因很简单,在import动作时在属性文件加载之前。类似如下这种错误
 IllegalArgumentException: Could not resolve placeholder in string value "${XXXXXX}"

翻看spring源码,ContextLoader

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
        if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
// The application context id is still set to its original default value
// -> assign a more useful id based on available information
            String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
            if (idParam != null) {
                wac.setId(idParam);
            }
            else {
// Generate default id...
                wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
                        ObjectUtils.getDisplayString(sc.getContextPath()));
            }
        }
        wac.setServletContext(sc);
        String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
        if (configLocationParam != null) {
            wac.setConfigLocation(configLocationParam);
        }
 
// The wac environment‘s #initPropertySources will be called in any case when the context
// is refreshed; do it eagerly here to ensure servlet property sources are in place for
// use in any post-processing or initialization that occurs below prior to #refresh
        ConfigurableEnvironment env = wac.getEnvironment();
        if (env instanceof ConfigurableWebEnvironment) {
            ((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
        }
        customizeContext(sc, wac);
        wac.refresh();
    }
    //initPropertySources这个方法可以自己定义属性文件的加载时机。
    @Override
    public void initPropertySources(ServletContext servletContext, ServletConfig servletConfig) {
        WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig);
    }

我们需要在PropertyPlaceholderConfigurer 重载的后置处理器BeanFactoryPostProcessor(修改bean配置信息) 调用postProcessBeanFactory 前加载properties属性文件

因为spring提供了ApplicationContextInitializer这个接口,我们写一个自己的类实现该接口:

public class CustomerApplicationContextInitializer implements ApplicationContextInitializer{
	private static Logger logger = LoggerFactory.getLogger(CustomerApplicationContextInitializer.class);
	@Override
	public void initialize(ConfigurableApplicationContext applicationContext) {
		ResourcePropertySource propertySource = null;
		try {
			propertySource = new ResourcePropertySource("classpath:application.properties");
		} catch (IOException e) {
			logger.error("application.properties is not exists");
		}
		applicationContext.getEnvironment().getPropertySources().addFirst(propertySource);
	}
}

写完 我们需要在 applicationContext.xml配上自己的bean

(com.xxx 自己java包路径)

然后需要配置web.xml


	contextInitializerClasses
	com.xxx.CustomerApplicationContextInitializer

因为在customizeContext(sc, wac);会调用所有的contextInitializerClasses中的initialize方法。

则会在 PropertyPlaceholderConfigurer 继承的BeanFactoryPostProcessor 的postProcessBeanFactory 方法之前加载 properties文件

至此,问题解决了,总结一下分为以下几步

1.提供实现ApplicationContextInitializer接口的实现类
2.在web.xml中配置,见上

3.在spring的主配置文件中使用

这样写好处在与你只需修改.properties配置信息便可以动态实现不同引入加载

你可能感兴趣的:(spring占位符使用)