diff --git a/docs/modules/ROOT/partials/_configprops.adoc b/docs/modules/ROOT/partials/_configprops.adoc index 45941b98a..e2abc13af 100644 --- a/docs/modules/ROOT/partials/_configprops.adoc +++ b/docs/modules/ROOT/partials/_configprops.adoc @@ -76,8 +76,8 @@ |spring.cloud.loadbalancer.zone | | Spring Cloud LoadBalancer zone. |spring.cloud.refresh.additional-property-sources-to-retain | | Additional property sources to retain during a refresh. Typically only system property sources are retained. This property allows property sources, such as property sources created by EnvironmentPostProcessors to be retained as well. |spring.cloud.refresh.enabled | `+++true+++` | Enables autoconfiguration for the refresh scope and associated features. -|spring.cloud.refresh.extra-refreshable | `+++true+++` | Additional class names for beans to post process into refresh scope. -|spring.cloud.refresh.never-refreshable | `+++true+++` | Comma separated list of class names for beans to never be refreshed or rebound. +|spring.cloud.refresh.extra-refreshable | `+++true+++` | Additional bean names or class names for beans to post process into refresh scope. +|spring.cloud.refresh.never-refreshable | `+++true+++` | Comma separated list of bean names or class names for beans to never be refreshed or rebound. |spring.cloud.refresh.on-restart.enabled | `+++true+++` | Enable refreshing context on start. |spring.cloud.service-registry.auto-registration.enabled | `+++true+++` | Whether service auto-registration is enabled. Defaults to true. |spring.cloud.service-registry.auto-registration.fail-fast | `+++false+++` | Whether startup fails if there is no AutoServiceRegistration. Defaults to false. diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/autoconfigure/RefreshAutoConfiguration.java b/spring-cloud-context/src/main/java/org/springframework/cloud/autoconfigure/RefreshAutoConfiguration.java index 57e26fc04..6f8012189 100644 --- a/spring-cloud-context/src/main/java/org/springframework/cloud/autoconfigure/RefreshAutoConfiguration.java +++ b/spring-cloud-context/src/main/java/org/springframework/cloud/autoconfigure/RefreshAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,6 +63,7 @@ * @author Dave Syer * @author Venil Noronha * @author Olga Maciaszek-Sharma + * @author Yanming Zhou */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass(RefreshScope.class) @@ -209,6 +210,9 @@ private boolean isApplicable(BeanDefinitionRegistry registry, String name, BeanD // Already refresh scoped return false; } + if (this.refreshables.contains(name)) { + return true; + } String type = definition.getBeanClassName(); if (!StringUtils.hasText(type) && registry instanceof BeanFactory) { Class cls = ((BeanFactory) registry).getType(name); 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 ca2e9d798..a2359c74d 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,6 +47,7 @@ * the @ConfigurationProperties bean. * * @author Dave Syer + * @author Yanming Zhou * @see RefreshScope for a deeper and optionally more focused refresh of bean components. * */ @@ -131,7 +132,7 @@ private boolean rebind(String name, ApplicationContext appContext) { // 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())) { + if (getNeverRefreshable().contains(bean.getClass().getName()) || getNeverRefreshable().contains(name)) { return false; // ignore } appContext.getAutowireCapableBeanFactory().destroyBean(bean); diff --git a/spring-cloud-context/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-context/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 448ce8fea..ff535a767 100644 --- a/spring-cloud-context/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-context/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -39,13 +39,13 @@ { "name": "spring.cloud.refresh.extra-refreshable", "type": "java.util.Set", - "description": "Additional class names for beans to post process into refresh scope.", + "description": "Additional bean names or class names for beans to post process into refresh scope.", "defaultValue": true }, { "name": "spring.cloud.refresh.never-refreshable", "type": "java.lang.String", - "description": "Comma separated list of class names for beans to never be refreshed or rebound.", + "description": "Comma separated list of bean names or class names for beans to never be refreshed or rebound.", "defaultValue": true }, { diff --git a/spring-cloud-context/src/test/java/org/springframework/cloud/autoconfigure/RefreshAutoConfigurationTests.java b/spring-cloud-context/src/test/java/org/springframework/cloud/autoconfigure/RefreshAutoConfigurationTests.java index 03d30c1fa..4786f2445 100644 --- a/spring-cloud-context/src/test/java/org/springframework/cloud/autoconfigure/RefreshAutoConfigurationTests.java +++ b/spring-cloud-context/src/test/java/org/springframework/cloud/autoconfigure/RefreshAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,6 +41,7 @@ /** * @author Dave Syer * @author Olga Maciaszek-Sharma + * @author Yanming Zhou */ @ExtendWith(OutputCaptureExtension.class) class RefreshAutoConfigurationTests { @@ -79,7 +80,7 @@ void refreshables() { } @Test - public void extraRefreshables() { + public void extraRefreshableWithClassName() { try (ConfigurableApplicationContext context = getApplicationContext(WebApplicationType.NONE, Config.class, "sealedconfig.foo=bar", "spring.cloud.refresh.extra-refreshable:" + SealedConfigProps.class.getName())) { @@ -89,7 +90,17 @@ public void extraRefreshables() { } @Test - void neverRefreshable() { + public void extraRefreshableWithBeanName() { + String beanName = "sealedconfig-" + SealedConfigProps.class.getName(); + try (ConfigurableApplicationContext context = getApplicationContext(WebApplicationType.NONE, Config.class, + "sealedconfig.foo=bar", "spring.cloud.refresh.extra-refreshable:" + beanName)) { + context.getBean(SealedConfigProps.class); + context.getBean(ContextRefresher.class).refresh(); + } + } + + @Test + void neverRefreshableWithClassName() { try (ConfigurableApplicationContext context = getApplicationContext(WebApplicationType.NONE, Config.class, "countingconfig.foo=bar", "spring.cloud.refresh.never-refreshable:" + CountingConfigProps.class.getName())) { @@ -99,6 +110,17 @@ void neverRefreshable() { } } + @Test + void neverRefreshableWithBeanName() { + String beanName = "countingconfig-" + CountingConfigProps.class.getName(); + try (ConfigurableApplicationContext context = getApplicationContext(WebApplicationType.NONE, Config.class, + "countingconfig.foo=bar", "spring.cloud.refresh.never-refreshable:" + beanName)) { + CountingConfigProps configProps = context.getBean(CountingConfigProps.class); + context.getBean(ContextRefresher.class).refresh(); + assertThat(configProps.count).as("config props was rebound when it should not have been").hasValue(1); + } + } + @Test void refreshScopeLifecylePresentByDefault() { new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(RefreshAutoConfiguration.class))