自定义弹簧属性源不会在@Value中解析占位符
问题描述:
我试图构建一个从Zookeeper节点读取其值的Spring 3.1 PropertySource。为了连接到Zookeeper,我使用Netflix的Curator。自定义弹簧属性源不会在@Value中解析占位符
为此,我构建了一个自定义属性源,它从Zookeeper中读取一个属性的值并将其返回。
这个问题有:当我解决这样
ZookeeperPropertySource zkPropertySource = new ZookeeperPropertySource(zkClient);
ctx.getEnvironment().getPropertySources().addLast(zkPropertySource);
ctx.getEnvironment().getProperty("foo"); // returns 'from zookeeper'
然而属性,当我尝试实例,从而具有与@Value注释字段,然后失败豆这工作正常最有可能与Zookeeper无关,但与我注册财产来源和创建豆的方式。
任何有识之士高度赞赏。
更新1:
我创建一个XML文件的应用背景是这样的:
public class Main {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
ctx.registerShutdownHook();
}
}
它连接到动物园管理员类是@Component。
@Component
public class Server {
CuratorFramework zkClient;
public void connectToZookeeper() {
zkClient = ... (curator magic) ...
}
public void registerPropertySource() {
ZookeeperPropertySource zkPropertySource = new ZookeeperPropertySource(zkClient);
ctx.getEnvironment().getPropertySources().addLast(zkPropertySource);
ctx.getEnvironment().getProperty("foo"); // returns 'from zookeeper'
}
@PostConstruct
public void start() {
connectToZookeeper();
registerPropertySource();
MyBean b = ctx.getBean(MyBean.class);
}
}
更新2
这似乎当我使用XML-更少的配置,即@Configuration,@ComponentScan和@PropertySource结合的AnnotationConfigApplicationContext工作。为什么它不适用于ClassPathXmlApplicationContext?
@Configuration
@ComponentScan("com.goleft")
@PropertySource({"classpath:config.properties","classpath:version.properties"})
public class AppConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
答
回答您更新2:这不与你原来的配置工作,这个时候(注册使用@PostConstruct
一个PropertySource),因为PropertySource正在注册很晚了,你的目标bean已经被构造和初始化。
通常,注入占位符是通过在Spring生命周期很早(在此阶段尚未创建bean)的BeanFactoryPostProcessor发生的,并且如果在该阶段注册了PropertySource,则应解决占位符。
但最好的方法是使用一个ApplicationContextInitializer,得到ApplicationContext的一个手柄,并有注册propertySource:
public class CustomInitializer implements ApplicationContextInitializer<ConfigurableWebApplicationContext> {
public void initialize(ConfigurableWebApplicationContext ctx) {
ZookeeperPropertySource zkPropertySource = new ZookeeperPropertySource(zkClient);
ctx.getEnvironment().getPropertySources().addFirst(zkPropertySource);
}
}
能否请您包括AppConfig的代码也在您的更新。 – 2012-08-13 20:35:05
我简化了这个问题,但现在我无法再使用它了。它总是从配置文件加载。嗯,实际上它可以在我的非简化项目中工作,但只能在AppConfig类中使用,并且该属性不存在于config.properties文件中。如何将ApplicationContextInitializer与非webapp一起使用? – magiconair 2012-08-13 21:24:44
是的,你是对的,它有点不同。我已经向您的存储库发送了一个pull请求,其中包含一个针对基于注释和基于xml的应用程序上下文一致行为的测试。 – 2012-08-14 02:12:15