2012-08-12 30 views
5

Próbuję zbudować źródło właściwości Spring 3.1, które odczytuje jego wartości z węzłów Zookeepera. Aby połączyć się z Zookeeperem, używam usługi Curator z Netflix.Niestandardowe źródło właściwości sprężyny nie rozpoznaje symboli zastępczych w @Value

W tym celu zbudowałem niestandardowe źródło właściwości, które odczytuje wartość właściwości od Zookeepera i zwraca ją. Działa to dobrze, gdy jestem rozwiązywania właściwości jak ten

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

jednak, gdy próbuję instancji fasola, który ma pole z adnotacją o @Value potem to się nie powiedzie:

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

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

Problem ten ma najprawdopodobniej nie ma to nic wspólnego z Zookeeperem, ale ze sposobem, w jaki rejestruję źródła nieruchomości i tworzę ziarna.

Każdy wgląd jest bardzo cenny.

Aktualizacja 1:

tworzę kontekst aplikacji z pliku XML tak:

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

Klasa, która łączy się Heca jest @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); 
    } 
} 

Aktualizacja 2

To wydaje się działać, gdy używam konfiguracji XML-mniej, tj @Configuration, @ComponentScan i @PropertySource w połączeniu z AnnotationConfigApplicationContext. Dlaczego nie działa z ClassPathXmlApplicationContext?

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

Odpowiedz

4

Odpowiadając na swojej Update 2: ta nie działa z oryginalnej konfiguracji (rejestracji PropertySource korzystając @PostConstruct), ponieważ PropertySource jest zarejestrowany bardzo późno, przez ten czas twój cel fasola została już wykonana i zainicjowany.

Zazwyczaj iniekcja symboli zastępczych odbywa się za pośrednictwem BeanFactoryPostProcessor, która jest bardzo wczesna w cyklu życia Wiosny (na tym etapie nie utworzono ziaren), a jeśli na tym etapie zarejestrowano zasób PropertySource, należy zastąpić elementy zastępcze.

Najlepszym rozwiązaniem jest jednak użycie ApplicationContextInitializer, uzyskać uchwyt na ApplicationContext i zarejestrować propertySource tam:

public class CustomInitializer implements ApplicationContextInitializer<ConfigurableWebApplicationContext> { 
    public void initialize(ConfigurableWebApplicationContext ctx) { 
     ZookeeperPropertySource zkPropertySource = new ZookeeperPropertySource(zkClient); 
     ctx.getEnvironment().getPropertySources().addFirst(zkPropertySource); 
    } 
} 
+0

Czy możesz zawierać kod AppConfig również w aktualizacji. –

+0

Uprościliśmy problem, ale teraz nie mogę go już uruchomić. Zawsze ładuje się z pliku konfiguracyjnego. Właściwie to działa w moim nie uproszczonym projekcie, ale tylko z klasą AppConfig i gdy właściwość nie istnieje w pliku config.properties. Jak korzystać z ApplicationContextInitializer za pomocą aplikacji innej niż web? – magiconair

+1

Tak, masz rację, działa to trochę inaczej. Wysłałem Ci żądanie ściągnięcia do twojego repozytorium za pomocą testu, który zachowuje się konsekwentnie w kontekście adnotacji i kontekstu aplikacji opartego na języku xml. –

Powiązane problemy