A origem da propriedade de mola personalizada não resolve os marcadores de posição em @Value

Eu estou tentando construir um Spring 3.1 PropertySource que lê seus valores de nós do Zookeeper. Para conectar-se ao Zookeeper, estou usandoCurador da Netflix.

Para isso, criei uma fonte de propriedade personalizada que lê o valor de uma propriedade do Zookeeper e a retorna. Isso funciona bem quando estou resolvendo a propriedade assim

ZookeeperPropertySource zkPropertySource = new ZookeeperPropertySource(zkClient);
ctx.getEnvironment().getPropertySources().addLast(zkPropertySource);
ctx.getEnvironment().getProperty("foo"); // returns 'from zookeeper'

No entanto, quando tento instanciar um bean que possui um campo com uma anotação @Value, isso falha:

@Component
public class MyBean {
    @Value("${foo}") public String foo;
}

MyBean b = ctx.getBean(MyBean.class); // fails with BeanCreationException

Esse problema provavelmente não tem nada a ver com o Zookeeper, mas com a maneira como estou registrando as fontes de propriedade e criando os beans.

Qualquer insight é muito apreciado.

Atualização 1:

Estou criando o contexto do aplicativo a partir de um arquivo XML como este:

public class Main {
    public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        ctx.registerShutdownHook();
    }
}

A classe que se conecta ao Zookeeper é um @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);
    }
}

Atualização 2

Isso parece funcionar quando estou usando uma configuração sem XML, ou seja, @Configuration, @ComponentScan e @PropertySource em combinação com um AnnotationConfigApplicationContext. Por que não funciona com um ClassPathXmlApplicationContext?

@Configuration
@ComponentScan("com.goleft")
@PropertySource({"classpath:config.properties","classpath:version.properties"})
public class AppConfig {
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

questionAnswers(1)

yourAnswerToTheQuestion