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-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.
|
||||
@@ -35,6 +35,7 @@ import java.util.TreeSet;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -74,12 +75,6 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
public ExtendedBeanInfo(BeanInfo delegate) throws IntrospectionException {
|
||||
this.delegate = delegate;
|
||||
|
||||
// PropertyDescriptor instances from the delegate object are never added directly, but always
|
||||
// copied to the local collection of #propertyDescriptors and returned by calls to
|
||||
// #getPropertyDescriptors(). this algorithm iterates through all methods (method descriptors)
|
||||
// in the wrapped BeanInfo object, copying any existing PropertyDescriptor or creating a new
|
||||
// one for any non-standard setter methods found.
|
||||
|
||||
ALL_METHODS:
|
||||
for (MethodDescriptor md : delegate.getMethodDescriptors()) {
|
||||
Method method = md.getMethod();
|
||||
@@ -136,19 +131,13 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
Method indexedReadMethod = ipd.getIndexedReadMethod();
|
||||
Method indexedWriteMethod = ipd.getIndexedWriteMethod();
|
||||
// has the setter already been found by the wrapped BeanInfo?
|
||||
if (indexedWriteMethod != null
|
||||
&& indexedWriteMethod.getName().equals(method.getName())) {
|
||||
// yes -> copy it, including corresponding getter method (if any -- may be null)
|
||||
this.addOrUpdatePropertyDescriptor(pd, propertyName, readMethod, writeMethod, indexedReadMethod, indexedWriteMethod);
|
||||
continue ALL_METHODS;
|
||||
}
|
||||
// has a getter corresponding to this setter already been found by the wrapped BeanInfo?
|
||||
if (indexedReadMethod != null
|
||||
&& indexedReadMethod.getName().equals(getterMethodNameFor(propertyName))
|
||||
&& indexedReadMethod.getReturnType().equals(method.getParameterTypes()[1])) {
|
||||
this.addOrUpdatePropertyDescriptor(pd, propertyName, readMethod, writeMethod, indexedReadMethod, method);
|
||||
continue ALL_METHODS;
|
||||
if (!(indexedWriteMethod != null
|
||||
&& indexedWriteMethod.getName().equals(method.getName()))) {
|
||||
indexedWriteMethod = method;
|
||||
}
|
||||
// yes -> copy it, including corresponding getter method (if any -- may be null)
|
||||
this.addOrUpdatePropertyDescriptor(pd, propertyName, readMethod, writeMethod, indexedReadMethod, indexedWriteMethod);
|
||||
continue ALL_METHODS;
|
||||
}
|
||||
// the INDEXED setter method was not found by the wrapped BeanInfo -> add a new PropertyDescriptor
|
||||
// for it. no corresponding INDEXED getter was detected, so the 'indexed read method' parameter is null.
|
||||
@@ -159,24 +148,27 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
// the method is not a setter, but is it a getter?
|
||||
for (PropertyDescriptor pd : delegate.getPropertyDescriptors()) {
|
||||
// have we already copied this read method to a property descriptor locally?
|
||||
String propertyName = pd.getName();
|
||||
Method readMethod = pd.getReadMethod();
|
||||
Method mostSpecificReadMethod = ClassUtils.getMostSpecificMethod(readMethod, method.getDeclaringClass());
|
||||
for (PropertyDescriptor existingPD : this.propertyDescriptors) {
|
||||
if (method.equals(pd.getReadMethod())
|
||||
&& existingPD.getName().equals(pd.getName())) {
|
||||
if (method.equals(mostSpecificReadMethod)
|
||||
&& existingPD.getName().equals(propertyName)) {
|
||||
if (existingPD.getReadMethod() == null) {
|
||||
// no -> add it now
|
||||
this.addOrUpdatePropertyDescriptor(pd, pd.getName(), method, pd.getWriteMethod());
|
||||
this.addOrUpdatePropertyDescriptor(pd, propertyName, method, pd.getWriteMethod());
|
||||
}
|
||||
// yes -> do not add a duplicate
|
||||
continue ALL_METHODS;
|
||||
}
|
||||
}
|
||||
if (method == pd.getReadMethod()
|
||||
|| (pd instanceof IndexedPropertyDescriptor && method == ((IndexedPropertyDescriptor) pd).getIndexedReadMethod())) {
|
||||
if (method.equals(mostSpecificReadMethod)
|
||||
|| (pd instanceof IndexedPropertyDescriptor && method.equals(((IndexedPropertyDescriptor) pd).getIndexedReadMethod()))) {
|
||||
// yes -> copy it, including corresponding setter method (if any -- may be null)
|
||||
if (pd instanceof IndexedPropertyDescriptor) {
|
||||
this.addOrUpdatePropertyDescriptor(pd, pd.getName(), pd.getReadMethod(), pd.getWriteMethod(), ((IndexedPropertyDescriptor)pd).getIndexedReadMethod(), ((IndexedPropertyDescriptor)pd).getIndexedWriteMethod());
|
||||
this.addOrUpdatePropertyDescriptor(pd, propertyName, readMethod, pd.getWriteMethod(), ((IndexedPropertyDescriptor)pd).getIndexedReadMethod(), ((IndexedPropertyDescriptor)pd).getIndexedWriteMethod());
|
||||
} else {
|
||||
this.addOrUpdatePropertyDescriptor(pd, pd.getName(), pd.getReadMethod(), pd.getWriteMethod());
|
||||
this.addOrUpdatePropertyDescriptor(pd, propertyName, readMethod, pd.getWriteMethod());
|
||||
}
|
||||
continue ALL_METHODS;
|
||||
}
|
||||
@@ -221,7 +213,9 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
}
|
||||
}
|
||||
// update the existing descriptor's write method
|
||||
if (writeMethod != null) {
|
||||
if (writeMethod != null
|
||||
&& !(existingPD instanceof IndexedPropertyDescriptor &&
|
||||
!writeMethod.getParameterTypes()[0].isArray())) {
|
||||
existingPD.setWriteMethod(writeMethod);
|
||||
}
|
||||
|
||||
@@ -278,7 +272,7 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
}
|
||||
this.propertyDescriptors.add(pd);
|
||||
} catch (IntrospectionException ex) {
|
||||
logger.warn(format("Could not create new PropertyDescriptor for readMethod [%s] writeMethod [%s] " +
|
||||
logger.debug(format("Could not create new PropertyDescriptor for readMethod [%s] writeMethod [%s] " +
|
||||
"indexedReadMethod [%s] indexedWriteMethod [%s] for property [%s]. Reason: %s",
|
||||
readMethod, writeMethod, indexedReadMethod, indexedWriteMethod, propertyName, ex.getMessage()));
|
||||
// suppress exception and attempt to continue
|
||||
@@ -289,10 +283,20 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
try {
|
||||
pd.setWriteMethod(writeMethod);
|
||||
} catch (IntrospectionException ex) {
|
||||
logger.warn(format("Could not add write method [%s] for property [%s]. Reason: %s",
|
||||
logger.debug(format("Could not add write method [%s] for property [%s]. Reason: %s",
|
||||
writeMethod, propertyName, ex.getMessage()));
|
||||
// fall through -> add property descriptor as best we can
|
||||
}
|
||||
if (pd instanceof IndexedPropertyDescriptor) {
|
||||
((IndexedPropertyDescriptor)pd).setIndexedReadMethod(indexedReadMethod);
|
||||
try {
|
||||
((IndexedPropertyDescriptor)pd).setIndexedWriteMethod(indexedWriteMethod);
|
||||
} catch (IntrospectionException ex) {
|
||||
logger.debug(format("Could not add indexed write method [%s] for property [%s]. Reason: %s",
|
||||
indexedWriteMethod, propertyName, ex.getMessage()));
|
||||
// fall through -> add property descriptor as best we can
|
||||
}
|
||||
}
|
||||
this.propertyDescriptors.add(pd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public class AnnotatedGenericBeanDefinition extends GenericBeanDefinition implem
|
||||
*/
|
||||
public AnnotatedGenericBeanDefinition(Class beanClass) {
|
||||
setBeanClass(beanClass);
|
||||
this.annotationMetadata = new StandardAnnotationMetadata(beanClass);
|
||||
this.annotationMetadata = new StandardAnnotationMetadata(beanClass, 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.
|
||||
@@ -21,6 +21,7 @@ import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
@@ -56,6 +57,8 @@ public class DependencyDescriptor implements Serializable {
|
||||
|
||||
private final boolean eager;
|
||||
|
||||
private int nestingLevel = 1;
|
||||
|
||||
private transient Annotation[] fieldAnnotations;
|
||||
|
||||
|
||||
@@ -153,6 +156,13 @@ public class DependencyDescriptor implements Serializable {
|
||||
}
|
||||
|
||||
|
||||
public void increaseNestingLevel() {
|
||||
this.nestingLevel++;
|
||||
if (this.methodParameter != null) {
|
||||
this.methodParameter.increaseNestingLevel();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize parameter name discovery for the underlying method parameter, if any.
|
||||
* <p>This method does not actually try to retrieve the parameter name at
|
||||
@@ -178,15 +188,30 @@ public class DependencyDescriptor implements Serializable {
|
||||
* @return the declared type (never <code>null</code>)
|
||||
*/
|
||||
public Class<?> getDependencyType() {
|
||||
return (this.field != null ? this.field.getType() : this.methodParameter.getParameterType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the generic type of the wrapped parameter/field.
|
||||
* @return the generic type (never <code>null</code>)
|
||||
*/
|
||||
public Type getGenericDependencyType() {
|
||||
return (this.field != null ? this.field.getGenericType() : this.methodParameter.getGenericParameterType());
|
||||
if (this.field != null) {
|
||||
if (this.nestingLevel > 1) {
|
||||
Type type = this.field.getGenericType();
|
||||
if (type instanceof ParameterizedType) {
|
||||
Type arg = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||
if (arg instanceof Class) {
|
||||
return (Class) arg;
|
||||
}
|
||||
else if (arg instanceof ParameterizedType) {
|
||||
arg = ((ParameterizedType) arg).getRawType();
|
||||
if (arg instanceof Class) {
|
||||
return (Class) arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Object.class;
|
||||
}
|
||||
else {
|
||||
return this.field.getType();
|
||||
}
|
||||
}
|
||||
else {
|
||||
return this.methodParameter.getNestedParameterType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,7 +220,7 @@ public class DependencyDescriptor implements Serializable {
|
||||
*/
|
||||
public Class<?> getCollectionType() {
|
||||
return (this.field != null ?
|
||||
GenericCollectionTypeResolver.getCollectionFieldType(this.field) :
|
||||
GenericCollectionTypeResolver.getCollectionFieldType(this.field, this.nestingLevel) :
|
||||
GenericCollectionTypeResolver.getCollectionParameterType(this.methodParameter));
|
||||
}
|
||||
|
||||
@@ -205,7 +230,7 @@ public class DependencyDescriptor implements Serializable {
|
||||
*/
|
||||
public Class<?> getMapKeyType() {
|
||||
return (this.field != null ?
|
||||
GenericCollectionTypeResolver.getMapKeyFieldType(this.field) :
|
||||
GenericCollectionTypeResolver.getMapKeyFieldType(this.field, this.nestingLevel) :
|
||||
GenericCollectionTypeResolver.getMapKeyParameterType(this.methodParameter));
|
||||
}
|
||||
|
||||
@@ -215,7 +240,7 @@ public class DependencyDescriptor implements Serializable {
|
||||
*/
|
||||
public Class<?> getMapValueType() {
|
||||
return (this.field != null ?
|
||||
GenericCollectionTypeResolver.getMapValueFieldType(this.field) :
|
||||
GenericCollectionTypeResolver.getMapValueFieldType(this.field, this.nestingLevel) :
|
||||
GenericCollectionTypeResolver.getMapValueParameterType(this.methodParameter));
|
||||
}
|
||||
|
||||
@@ -248,13 +273,18 @@ public class DependencyDescriptor implements Serializable {
|
||||
if (this.fieldName != null) {
|
||||
this.field = this.declaringClass.getDeclaredField(this.fieldName);
|
||||
}
|
||||
else if (this.methodName != null) {
|
||||
this.methodParameter = new MethodParameter(
|
||||
this.declaringClass.getDeclaredMethod(this.methodName, this.parameterTypes), this.parameterIndex);
|
||||
}
|
||||
else {
|
||||
this.methodParameter = new MethodParameter(
|
||||
this.declaringClass.getDeclaredConstructor(this.parameterTypes), this.parameterIndex);
|
||||
if (this.methodName != null) {
|
||||
this.methodParameter = new MethodParameter(
|
||||
this.declaringClass.getDeclaredMethod(this.methodName, this.parameterTypes), this.parameterIndex);
|
||||
}
|
||||
else {
|
||||
this.methodParameter = new MethodParameter(
|
||||
this.declaringClass.getDeclaredConstructor(this.parameterTypes), this.parameterIndex);
|
||||
}
|
||||
for (int i = 1; i < this.nestingLevel; i++) {
|
||||
this.methodParameter.increaseNestingLevel();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
|
||||
@@ -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.
|
||||
@@ -1328,8 +1328,9 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
* @param mbd the corresponding bean definition
|
||||
*/
|
||||
protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
|
||||
Class<?> beanClass = predictBeanType(beanName, mbd, FactoryBean.class);
|
||||
return (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass));
|
||||
Class<?> predictedType = predictBeanType(beanName, mbd, FactoryBean.class);
|
||||
return (predictedType != null && FactoryBean.class.isAssignableFrom(predictedType)) ||
|
||||
(mbd.hasBeanClass() && FactoryBean.class.isAssignableFrom(mbd.getBeanClass()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
@@ -1000,27 +1000,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
private final String beanName;
|
||||
|
||||
private final Class type;
|
||||
|
||||
public DependencyObjectFactory(DependencyDescriptor descriptor, String beanName) {
|
||||
this.descriptor = descriptor;
|
||||
this.beanName = beanName;
|
||||
this.type = determineObjectFactoryType();
|
||||
}
|
||||
|
||||
private Class determineObjectFactoryType() {
|
||||
Type type = this.descriptor.getGenericDependencyType();
|
||||
if (type instanceof ParameterizedType) {
|
||||
Type arg = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||
if (arg instanceof Class) {
|
||||
return (Class) arg;
|
||||
}
|
||||
}
|
||||
return Object.class;
|
||||
this.descriptor.increaseNestingLevel();
|
||||
}
|
||||
|
||||
public Object getObject() throws BeansException {
|
||||
return doResolveDependency(this.descriptor, this.type, this.beanName, null, null);
|
||||
return doResolveDependency(this.descriptor, this.descriptor.getDependencyType(), this.beanName, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user