From 28b27dfac70fbb9d10c788ec91712677c481f165 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Wed, 3 Dec 2014 11:36:47 -0700 Subject: [PATCH] add RefreshScopeRefreshedEvent when RefreshScope.refresh*() is called. This is so apps can do something when a POST is received at /refresh even if the environment hasn't changed. --- .../context/scope/refresh/RefreshScope.java | 18 +++++++++++--- .../refresh/RefreshScopeRefreshedEvent.java | 24 +++++++++++++++++++ .../refresh/RefreshScopeIntegrationTests.java | 22 +++++++++++++---- 3 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 spring-cloud-config-client/src/main/java/org/springframework/cloud/context/scope/refresh/RefreshScopeRefreshedEvent.java diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/context/scope/refresh/RefreshScope.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/context/scope/refresh/RefreshScope.java index 5e9f3073..b7429e5b 100644 --- a/spring-cloud-config-client/src/main/java/org/springframework/cloud/context/scope/refresh/RefreshScope.java +++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/context/scope/refresh/RefreshScope.java @@ -15,6 +15,9 @@ package org.springframework.cloud.context.scope.refresh; import java.io.Serializable; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.cloud.context.scope.GenericScope; @@ -54,7 +57,10 @@ import org.springframework.cloud.context.scope.GenericScope; * */ @ManagedResource -public class RefreshScope extends GenericScope { +public class RefreshScope extends GenericScope implements ApplicationContextAware { + + protected static final String SCOPED_TARGET_PREFIX = "scopedTarget."; + private ApplicationContext context; /** * Create a scope instance and give it the default name: "refresh". @@ -66,17 +72,23 @@ public class RefreshScope extends GenericScope { @ManagedOperation(description = "Dispose of the current instance of bean name provided and force a refresh on next method execution.") public void refresh(String name) { - if (!name.startsWith("scopedTarget.")) { + if (!name.startsWith(SCOPED_TARGET_PREFIX)) { // User wants to refresh the bean with this name but that isn't the one in the cache... - name = "scopedTarget." + name; + name = SCOPED_TARGET_PREFIX + name; } // Ensure lifecycle is finished if bean was disposable super.destroy(name); + context.publishEvent(new RefreshScopeRefreshedEvent(name)); } @ManagedOperation(description = "Dispose of the current instance of all beans in this scope and force a refresh on next method execution.") public void refreshAll() { super.destroy(); + context.publishEvent(new RefreshScopeRefreshedEvent()); } + @Override + public void setApplicationContext(ApplicationContext context) throws BeansException { + this.context = context; + } } diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/context/scope/refresh/RefreshScopeRefreshedEvent.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/context/scope/refresh/RefreshScopeRefreshedEvent.java new file mode 100644 index 00000000..4cfe1753 --- /dev/null +++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/context/scope/refresh/RefreshScopeRefreshedEvent.java @@ -0,0 +1,24 @@ +package org.springframework.cloud.context.scope.refresh; + +import org.springframework.context.ApplicationEvent; + +/** + * @author Spencer Gibb + */ +public class RefreshScopeRefreshedEvent extends ApplicationEvent { + public static final String DEFAULT_NAME = "__refreshAll__"; + private String name; + + public RefreshScopeRefreshedEvent() { + this(DEFAULT_NAME); + } + + public RefreshScopeRefreshedEvent(String name) { + super(name); + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/RefreshScopeIntegrationTests.java b/spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/RefreshScopeIntegrationTests.java index ad7edb01..02886c47 100644 --- a/spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/RefreshScopeIntegrationTests.java +++ b/spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/RefreshScopeIntegrationTests.java @@ -15,10 +15,6 @@ */ package org.springframework.cloud.context.scope.refresh; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertTrue; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.Before; @@ -35,6 +31,7 @@ import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.cloud.context.scope.refresh.RefreshScopeIntegrationTests.TestConfiguration; +import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -43,6 +40,8 @@ import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import static org.junit.Assert.*; + @SpringApplicationConfiguration(classes = TestConfiguration.class) @RunWith(SpringJUnit4ClassRunner.class) public class RefreshScopeIntegrationTests { @@ -88,6 +87,9 @@ public class RefreshScopeIntegrationTests { assertEquals(2, ExampleService.getInitCount()); assertEquals(1, ExampleService.getDestroyCount()); assertNotSame(id1, id2); + assertNotNull(ExampleService.event); + assertEquals(RefreshScopeRefreshedEvent.DEFAULT_NAME, + ExampleService.event.getName()); } @Test @@ -104,6 +106,10 @@ public class RefreshScopeIntegrationTests { assertEquals(2, ExampleService.getInitCount()); assertEquals(1, ExampleService.getDestroyCount()); assertNotSame(id1, id2); + assertNotNull(ExampleService.event); + assertEquals( + org.springframework.cloud.context.scope.refresh.RefreshScope.SCOPED_TARGET_PREFIX + + "service", ExampleService.event.getName()); } public static interface Service { @@ -113,12 +119,13 @@ public class RefreshScopeIntegrationTests { } public static class ExampleService implements Service, InitializingBean, - DisposableBean { + DisposableBean, ApplicationListener { private static Log logger = LogFactory.getLog(ExampleService.class); private volatile static int initCount = 0; private volatile static int destroyCount = 0; + private volatile static RefreshScopeRefreshedEvent event; private String message = null; private volatile long delay = 0; @@ -141,6 +148,7 @@ public class RefreshScopeIntegrationTests { public static void reset() { initCount = 0; destroyCount = 0; + event = null; } public static int getInitCount() { @@ -168,6 +176,10 @@ public class RefreshScopeIntegrationTests { return message; } + @Override + public void onApplicationEvent(RefreshScopeRefreshedEvent e) { + event = e; + } } @Configuration