Sync with 3.1.x
* 3.1.x: (61 commits) Compensate for changes in JDK 7 Introspector Avoid 'type mismatch' errors in ExtendedBeanInfo Polish ExtendedBeanInfo and tests Infer AnnotationAttributes method return types Minor fix in MVC reference doc chapter Hibernate 4.1 etc TypeDescriptor equals implementation accepts annotations in any order "setBasenames" uses varargs now (for programmatic setup; SPR-9106) @ActiveProfiles mechanism works with @ImportResource as well (SPR-8992 polishing clarified Resource's "getFilename" method to consistently return null substituteNamedParameters detects and unwraps SqlParameterValue object Replace spaces with tabs Consider security in ClassUtils#getMostSpecificMethod Adding null check for username being null. Improvements for registering custom SQL exception translators in app c SPR-7680 Adding QueryTimeoutException to the DataAccessException hiera Minor polish in WebMvcConfigurationSupport Detect overridden boolean getters in ExtendedBeanInfo Polish ExtendedBeanInfoTests ...
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -16,11 +16,12 @@
|
||||
|
||||
package org.springframework.beans;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
import test.beans.CustomEnum;
|
||||
import test.beans.GenericBean;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
@@ -109,4 +110,14 @@ public final class BeanWrapperEnumTests {
|
||||
assertTrue(gb.getCustomEnumSet().contains(CustomEnum.VALUE_2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomEnumSetWithGetterSetterMismatch() {
|
||||
GenericBean<?> gb = new GenericBean<Object>();
|
||||
BeanWrapper bw = new BeanWrapperImpl(gb);
|
||||
bw.setPropertyValue("customEnumSetMismatch", new String[] {"VALUE_1", "VALUE_2"});
|
||||
assertEquals(2, gb.getCustomEnumSet().size());
|
||||
assertTrue(gb.getCustomEnumSet().contains(CustomEnum.VALUE_1));
|
||||
assertTrue(gb.getCustomEnumSet().contains(CustomEnum.VALUE_2));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -16,13 +16,13 @@
|
||||
|
||||
package org.springframework.beans;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.lessThan;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.beans.BeanInfo;
|
||||
@@ -32,9 +32,10 @@ import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.ExtendedBeanInfo.PropertyDescriptorComparator;
|
||||
import org.springframework.core.JdkVersion;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import test.beans.TestBean;
|
||||
|
||||
@@ -429,11 +430,12 @@ public class ExtendedBeanInfoTests {
|
||||
}
|
||||
|
||||
BeanInfo bi = Introspector.getBeanInfo(C.class);
|
||||
BeanInfo ebi = new ExtendedBeanInfo(Introspector.getBeanInfo(C.class));
|
||||
|
||||
assertThat(hasIndexedReadMethodForProperty(bi, "foos"), is(true));
|
||||
// interesting! standard Inspector picks up non-void return types on indexed write methods by default
|
||||
assertThat(hasIndexedWriteMethodForProperty(bi, "foos"), is(true));
|
||||
assertThat(hasIndexedWriteMethodForProperty(bi, "foos"), is(trueUntilJdk17()));
|
||||
|
||||
BeanInfo ebi = new ExtendedBeanInfo(Introspector.getBeanInfo(C.class));
|
||||
|
||||
assertThat(hasIndexedReadMethodForProperty(ebi, "foos"), is(true));
|
||||
assertThat(hasIndexedWriteMethodForProperty(ebi, "foos"), is(true));
|
||||
@@ -456,13 +458,12 @@ public class ExtendedBeanInfoTests {
|
||||
assertThat(hasIndexedReadMethodForProperty(bi, "foos"), is(true));
|
||||
assertThat(hasWriteMethodForProperty(bi, "foos"), is(false));
|
||||
// again as above, standard Inspector picks up non-void return types on indexed write methods by default
|
||||
assertThat(hasIndexedWriteMethodForProperty(bi, "foos"), is(true));
|
||||
assertThat(hasIndexedWriteMethodForProperty(bi, "foos"), is(trueUntilJdk17()));
|
||||
|
||||
BeanInfo ebi = new ExtendedBeanInfo(Introspector.getBeanInfo(C.class));
|
||||
|
||||
assertThat(hasIndexedReadMethodForProperty(bi, "foos"), is(true));
|
||||
assertThat(hasWriteMethodForProperty(bi, "foos"), is(true));
|
||||
// again as above, standard Inspector picks up non-void return types on indexed write methods by default
|
||||
assertThat(hasIndexedWriteMethodForProperty(bi, "foos"), is(true));
|
||||
|
||||
assertThat(hasIndexedReadMethodForProperty(ebi, "foos"), is(true));
|
||||
@@ -550,17 +551,17 @@ public class ExtendedBeanInfoTests {
|
||||
assertThat(hasReadMethodForProperty(bi, "dateFormat"), is(false));
|
||||
assertThat(hasWriteMethodForProperty(bi, "dateFormat"), is(false));
|
||||
assertThat(hasIndexedReadMethodForProperty(bi, "dateFormat"), is(false));
|
||||
assertThat(hasIndexedWriteMethodForProperty(bi, "dateFormat"), is(true));
|
||||
assertThat(hasIndexedWriteMethodForProperty(bi, "dateFormat"), is(trueUntilJdk17()));
|
||||
|
||||
ExtendedBeanInfo ebi = new ExtendedBeanInfo(bi);
|
||||
|
||||
assertThat(hasReadMethodForProperty(bi, "dateFormat"), is(false));
|
||||
assertThat(hasWriteMethodForProperty(bi, "dateFormat"), is(true));
|
||||
assertThat(hasWriteMethodForProperty(bi, "dateFormat"), is(false));
|
||||
assertThat(hasIndexedReadMethodForProperty(bi, "dateFormat"), is(false));
|
||||
assertThat(hasIndexedWriteMethodForProperty(bi, "dateFormat"), is(true));
|
||||
assertThat(hasIndexedWriteMethodForProperty(bi, "dateFormat"), is(trueUntilJdk17()));
|
||||
|
||||
assertThat(hasReadMethodForProperty(ebi, "dateFormat"), is(false));
|
||||
assertThat(hasWriteMethodForProperty(ebi, "dateFormat"), is(true));
|
||||
assertThat(hasWriteMethodForProperty(ebi, "dateFormat"), is(false));
|
||||
assertThat(hasIndexedReadMethodForProperty(ebi, "dateFormat"), is(false));
|
||||
assertThat(hasIndexedWriteMethodForProperty(ebi, "dateFormat"), is(true));
|
||||
}
|
||||
@@ -663,52 +664,18 @@ public class ExtendedBeanInfoTests {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reproSpr8806_y() throws IntrospectionException, SecurityException, NoSuchMethodException {
|
||||
Introspector.getBeanInfo(LawLibrary.class);
|
||||
private boolean trueUntilJdk17() {
|
||||
return JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_17;
|
||||
}
|
||||
|
||||
@Ignore @Test
|
||||
public void reproSpr8806_x() throws IntrospectionException, SecurityException, NoSuchMethodException {
|
||||
BeanInfo info = Introspector.getBeanInfo(LawLibrary.class);
|
||||
for (PropertyDescriptor d : info.getPropertyDescriptors()) {
|
||||
if (d.getName().equals("book")) {
|
||||
Method readMethod = d.getReadMethod();
|
||||
Method writeMethod = d.getWriteMethod();
|
||||
System.out.println(format("READ : %s.%s (bridge:%s)",
|
||||
readMethod.getDeclaringClass().getSimpleName(), readMethod.getName(), readMethod.isBridge()));
|
||||
System.out.println(format("WRITE: %s.%s (bridge:%s)",
|
||||
writeMethod.getDeclaringClass().getSimpleName(), writeMethod.getName(), writeMethod.isBridge()));
|
||||
new PropertyDescriptor("book", readMethod, writeMethod);
|
||||
}
|
||||
}
|
||||
|
||||
Method readMethod = LawLibrary.class.getMethod("getBook");
|
||||
Method writeMethod = LawLibrary.class.getMethod("setBook", Book.class);
|
||||
|
||||
System.out.println(format("read : %s.%s (bridge:%s)",
|
||||
readMethod.getDeclaringClass().getSimpleName(), readMethod.getName(), readMethod.isBridge()));
|
||||
System.out.println(format("write: %s.%s (bridge:%s)",
|
||||
writeMethod.getDeclaringClass().getSimpleName(), writeMethod.getName(), writeMethod.isBridge()));
|
||||
|
||||
|
||||
System.out.println("--------");
|
||||
for (Method m : LawLibrary.class.getMethods()) {
|
||||
if (m.getDeclaringClass() == Object.class) continue;
|
||||
System.out.println(format("%s %s.%s(%s) [bridge:%s]",
|
||||
m.getReturnType().getSimpleName(), m.getDeclaringClass().getSimpleName(),
|
||||
m.getName(),
|
||||
m.getParameterTypes().length == 1 ? m.getParameterTypes()[0].getSimpleName() : "",
|
||||
m.isBridge()));
|
||||
}
|
||||
|
||||
//new ExtendedBeanInfo(info);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reproSpr8806() throws IntrospectionException {
|
||||
BeanInfo bi = Introspector.getBeanInfo(LawLibrary.class);
|
||||
new ExtendedBeanInfo(bi); // throws
|
||||
// does not throw
|
||||
Introspector.getBeanInfo(LawLibrary.class);
|
||||
|
||||
// does not throw after the changes introduced in SPR-8806
|
||||
new ExtendedBeanInfo(Introspector.getBeanInfo(LawLibrary.class));
|
||||
}
|
||||
|
||||
interface Book { }
|
||||
@@ -734,4 +701,74 @@ public class ExtendedBeanInfoTests {
|
||||
class LawLibrary extends Library implements TextBookOperations {
|
||||
public LawBook getBook() { return null; }
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void cornerSpr8949() throws IntrospectionException {
|
||||
class A {
|
||||
@SuppressWarnings("unused")
|
||||
public boolean isTargetMethod() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
@Override
|
||||
public boolean isTargetMethod() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
BeanInfo bi = Introspector.getBeanInfo(B.class);
|
||||
|
||||
/* first, demonstrate the 'problem':
|
||||
* java.beans.Introspector returns the "wrong" declaring class for overridden read
|
||||
* methods, which in turn violates expectations in {@link ExtendedBeanInfo} regarding
|
||||
* method equality. Spring's {@link ClassUtils#getMostSpecificMethod(Method, Class)}
|
||||
* helps out here, and is now put into use in ExtendedBeanInfo as well
|
||||
*/
|
||||
for (PropertyDescriptor pd : bi.getPropertyDescriptors()) {
|
||||
if ("targetMethod".equals(pd.getName())) {
|
||||
Method readMethod = pd.getReadMethod();
|
||||
assertTrue(readMethod.getDeclaringClass().equals(A.class)); // we expected B!
|
||||
|
||||
Method msReadMethod = ClassUtils.getMostSpecificMethod(readMethod, B.class);
|
||||
assertTrue(msReadMethod.getDeclaringClass().equals(B.class)); // and now we get it.
|
||||
}
|
||||
}
|
||||
|
||||
// and now demonstrate that we've indeed fixed the problem
|
||||
ExtendedBeanInfo ebi = new ExtendedBeanInfo(bi);
|
||||
|
||||
assertThat(hasReadMethodForProperty(bi, "targetMethod"), is(true));
|
||||
assertThat(hasWriteMethodForProperty(bi, "targetMethod"), is(false));
|
||||
|
||||
assertThat(hasReadMethodForProperty(ebi, "targetMethod"), is(true));
|
||||
assertThat(hasWriteMethodForProperty(ebi, "targetMethod"), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cornerSpr8937() throws IntrospectionException {
|
||||
@SuppressWarnings("unused") class A {
|
||||
public void setAddress(String addr){ }
|
||||
public void setAddress(int index, String addr) { }
|
||||
public String getAddress(int index){ return null; }
|
||||
}
|
||||
|
||||
{ // baseline. ExtendedBeanInfo needs to behave exactly like the following
|
||||
BeanInfo bi = Introspector.getBeanInfo(A.class);
|
||||
assertThat(hasReadMethodForProperty(bi, "address"), is(false));
|
||||
assertThat(hasWriteMethodForProperty(bi, "address"), is(false));
|
||||
assertThat(hasIndexedReadMethodForProperty(bi, "address"), is(true));
|
||||
assertThat(hasIndexedWriteMethodForProperty(bi, "address"), is(true));
|
||||
}
|
||||
{
|
||||
ExtendedBeanInfo bi = new ExtendedBeanInfo(Introspector.getBeanInfo(A.class));
|
||||
assertThat(hasReadMethodForProperty(bi, "address"), is(false));
|
||||
assertThat(hasWriteMethodForProperty(bi, "address"), is(false));
|
||||
assertThat(hasIndexedReadMethodForProperty(bi, "address"), is(true));
|
||||
assertThat(hasIndexedWriteMethodForProperty(bi, "address"), is(true));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2012 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,7 +23,6 @@ import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.IndexedTestBean;
|
||||
@@ -40,6 +39,8 @@ import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor}
|
||||
* processing the JSR-303 {@link javax.inject.Inject} annotation.
|
||||
@@ -206,8 +207,8 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(
|
||||
ConstructorsCollectionResourceInjectionBean.class));
|
||||
bf.registerBeanDefinition("annotatedBean",
|
||||
new RootBeanDefinition(ConstructorsCollectionResourceInjectionBean.class));
|
||||
TestBean tb = new TestBean();
|
||||
bf.registerSingleton("testBean", tb);
|
||||
NestedTestBean ntb1 = new NestedTestBean();
|
||||
@@ -415,6 +416,74 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryWithTypedListField() throws Exception {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryListFieldInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
bf.setSerializationId("test");
|
||||
|
||||
ObjectFactoryListFieldInjectionBean bean = (ObjectFactoryListFieldInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("testBean"), bean.getTestBean());
|
||||
bean = (ObjectFactoryListFieldInjectionBean) SerializationTestUtils.serializeAndDeserialize(bean);
|
||||
assertSame(bf.getBean("testBean"), bean.getTestBean());
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryWithTypedListMethod() throws Exception {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryListMethodInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
bf.setSerializationId("test");
|
||||
|
||||
ObjectFactoryListMethodInjectionBean bean = (ObjectFactoryListMethodInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("testBean"), bean.getTestBean());
|
||||
bean = (ObjectFactoryListMethodInjectionBean) SerializationTestUtils.serializeAndDeserialize(bean);
|
||||
assertSame(bf.getBean("testBean"), bean.getTestBean());
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryWithTypedMapField() throws Exception {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryMapFieldInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
bf.setSerializationId("test");
|
||||
|
||||
ObjectFactoryMapFieldInjectionBean bean = (ObjectFactoryMapFieldInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("testBean"), bean.getTestBean());
|
||||
bean = (ObjectFactoryMapFieldInjectionBean) SerializationTestUtils.serializeAndDeserialize(bean);
|
||||
assertSame(bf.getBean("testBean"), bean.getTestBean());
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryWithTypedMapMethod() throws Exception {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryMapMethodInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
bf.setSerializationId("test");
|
||||
|
||||
ObjectFactoryMapMethodInjectionBean bean = (ObjectFactoryMapMethodInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("testBean"), bean.getTestBean());
|
||||
bean = (ObjectFactoryMapMethodInjectionBean) SerializationTestUtils.serializeAndDeserialize(bean);
|
||||
assertSame(bf.getBean("testBean"), bean.getTestBean());
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a dependency on a {@link org.springframework.beans.factory.FactoryBean} can be autowired via
|
||||
* {@link org.springframework.beans.factory.annotation.Autowired @Inject}, specifically addressing the JIRA issue
|
||||
@@ -835,6 +904,66 @@ public class InjectAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
|
||||
|
||||
public static class ObjectFactoryListFieldInjectionBean implements Serializable {
|
||||
|
||||
@Inject
|
||||
private Provider<List<TestBean>> testBeanFactory;
|
||||
|
||||
public void setTestBeanFactory(Provider<List<TestBean>> testBeanFactory) {
|
||||
this.testBeanFactory = testBeanFactory;
|
||||
}
|
||||
|
||||
public TestBean getTestBean() {
|
||||
return this.testBeanFactory.get().get(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ObjectFactoryListMethodInjectionBean implements Serializable {
|
||||
|
||||
private Provider<List<TestBean>> testBeanFactory;
|
||||
|
||||
@Inject
|
||||
public void setTestBeanFactory(Provider<List<TestBean>> testBeanFactory) {
|
||||
this.testBeanFactory = testBeanFactory;
|
||||
}
|
||||
|
||||
public TestBean getTestBean() {
|
||||
return this.testBeanFactory.get().get(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ObjectFactoryMapFieldInjectionBean implements Serializable {
|
||||
|
||||
@Inject
|
||||
private Provider<Map<String, TestBean>> testBeanFactory;
|
||||
|
||||
public void setTestBeanFactory(Provider<Map<String, TestBean>> testBeanFactory) {
|
||||
this.testBeanFactory = testBeanFactory;
|
||||
}
|
||||
|
||||
public TestBean getTestBean() {
|
||||
return this.testBeanFactory.get().values().iterator().next();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ObjectFactoryMapMethodInjectionBean implements Serializable {
|
||||
|
||||
private Provider<Map<String, TestBean>> testBeanFactory;
|
||||
|
||||
@Inject
|
||||
public void setTestBeanFactory(Provider<Map<String, TestBean>> testBeanFactory) {
|
||||
this.testBeanFactory = testBeanFactory;
|
||||
}
|
||||
|
||||
public TestBean getTestBean() {
|
||||
return this.testBeanFactory.get().values().iterator().next();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bean with a dependency on a {@link org.springframework.beans.factory.FactoryBean}.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
|
||||
/**
|
||||
* Unit tests for SPR-8954, in which a custom {@link InstantiationAwareBeanPostProcessor}
|
||||
* forces the predicted type of a FactoryBean, effectively preventing retrieval of the
|
||||
* bean from calls to #getBeansOfType(FactoryBean.class). The implementation of
|
||||
* {@link AbstractBeanFactory#isFactoryBean(String, RootBeanDefinition)} now ensures
|
||||
* that not only the predicted bean type is considered, but also the original bean
|
||||
* definition's beanClass.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class Spr8954Tests {
|
||||
|
||||
@Test
|
||||
public void repro() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("foo", new RootBeanDefinition(FooFactoryBean.class));
|
||||
bf.addBeanPostProcessor(new PredictingBPP());
|
||||
|
||||
assertThat(bf.getBean("foo"), instanceOf(Foo.class));
|
||||
assertThat(bf.getBean("&foo"), instanceOf(FooFactoryBean.class));
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map<String, FactoryBean> fbBeans = bf.getBeansOfType(FactoryBean.class);
|
||||
assertThat(1, equalTo(fbBeans.size()));
|
||||
assertThat("&foo", equalTo(fbBeans.keySet().iterator().next()));
|
||||
|
||||
Map<String, AnInterface> aiBeans = bf.getBeansOfType(AnInterface.class);
|
||||
assertThat(1, equalTo(aiBeans.size()));
|
||||
assertThat("&foo", equalTo(aiBeans.keySet().iterator().next()));
|
||||
}
|
||||
|
||||
static class FooFactoryBean implements FactoryBean<Foo>, AnInterface {
|
||||
|
||||
public Foo getObject() throws Exception {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
public Class<?> getObjectType() {
|
||||
return Foo.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
interface AnInterface {
|
||||
}
|
||||
|
||||
static class Foo {
|
||||
}
|
||||
|
||||
interface PredictedType {
|
||||
|
||||
}
|
||||
|
||||
static class PredictingBPP extends InstantiationAwareBeanPostProcessorAdapter {
|
||||
|
||||
@Override
|
||||
public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
|
||||
return FactoryBean.class.isAssignableFrom(beanClass) ?
|
||||
PredictedType.class :
|
||||
super.predictBeanType(beanClass, beanName);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user