getBean(name, type) attempts type conversion if necessary (SPR-8480)

This commit is contained in:
Juergen Hoeller
2011-06-22 20:53:38 +00:00
parent 22739bebf3
commit d8a4949faf
3 changed files with 33 additions and 9 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 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.
@@ -173,7 +173,7 @@ public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, Single
* @param requiredType type of the property
* @param propertyEditorClass the {@link PropertyEditor} class to register
*/
void registerCustomEditor(Class requiredType, Class<? extends PropertyEditor> propertyEditorClass);
void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass);
/**
* Initialize the given PropertyEditorRegistry with the custom editors

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -42,6 +42,7 @@ import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.PropertyEditorRegistrySupport;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.TypeMismatchException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanCurrentlyInCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
@@ -166,6 +167,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
new NamedThreadLocal<Object>("Prototype beans currently in creation");
/**
* Create a new AbstractBeanFactory.
*/
@@ -189,7 +191,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
@@ -346,7 +348,16 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type [" +
ClassUtils.getQualifiedName(requiredType) + "]", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
@@ -682,7 +693,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
return this.propertyEditorRegistrars;
}
public void registerCustomEditor(Class requiredType, Class<? extends PropertyEditor> propertyEditorClass) {
public void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass) {
Assert.notNull(requiredType, "Required type must not be null");
Assert.isAssignable(PropertyEditor.class, propertyEditorClass);
this.customEditors.put(requiredType, propertyEditorClass);
@@ -1253,7 +1264,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
}
}
private Class doResolveBeanClass(RootBeanDefinition mbd, Class... typesToMatch) throws ClassNotFoundException {
if (!ObjectUtils.isEmpty(typesToMatch)) {
ClassLoader tempClassLoader = getTempClassLoader();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -22,7 +22,6 @@ import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.ejb.EJB;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.beans.BeansException;
@@ -43,6 +42,8 @@ import org.springframework.jndi.support.SimpleJndiBeanFactory;
import org.springframework.mock.jndi.ExpectedLookupTemplate;
import org.springframework.util.SerializationTestUtils;
import static org.junit.Assert.*;
/**
* @author Juergen Hoeller
* @author Chris Beams
@@ -229,6 +230,7 @@ public class CommonAnnotationBeanPostProcessorTests {
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ExtendedResourceInjectionBean.class));
bf.registerBeanDefinition("annotatedBean2", new RootBeanDefinition(NamedResourceInjectionBean.class));
bf.registerBeanDefinition("annotatedBean3", new RootBeanDefinition(ConvertedResourceInjectionBean.class));
TestBean tb = new TestBean();
bf.registerSingleton("testBean", tb);
TestBean tb2 = new TestBean();
@@ -238,6 +240,7 @@ public class CommonAnnotationBeanPostProcessorTests {
TestBean tb4 = new TestBean();
bf.registerSingleton("testBean4", tb4);
NestedTestBean tb6 = new NestedTestBean();
bf.registerSingleton("value", "5");
bf.registerSingleton("xy", tb6);
bf.registerAlias("xy", "testBean9");
@@ -255,6 +258,9 @@ public class CommonAnnotationBeanPostProcessorTests {
NamedResourceInjectionBean bean2 = (NamedResourceInjectionBean) bf.getBean("annotatedBean2");
assertSame(tb6, bean2.testBean);
ConvertedResourceInjectionBean bean3 = (ConvertedResourceInjectionBean) bf.getBean("annotatedBean3");
assertSame(5, bean3.value);
bf.destroySingletons();
assertTrue(bean.destroyCalled);
assertTrue(bean.destroy2Called);
@@ -591,6 +597,13 @@ public class CommonAnnotationBeanPostProcessorTests {
}
private static class ConvertedResourceInjectionBean {
@Resource(name="value")
private int value;
}
private static class NullFactory {
public static Object create() {