Test case for event listener methods on bean with potentially inactive scope
Also taking the opportunity to refine the "No Scope registered" exception message a bit. Issue: SPR-13681
This commit is contained in:
@@ -334,7 +334,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
|||||||
String scopeName = mbd.getScope();
|
String scopeName = mbd.getScope();
|
||||||
final Scope scope = this.scopes.get(scopeName);
|
final Scope scope = this.scopes.get(scopeName);
|
||||||
if (scope == null) {
|
if (scope == null) {
|
||||||
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
|
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
|
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
|
||||||
@@ -353,8 +353,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
|||||||
}
|
}
|
||||||
catch (IllegalStateException ex) {
|
catch (IllegalStateException ex) {
|
||||||
throw new BeanCreationException(beanName,
|
throw new BeanCreationException(beanName,
|
||||||
"Scope '" + scopeName + "' is not active for the current thread; " +
|
"Scope '" + scopeName + "' is not active for the current thread; consider " +
|
||||||
"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
|
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
|
||||||
ex);
|
ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ import org.junit.rules.ExpectedException;
|
|||||||
|
|
||||||
import org.springframework.aop.framework.Advised;
|
import org.springframework.aop.framework.Advised;
|
||||||
import org.springframework.aop.support.AopUtils;
|
import org.springframework.aop.support.AopUtils;
|
||||||
|
import org.springframework.beans.factory.BeanCreationException;
|
||||||
import org.springframework.beans.factory.BeanInitializationException;
|
import org.springframework.beans.factory.BeanInitializationException;
|
||||||
|
import org.springframework.beans.factory.ObjectFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.PayloadApplicationEvent;
|
import org.springframework.context.PayloadApplicationEvent;
|
||||||
@@ -55,6 +57,7 @@ import org.springframework.core.annotation.Order;
|
|||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.scheduling.annotation.EnableAsync;
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
@@ -238,6 +241,9 @@ public class AnnotationDrivenEventListenerTests {
|
|||||||
assertTrue("bean should be a proxy", proxy instanceof Advised);
|
assertTrue("bean should be a proxy", proxy instanceof Advised);
|
||||||
this.eventCollector.assertNoEventReceived(proxy.getId());
|
this.eventCollector.assertNoEventReceived(proxy.getId());
|
||||||
|
|
||||||
|
this.context.publishEvent(new ContextRefreshedEvent(this.context));
|
||||||
|
this.eventCollector.assertNoEventReceived(proxy.getId());
|
||||||
|
|
||||||
TestEvent event = new TestEvent();
|
TestEvent event = new TestEvent();
|
||||||
this.context.publishEvent(event);
|
this.context.publishEvent(event);
|
||||||
this.eventCollector.assertEvent(proxy.getId(), event);
|
this.eventCollector.assertEvent(proxy.getId(), event);
|
||||||
@@ -252,6 +258,9 @@ public class AnnotationDrivenEventListenerTests {
|
|||||||
assertTrue("bean should be a proxy", proxy instanceof Advised);
|
assertTrue("bean should be a proxy", proxy instanceof Advised);
|
||||||
this.eventCollector.assertNoEventReceived(proxy.getId());
|
this.eventCollector.assertNoEventReceived(proxy.getId());
|
||||||
|
|
||||||
|
this.context.publishEvent(new ContextRefreshedEvent(this.context));
|
||||||
|
this.eventCollector.assertNoEventReceived(proxy.getId());
|
||||||
|
|
||||||
TestEvent event = new TestEvent();
|
TestEvent event = new TestEvent();
|
||||||
this.context.publishEvent(event);
|
this.context.publishEvent(event);
|
||||||
this.eventCollector.assertEvent(proxy.getId(), event);
|
this.eventCollector.assertEvent(proxy.getId(), event);
|
||||||
@@ -266,12 +275,49 @@ public class AnnotationDrivenEventListenerTests {
|
|||||||
assertTrue("bean should be a cglib proxy", AopUtils.isCglibProxy(proxy));
|
assertTrue("bean should be a cglib proxy", AopUtils.isCglibProxy(proxy));
|
||||||
this.eventCollector.assertNoEventReceived(proxy.getId());
|
this.eventCollector.assertNoEventReceived(proxy.getId());
|
||||||
|
|
||||||
|
this.context.publishEvent(new ContextRefreshedEvent(this.context));
|
||||||
|
this.eventCollector.assertNoEventReceived(proxy.getId());
|
||||||
|
|
||||||
TestEvent event = new TestEvent();
|
TestEvent event = new TestEvent();
|
||||||
this.context.publishEvent(event);
|
this.context.publishEvent(event);
|
||||||
this.eventCollector.assertEvent(proxy.getId(), event);
|
this.eventCollector.assertEvent(proxy.getId(), event);
|
||||||
this.eventCollector.assertTotalEventsCount(1);
|
this.eventCollector.assertTotalEventsCount(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void eventListenerWorksWithCustomScope() throws Exception {
|
||||||
|
load(CustomScopeTestBean.class);
|
||||||
|
CustomScope customScope = new CustomScope();
|
||||||
|
this.context.getBeanFactory().registerScope("custom", customScope);
|
||||||
|
|
||||||
|
CustomScopeTestBean proxy = this.context.getBean(CustomScopeTestBean.class);
|
||||||
|
assertTrue("bean should be a cglib proxy", AopUtils.isCglibProxy(proxy));
|
||||||
|
this.eventCollector.assertNoEventReceived(proxy.getId());
|
||||||
|
|
||||||
|
this.context.publishEvent(new ContextRefreshedEvent(this.context));
|
||||||
|
this.eventCollector.assertNoEventReceived(proxy.getId());
|
||||||
|
|
||||||
|
customScope.active = false;
|
||||||
|
this.context.publishEvent(new ContextRefreshedEvent(this.context));
|
||||||
|
customScope.active = true;
|
||||||
|
this.eventCollector.assertNoEventReceived(proxy.getId());
|
||||||
|
|
||||||
|
TestEvent event = new TestEvent();
|
||||||
|
this.context.publishEvent(event);
|
||||||
|
this.eventCollector.assertEvent(proxy.getId(), event);
|
||||||
|
this.eventCollector.assertTotalEventsCount(1);
|
||||||
|
|
||||||
|
try {
|
||||||
|
customScope.active = false;
|
||||||
|
this.context.publishEvent(new TestEvent());
|
||||||
|
fail("Should have thrown IllegalStateException");
|
||||||
|
}
|
||||||
|
catch (BeanCreationException ex) {
|
||||||
|
// expected
|
||||||
|
assertTrue(ex.getCause() instanceof IllegalStateException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void asyncProcessingApplied() throws InterruptedException {
|
public void asyncProcessingApplied() throws InterruptedException {
|
||||||
loadAsync(AsyncEventListener.class);
|
loadAsync(AsyncEventListener.class);
|
||||||
@@ -724,6 +770,17 @@ public class AnnotationDrivenEventListenerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Scope(scopeName = "custom", proxyMode = ScopedProxyMode.TARGET_CLASS)
|
||||||
|
static class CustomScopeTestBean extends AbstractTestEventListener {
|
||||||
|
|
||||||
|
@EventListener
|
||||||
|
public void handleIt(TestEvent event) {
|
||||||
|
collectEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
static class GenericEventListener extends AbstractTestEventListener {
|
static class GenericEventListener extends AbstractTestEventListener {
|
||||||
|
|
||||||
@@ -779,4 +836,40 @@ public class AnnotationDrivenEventListenerTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class CustomScope implements org.springframework.beans.factory.config.Scope {
|
||||||
|
|
||||||
|
public boolean active = true;
|
||||||
|
|
||||||
|
private Object instance = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object get(String name, ObjectFactory<?> objectFactory) {
|
||||||
|
Assert.state(this.active, "Not active");
|
||||||
|
if (this.instance == null) {
|
||||||
|
this.instance = objectFactory.getObject();
|
||||||
|
}
|
||||||
|
return this.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object remove(String name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerDestructionCallback(String name, Runnable callback) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object resolveContextualObject(String key) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getConversationId() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user