Initialize beans after rebinding as necessary

On startup a bean will be bound by the
ConfigurationPropertiesBindingPostProcessor and then initialized
by the ApplicationContext. The ConfigurationPropertiesRebinder
does the binding but not the initialization (until this change).

Fixes gh-80
This commit is contained in:
Dave Syer
2015-02-05 14:24:18 +01:00
parent a0b9fc6ced
commit 9e35f60d97
2 changed files with 32 additions and 4 deletions

View File

@@ -25,12 +25,14 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.context.properties.ConfigurationBeanFactoryMetaData;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.stereotype.Component;
/**
@@ -39,7 +41,8 @@ import org.springframework.stereotype.Component;
*/
@Component
@ManagedResource
public class ConfigurationPropertiesRebinder implements BeanPostProcessor, ApplicationListener<EnvironmentChangeEvent> {
public class ConfigurationPropertiesRebinder implements BeanPostProcessor,
ApplicationListener<EnvironmentChangeEvent>, ApplicationContextAware {
private ConfigurationBeanFactoryMetaData metaData;
@@ -52,6 +55,14 @@ public class ConfigurationPropertiesRebinder implements BeanPostProcessor, Appli
private Map<String, Object> beans = new HashMap<String, Object>();
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
/**
* @param beans the bean meta data to set
*/
@@ -93,13 +104,17 @@ public class ConfigurationPropertiesRebinder implements BeanPostProcessor, Appli
@ManagedOperation
public void rebind(String name) {
binder.postProcessBeforeInitialization(beans.get(name), name);
if (applicationContext != null) {
applicationContext.getAutowireCapableBeanFactory().initializeBean(
beans.get(name), name);
}
}
@ManagedAttribute
public Set<String> getBeanNames() {
return new HashSet<String>(beans.keySet());
}
@Override
public void onApplicationEvent(EnvironmentChangeEvent event) {
rebind();

View File

@@ -17,6 +17,8 @@ package org.springframework.cloud.context.properties;
import static org.junit.Assert.assertEquals;
import javax.annotation.PostConstruct;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -55,17 +57,20 @@ public class ConfigurationPropertiesRebinderIntegrationTests {
EnvironmentTestUtils.addEnvironment(environment, "message:Foo");
// ...but don't refresh, so the bean stays the same:
assertEquals("Hello scope!", properties.getMessage());
assertEquals(1, properties.getCount());
}
@Test
@DirtiesContext
public void testRefresh() throws Exception {
assertEquals(1, properties.getCount());
assertEquals("Hello scope!", properties.getMessage());
// Change the dynamic property source...
EnvironmentTestUtils.addEnvironment(environment, "message:Foo");
// ...and then refresh, so the bean is re-initialized:
rebinder.rebind();
assertEquals("Foo", properties.getMessage());
assertEquals(2, properties.getCount());
}
@Configuration
@@ -84,6 +89,10 @@ public class ConfigurationPropertiesRebinderIntegrationTests {
protected static class TestProperties {
private String message;
private int delay;
private int count = 0;
public int getCount() {
return count;
}
public String getMessage() {
return message;
}
@@ -96,6 +105,10 @@ public class ConfigurationPropertiesRebinderIntegrationTests {
public void setDelay(int delay) {
this.delay = delay;
}
@PostConstruct
public void init() {
this.count ++;
}
}
}