Ignore resolved bean from non-active scope in getIfAvailable/getIfUnique

Closes gh-24822
This commit is contained in:
Juergen Hoeller
2020-05-13 19:25:20 +02:00
parent a3c5625d4e
commit 5de6ae6fca
7 changed files with 239 additions and 52 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 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.
@@ -23,8 +23,11 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanCurrentlyInCreationException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.ScopeNotActiveException;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.beans.testfixture.beans.CountingTestBean;
import org.springframework.beans.testfixture.beans.DerivedTestBean;
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.context.expression.StandardBeanExpressionResolver;
@@ -33,6 +36,7 @@ import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.springframework.beans.factory.config.AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
/**
* @author Rob Harrop
@@ -47,7 +51,7 @@ public class RequestScopeTests {
@BeforeEach
public void setup() throws Exception {
public void setup() {
this.beanFactory.registerScope("request", new RequestScope());
this.beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory);
@@ -62,7 +66,7 @@ public class RequestScopeTests {
@Test
public void getFromScope() throws Exception {
public void getFromScope() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setContextPath("/path");
RequestAttributes requestAttributes = new ServletRequestAttributes(request);
@@ -77,7 +81,7 @@ public class RequestScopeTests {
}
@Test
public void destructionAtRequestCompletion() throws Exception {
public void destructionAtRequestCompletion() {
MockHttpServletRequest request = new MockHttpServletRequest();
ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
RequestContextHolder.setRequestAttributes(requestAttributes);
@@ -93,7 +97,7 @@ public class RequestScopeTests {
}
@Test
public void getFromFactoryBeanInScope() throws Exception {
public void getFromFactoryBeanInScope() {
MockHttpServletRequest request = new MockHttpServletRequest();
RequestAttributes requestAttributes = new ServletRequestAttributes(request);
RequestContextHolder.setRequestAttributes(requestAttributes);
@@ -107,7 +111,7 @@ public class RequestScopeTests {
}
@Test
public void circleLeadsToException() throws Exception {
public void circleLeadsToException() {
MockHttpServletRequest request = new MockHttpServletRequest();
RequestAttributes requestAttributes = new ServletRequestAttributes(request);
RequestContextHolder.setRequestAttributes(requestAttributes);
@@ -143,7 +147,7 @@ public class RequestScopeTests {
}
@Test
public void requestScopedInnerBeanDestroyedWhileContainedBySingleton() throws Exception {
public void requestScopedInnerBeanDestroyedWhileContainedBySingleton() {
MockHttpServletRequest request = new MockHttpServletRequest();
ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
RequestContextHolder.setRequestAttributes(requestAttributes);
@@ -160,4 +164,31 @@ public class RequestScopeTests {
assertThat(outer1.wasDestroyed()).isFalse();
}
@Test
public void scopeNotAvailable() {
assertThatExceptionOfType(ScopeNotActiveException.class).isThrownBy(
() -> this.beanFactory.getBean(CountingTestBean.class));
ObjectProvider<CountingTestBean> beanProvider = this.beanFactory.getBeanProvider(CountingTestBean.class);
assertThatExceptionOfType(ScopeNotActiveException.class).isThrownBy(beanProvider::getObject);
assertThat(beanProvider.getIfAvailable()).isNull();
assertThat(beanProvider.getIfUnique()).isNull();
ObjectProvider<CountingTestBean> provider =
((ProviderBean) this.beanFactory.createBean(ProviderBean.class, AUTOWIRE_CONSTRUCTOR, false)).provider;
assertThatExceptionOfType(ScopeNotActiveException.class).isThrownBy(provider::getObject);
assertThat(provider.getIfAvailable()).isNull();
assertThat(provider.getIfUnique()).isNull();
}
public static class ProviderBean {
public ObjectProvider<CountingTestBean> provider;
public ProviderBean(ObjectProvider<CountingTestBean> provider) {
this.provider = provider;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 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.
@@ -20,10 +20,13 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.ScopeNotActiveException;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.beans.testfixture.beans.CountingTestBean;
import org.springframework.beans.testfixture.beans.DerivedTestBean;
import org.springframework.beans.testfixture.beans.ITestBean;
import org.springframework.beans.testfixture.beans.TestBean;
@@ -32,6 +35,8 @@ import org.springframework.core.io.ClassPathResource;
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.springframework.beans.factory.config.AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
/**
* @author Juergen Hoeller
@@ -51,7 +56,7 @@ public class RequestScopedProxyTests {
@Test
public void testGetFromScope() throws Exception {
public void testGetFromScope() {
String name = "requestScopedObject";
TestBean bean = (TestBean) this.beanFactory.getBean(name);
assertThat(AopUtils.isCglibProxy(bean)).isTrue();
@@ -76,7 +81,7 @@ public class RequestScopedProxyTests {
}
@Test
public void testGetFromScopeThroughDynamicProxy() throws Exception {
public void testGetFromScopeThroughDynamicProxy() {
String name = "requestScopedProxy";
ITestBean bean = (ITestBean) this.beanFactory.getBean(name);
// assertTrue(AopUtils.isJdkDynamicProxy(bean));
@@ -101,7 +106,7 @@ public class RequestScopedProxyTests {
}
@Test
public void testDestructionAtRequestCompletion() throws Exception {
public void testDestructionAtRequestCompletion() {
String name = "requestScopedDisposableObject";
DerivedTestBean bean = (DerivedTestBean) this.beanFactory.getBean(name);
assertThat(AopUtils.isCglibProxy(bean)).isTrue();
@@ -127,7 +132,7 @@ public class RequestScopedProxyTests {
}
@Test
public void testGetFromFactoryBeanInScope() throws Exception {
public void testGetFromFactoryBeanInScope() {
String name = "requestScopedFactoryBean";
TestBean bean = (TestBean) this.beanFactory.getBean(name);
assertThat(AopUtils.isCglibProxy(bean)).isTrue();
@@ -149,7 +154,7 @@ public class RequestScopedProxyTests {
}
@Test
public void testGetInnerBeanFromScope() throws Exception {
public void testGetInnerBeanFromScope() {
TestBean bean = (TestBean) this.beanFactory.getBean("outerBean");
assertThat(AopUtils.isAopProxy(bean)).isFalse();
assertThat(AopUtils.isCglibProxy(bean.getSpouse())).isTrue();
@@ -173,7 +178,7 @@ public class RequestScopedProxyTests {
}
@Test
public void testGetAnonymousInnerBeanFromScope() throws Exception {
public void testGetAnonymousInnerBeanFromScope() {
TestBean bean = (TestBean) this.beanFactory.getBean("outerBean");
assertThat(AopUtils.isAopProxy(bean)).isFalse();
assertThat(AopUtils.isCglibProxy(bean.getSpouse())).isTrue();
@@ -199,4 +204,31 @@ public class RequestScopedProxyTests {
}
}
@Test
public void scopeNotAvailable() {
assertThatExceptionOfType(ScopeNotActiveException.class).isThrownBy(
() -> this.beanFactory.getBean(CountingTestBean.class).absquatulate());
final ObjectProvider<CountingTestBean> beanProvider = this.beanFactory.getBeanProvider(CountingTestBean.class);
assertThatExceptionOfType(ScopeNotActiveException.class).isThrownBy(() -> beanProvider.getObject().absquatulate());
beanProvider.ifAvailable(TestBean::absquatulate);
beanProvider.ifUnique(TestBean::absquatulate);
final ObjectProvider<CountingTestBean> provider =
((ProviderBean) this.beanFactory.createBean(ProviderBean.class, AUTOWIRE_CONSTRUCTOR, false)).provider;
assertThatExceptionOfType(ScopeNotActiveException.class).isThrownBy(() -> provider.getObject().absquatulate());
provider.ifAvailable(TestBean::absquatulate);
provider.ifUnique(TestBean::absquatulate);
}
public static class ProviderBean {
public ObjectProvider<CountingTestBean> provider;
public ProviderBean(ObjectProvider<CountingTestBean> provider) {
this.provider = provider;
}
}
}

View File

@@ -1,8 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="requestScopedObject" class="org.springframework.beans.testfixture.beans.TestBean" scope="request">
<property name="name" value="#{request.contextPath}"/>
@@ -12,6 +11,8 @@
<bean id="requestScopedFactoryBean" class="org.springframework.beans.testfixture.beans.factory.DummyFactory" scope="request"/>
<bean id="requestScopedUniqueBean" class="org.springframework.beans.testfixture.beans.CountingTestBean" scope="request"/>
<bean id="requestScopedObjectCircle1" class="org.springframework.beans.testfixture.beans.TestBean" scope="request">
<property name="spouse" ref="requestScopedObjectCircle2"/>
</bean>
@@ -20,22 +21,22 @@
<property name="spouse" ref="requestScopedObjectCircle1"/>
</bean>
<bean id="requestScopedOuterBean" class="org.springframework.beans.testfixture.beans.DerivedTestBean" scope="request">
<property name="name" value="outer"/>
<property name="spouse">
<bean class="org.springframework.beans.testfixture.beans.DerivedTestBean">
<property name="name" value="inner"/>
</bean>
</property>
</bean>
<bean id="requestScopedOuterBean" class="org.springframework.beans.testfixture.beans.DerivedTestBean" scope="request">
<property name="name" value="outer"/>
<property name="spouse">
<bean class="org.springframework.beans.testfixture.beans.DerivedTestBean">
<property name="name" value="inner"/>
</bean>
</property>
</bean>
<bean id="singletonOuterBean" class="org.springframework.beans.testfixture.beans.DerivedTestBean" lazy-init="true">
<property name="name" value="outer"/>
<property name="spouse">
<bean class="org.springframework.beans.testfixture.beans.DerivedTestBean" scope="request">
<property name="name" value="inner"/>
</bean>
</property>
</bean>
<bean id="singletonOuterBean" class="org.springframework.beans.testfixture.beans.DerivedTestBean" lazy-init="true">
<property name="name" value="outer"/>
<property name="spouse">
<bean class="org.springframework.beans.testfixture.beans.DerivedTestBean" scope="request">
<property name="name" value="inner"/>
</bean>
</property>
</bean>
</beans>

View File

@@ -24,6 +24,10 @@
<aop:scoped-proxy/>
</bean>
<bean id="requestScopedUniqueBean" class="org.springframework.beans.testfixture.beans.CountingTestBean" scope="request">
<aop:scoped-proxy/>
</bean>
<bean id="requestScopedObjectCircle1" class="org.springframework.beans.testfixture.beans.TestBean" scope="request">
<aop:scoped-proxy/>
<property name="spouse" ref="requestScopedObjectCircle2"/>