diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/context/properties/ConfigurationPropertiesRebinder.java b/spring-cloud-context/src/main/java/org/springframework/cloud/context/properties/ConfigurationPropertiesRebinder.java index 2f83e237..b79d5a7b 100644 --- a/spring-cloud-context/src/main/java/org/springframework/cloud/context/properties/ConfigurationPropertiesRebinder.java +++ b/spring-cloud-context/src/main/java/org/springframework/cloud/context/properties/ConfigurationPropertiesRebinder.java @@ -21,8 +21,10 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import org.springframework.aop.scope.ScopedProxyUtils; import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.cloud.context.environment.EnvironmentChangeEvent; @@ -92,31 +94,7 @@ public class ConfigurationPropertiesRebinder ApplicationContext appContext = this.applicationContext; while (appContext != null) { if (appContext.containsLocalBean(name)) { - try { - Object bean = appContext.getBean(name); - if (AopUtils.isAopProxy(bean)) { - bean = ProxyUtils.getTargetObject(bean); - } - if (bean != null) { - // TODO: determine a more general approach to fix this. - // see - // https://github.com/spring-cloud/spring-cloud-commons/issues/571 - if (getNeverRefreshable().contains(bean.getClass().getName())) { - return false; // ignore - } - appContext.getAutowireCapableBeanFactory().destroyBean(bean); - appContext.getAutowireCapableBeanFactory().initializeBean(bean, name); - return true; - } - } - catch (RuntimeException e) { - this.errors.put(name, e); - throw e; - } - catch (Exception e) { - this.errors.put(name, e); - throw new IllegalStateException("Cannot rebind to " + name, e); - } + return rebind(name, appContext); } else { appContext = appContext.getParent(); @@ -125,6 +103,53 @@ public class ConfigurationPropertiesRebinder return false; } + /** + * WARNING: This method rebinds beans from any context in the hierarchy using the main + * application context. + * @param type bean type to rebind. + * @return true, if successful. + */ + public boolean rebind(Class type) { + String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.applicationContext, type); + if (beanNamesForType.length > 0) { + String name = beanNamesForType[0]; + if (ScopedProxyUtils.isScopedTarget(name)) { + name = ScopedProxyUtils.getOriginalBeanName(name); + } + return rebind(name, this.applicationContext); + } + return false; + } + + private boolean rebind(String name, ApplicationContext appContext) { + try { + Object bean = appContext.getBean(name); + if (AopUtils.isAopProxy(bean)) { + bean = ProxyUtils.getTargetObject(bean); + } + if (bean != null) { + // TODO: determine a more general approach to fix this. + // see + // https://github.com/spring-cloud/spring-cloud-commons/issues/571 + if (getNeverRefreshable().contains(bean.getClass().getName())) { + return false; // ignore + } + appContext.getAutowireCapableBeanFactory().destroyBean(bean); + appContext.getAutowireCapableBeanFactory().initializeBean(bean, name); + return true; + } + } + catch (RuntimeException e) { + this.errors.put(name, e); + throw e; + } + catch (Exception e) { + this.errors.put(name, e); + throw new IllegalStateException("Cannot rebind to " + name, e); + } + return false; + } + @ManagedAttribute public Set getNeverRefreshable() { String neverRefresh = this.applicationContext.getEnvironment() diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/context/scope/refresh/RefreshScope.java b/spring-cloud-context/src/main/java/org/springframework/cloud/context/scope/refresh/RefreshScope.java index 44018606..b08dfa0f 100644 --- a/spring-cloud-context/src/main/java/org/springframework/cloud/context/scope/refresh/RefreshScope.java +++ b/spring-cloud-context/src/main/java/org/springframework/cloud/context/scope/refresh/RefreshScope.java @@ -20,6 +20,7 @@ import java.io.Serializable; import org.springframework.aop.scope.ScopedProxyUtils; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.cloud.context.scope.GenericScope; @@ -130,6 +131,20 @@ public class RefreshScope extends GenericScope } } + /** + * WARNING: This method refreshes beans from any context in the hierarchy using the + * main application context. + * @param type bean type to rebind. + * @return true, if successful. + */ + public boolean refresh(Class type) { + String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.context, type); + if (beanNamesForType.length > 0) { + return refresh(beanNamesForType[0]); + } + return false; + } + @ManagedOperation(description = "Dispose of the current instance of bean name " + "provided and force a refresh on next method execution.") public boolean refresh(String name) {