2012-08-12 60 views
5

我试图构建一个从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(); 
    } 
} 

回答

4

回答您更新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); 
    } 
} 
+0

能否请您包括AppConfig的代码也在您的更新。 – 2012-08-13 20:35:05

+0

我简化了这个问题,但现在我无法再使用它了。它总是从配置文件加载。嗯,实际上它可以在我的非简化项目中工作,但只能在AppConfig类中使用,并且该属性不存在于config.properties文件中。如何将ApplicationContextInitializer与非webapp一起使用? – magiconair 2012-08-13 21:24:44

+1

是的,你是对的,它有点不同。我已经向您的存储库发送了一个pull请求,其中包含一个针对基于注释和基于xml的应用程序上下文一致行为的测试。 – 2012-08-14 02:12:15