completed value annotation support; Java 5 code style updates
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@312 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
parent
fee0e1b8f3
commit
e6f75f212d
|
|
@ -18,6 +18,7 @@ package org.springframework.beans.factory.annotation;
|
|||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
|
@ -99,14 +100,14 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
|||
|
||||
protected final Log logger = LogFactory.getLog(AutowiredAnnotationBeanPostProcessor.class);
|
||||
|
||||
private Class<? extends Annotation> autowiredAnnotationType = Autowired.class;
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class<? extends Annotation>[] autowiredAnnotationTypes =
|
||||
new Class[] {Autowired.class, Qualifier.class, Value.class};
|
||||
|
||||
private String requiredParameterName = "required";
|
||||
|
||||
private boolean requiredParameterValue = true;
|
||||
|
||||
private Class<? extends Annotation> valueAnnotationType = Value.class;
|
||||
|
||||
private int order = Ordered.LOWEST_PRECEDENCE - 2;
|
||||
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
|
@ -127,16 +128,24 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
|||
* (non-Spring-specific) annotation type to indicate that a member is
|
||||
* supposed to be autowired.
|
||||
*/
|
||||
public void setAutowiredAnnotationType(Class<? extends Annotation> autowiredAnnotationType) {
|
||||
Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null");
|
||||
this.autowiredAnnotationType = autowiredAnnotationType;
|
||||
public void setAutowiredAnnotationTypes(Class<? extends Annotation>[] autowiredAnnotationTypes) {
|
||||
Assert.notEmpty(autowiredAnnotationTypes, "'autowiredAnnotationTypes' must not be empty");
|
||||
this.autowiredAnnotationTypes = autowiredAnnotationTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the 'autowired' annotation type.
|
||||
* Set the 'autowired' annotation type, to be used on constructors, fields,
|
||||
* setter methods and arbitrary config methods.
|
||||
* <p>The default autowired annotation type is the Spring-provided
|
||||
* {@link Autowired} annotation.
|
||||
* <p>This setter property exists so that developers can provide their own
|
||||
* (non-Spring-specific) annotation type to indicate that a member is
|
||||
* supposed to be autowired.
|
||||
*/
|
||||
protected Class<? extends Annotation> getAutowiredAnnotationType() {
|
||||
return this.autowiredAnnotationType;
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setAutowiredAnnotationType(Class<? extends Annotation> autowiredAnnotationType) {
|
||||
Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null");
|
||||
this.autowiredAnnotationTypes = new Class[] {autowiredAnnotationType};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -196,7 +205,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
|||
Constructor requiredConstructor = null;
|
||||
Constructor defaultConstructor = null;
|
||||
for (Constructor<?> candidate : rawCandidates) {
|
||||
Annotation annotation = candidate.getAnnotation(getAutowiredAnnotationType());
|
||||
Annotation annotation = findAutowiredAnnotation(candidate);
|
||||
if (annotation != null) {
|
||||
if (requiredConstructor != null) {
|
||||
throw new BeanCreationException("Invalid autowire-marked constructor: " + candidate +
|
||||
|
|
@ -212,8 +221,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
|||
if (!candidates.isEmpty()) {
|
||||
throw new BeanCreationException(
|
||||
"Invalid autowire-marked constructors: " + candidates +
|
||||
". Found another constructor with 'required' Autowired annotation: " +
|
||||
requiredConstructor);
|
||||
". Found another constructor with 'required' Autowired annotation: " +
|
||||
requiredConstructor);
|
||||
}
|
||||
requiredConstructor = candidate;
|
||||
}
|
||||
|
|
@ -294,7 +303,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
|||
final InjectionMetadata newMetadata = new InjectionMetadata(clazz);
|
||||
ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() {
|
||||
public void doWith(Field field) {
|
||||
Annotation annotation = field.getAnnotation(getAutowiredAnnotationType());
|
||||
Annotation annotation = findAutowiredAnnotation(field);
|
||||
if (annotation != null) {
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
throw new IllegalStateException("Autowired annotation is not supported on static fields");
|
||||
|
|
@ -306,7 +315,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
|||
});
|
||||
ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() {
|
||||
public void doWith(Method method) {
|
||||
Annotation annotation = method.getAnnotation(getAutowiredAnnotationType());
|
||||
Annotation annotation = findAutowiredAnnotation(method);
|
||||
if (annotation != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
|
||||
if (Modifier.isStatic(method.getModifiers())) {
|
||||
throw new IllegalStateException("Autowired annotation is not supported on static methods");
|
||||
|
|
@ -328,6 +337,16 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
|||
return metadata;
|
||||
}
|
||||
|
||||
private Annotation findAutowiredAnnotation(AccessibleObject ao) {
|
||||
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
|
||||
Annotation annotation = ao.getAnnotation(type);
|
||||
if (annotation != null) {
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain all beans of the given type as autowire candidates.
|
||||
* @param type the type of the bean
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2008 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.
|
||||
|
|
@ -17,7 +17,6 @@
|
|||
package org.springframework.beans.factory.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
|
|
@ -83,6 +82,7 @@ public class CustomAutowireConfigurer implements BeanFactoryPostProcessor, BeanC
|
|||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
if (this.customQualifierTypes != null) {
|
||||
if (!(beanFactory instanceof DefaultListableBeanFactory)) {
|
||||
|
|
@ -91,14 +91,12 @@ public class CustomAutowireConfigurer implements BeanFactoryPostProcessor, BeanC
|
|||
}
|
||||
DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory;
|
||||
if (!(dlbf.getAutowireCandidateResolver() instanceof QualifierAnnotationAutowireCandidateResolver)) {
|
||||
throw new IllegalStateException(
|
||||
"CustomAutowireConfigurer needs to operate on a QualifierAnnotationAutowireCandidateResolver");
|
||||
dlbf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
}
|
||||
QualifierAnnotationAutowireCandidateResolver resolver =
|
||||
(QualifierAnnotationAutowireCandidateResolver) dlbf.getAutowireCandidateResolver();
|
||||
for (Iterator it = this.customQualifierTypes.iterator(); it.hasNext();) {
|
||||
for (Object value : this.customQualifierTypes) {
|
||||
Class customType = null;
|
||||
Object value = it.next();
|
||||
if (value instanceof Class) {
|
||||
customType = (Class) value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,9 +181,9 @@ public class InjectionMetadata {
|
|||
}
|
||||
else {
|
||||
if (this.skip == null) {
|
||||
this.skip = Boolean.valueOf(checkPropertySkipping(pvs));
|
||||
this.skip = checkPropertySkipping(pvs);
|
||||
}
|
||||
if (this.skip.booleanValue()) {
|
||||
if (this.skip) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2008 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,17 +35,21 @@ import org.springframework.util.ObjectUtils;
|
|||
/**
|
||||
* {@link AutowireCandidateResolver} implementation that matches bean definition
|
||||
* qualifiers against qualifier annotations on the field or parameter to be autowired.
|
||||
* Also supports suggested expression values through a value annotation.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
* @see AutowireCandidateQualifier
|
||||
* @see Qualifier
|
||||
* @see Value
|
||||
*/
|
||||
public class QualifierAnnotationAutowireCandidateResolver implements AutowireCandidateResolver {
|
||||
|
||||
private final Set<Class<? extends Annotation>> qualifierTypes;
|
||||
|
||||
private Class<? extends Annotation> valueAnnotationType = Value.class;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new QualifierAnnotationAutowireCandidateResolver
|
||||
|
|
@ -80,13 +84,32 @@ public class QualifierAnnotationAutowireCandidateResolver implements AutowireCan
|
|||
|
||||
/**
|
||||
* Register the given type to be used as a qualifier when autowiring.
|
||||
* <p>This identifies qualifier annotations for direct use (on fields,
|
||||
* method parameters and constructor parameters) as well as meta
|
||||
* annotations that in turn identify actual qualifier annotations.
|
||||
* <p>This implementation only supports annotations as qualifier types.
|
||||
* The default is Spring's {@link Qualifier} annotation which serves
|
||||
* as a qualifier for direct use and also as a meta annotation.
|
||||
* @param qualifierType the annotation type to register
|
||||
*/
|
||||
public void addQualifierType(Class<? extends Annotation> qualifierType) {
|
||||
this.qualifierTypes.add(qualifierType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'value' annotation type, to be used on fields, method parameters
|
||||
* and constructor parameters.
|
||||
* <p>The default value annotation type is the Spring-provided
|
||||
* {@link Value} annotation.
|
||||
* <p>This setter property exists so that developers can provide their own
|
||||
* (non-Spring-specific) annotation type to indicate a default value
|
||||
* expression for a specific argument.
|
||||
*/
|
||||
public void setValueAnnotationType(Class<? extends Annotation> valueAnnotationType) {
|
||||
this.valueAnnotationType = valueAnnotationType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the provided bean definition is an autowire candidate.
|
||||
* <p>To be considered a candidate the bean's <em>autowire-candidate</em>
|
||||
|
|
@ -176,4 +199,17 @@ public class QualifierAnnotationAutowireCandidateResolver implements AutowireCan
|
|||
return false;
|
||||
}
|
||||
|
||||
public Object getSuggestedValue(DependencyDescriptor descriptor) {
|
||||
for (Annotation annotation : descriptor.getAnnotations()) {
|
||||
if (this.valueAnnotationType.isInstance(annotation)) {
|
||||
Object value = AnnotationUtils.getValue(annotation);
|
||||
if (value == null) {
|
||||
throw new IllegalStateException("Value annotation must have a value attribute");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
* Copyright 2002-2008 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.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
|
|
@ -6,13 +22,24 @@ import java.lang.annotation.RetentionPolicy;
|
|||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation at the field or method/constructor parameter level
|
||||
* that indicates a default value expression for the affected argument.
|
||||
*
|
||||
* <p>This is typically used for assigning default field values
|
||||
* with "#{systemProperties.myProp}" style expressions.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see org.springframework.beans.factory.config.BeanExpressionResolver
|
||||
* @see org.springframework.beans.factory.support.AutowireCandidateResolver#getSuggestedValue
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER})
|
||||
public @interface Value {
|
||||
|
||||
/**
|
||||
* The actual value expression: e.g. "#{systemProperties.myProp}".
|
||||
*/
|
||||
String value();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2008 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,9 +42,9 @@ import org.springframework.util.ObjectUtils;
|
|||
*/
|
||||
public class ConstructorArgumentValues {
|
||||
|
||||
private final Map indexedArgumentValues = new HashMap();
|
||||
private final Map<Integer, ValueHolder> indexedArgumentValues = new HashMap<Integer, ValueHolder>();
|
||||
|
||||
private final List genericArgumentValues = new LinkedList();
|
||||
private final List<ValueHolder> genericArgumentValues = new LinkedList<ValueHolder>();
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -61,6 +61,7 @@ public class ConstructorArgumentValues {
|
|||
addArgumentValues(original);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy all given argument values into this object, using separate holder
|
||||
* instances to keep the values independent from the original object.
|
||||
|
|
@ -70,13 +71,10 @@ public class ConstructorArgumentValues {
|
|||
*/
|
||||
public void addArgumentValues(ConstructorArgumentValues other) {
|
||||
if (other != null) {
|
||||
for (Iterator it = other.indexedArgumentValues.entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
ValueHolder valueHolder = (ValueHolder) entry.getValue();
|
||||
addOrMergeIndexedArgumentValue(entry.getKey(), valueHolder.copy());
|
||||
for (Map.Entry<Integer, ValueHolder> entry : other.indexedArgumentValues.entrySet()) {
|
||||
addOrMergeIndexedArgumentValue(entry.getKey(), entry.getValue().copy());
|
||||
}
|
||||
for (Iterator it = other.genericArgumentValues.iterator(); it.hasNext();) {
|
||||
ValueHolder valueHolder = (ValueHolder) it.next();
|
||||
for (ValueHolder valueHolder : other.genericArgumentValues) {
|
||||
if (!this.genericArgumentValues.contains(valueHolder)) {
|
||||
this.genericArgumentValues.add(valueHolder.copy());
|
||||
}
|
||||
|
|
@ -112,7 +110,7 @@ public class ConstructorArgumentValues {
|
|||
public void addIndexedArgumentValue(int index, ValueHolder newValue) {
|
||||
Assert.isTrue(index >= 0, "Index must not be negative");
|
||||
Assert.notNull(newValue, "ValueHolder must not be null");
|
||||
addOrMergeIndexedArgumentValue(new Integer(index), newValue);
|
||||
addOrMergeIndexedArgumentValue(index, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -122,8 +120,8 @@ public class ConstructorArgumentValues {
|
|||
* @param key the index in the constructor argument list
|
||||
* @param newValue the argument value in the form of a ValueHolder
|
||||
*/
|
||||
private void addOrMergeIndexedArgumentValue(Object key, ValueHolder newValue) {
|
||||
ValueHolder currentValue = (ValueHolder) this.indexedArgumentValues.get(key);
|
||||
private void addOrMergeIndexedArgumentValue(Integer key, ValueHolder newValue) {
|
||||
ValueHolder currentValue = this.indexedArgumentValues.get(key);
|
||||
if (currentValue != null && newValue.getValue() instanceof Mergeable) {
|
||||
Mergeable mergeable = (Mergeable) newValue.getValue();
|
||||
if (mergeable.isMergeEnabled()) {
|
||||
|
|
@ -142,7 +140,7 @@ public class ConstructorArgumentValues {
|
|||
*/
|
||||
public ValueHolder getIndexedArgumentValue(int index, Class requiredType) {
|
||||
Assert.isTrue(index >= 0, "Index must not be negative");
|
||||
ValueHolder valueHolder = (ValueHolder) this.indexedArgumentValues.get(new Integer(index));
|
||||
ValueHolder valueHolder = this.indexedArgumentValues.get(index);
|
||||
if (valueHolder != null) {
|
||||
if (valueHolder.getType() == null ||
|
||||
(requiredType != null && requiredType.getName().equals(valueHolder.getType()))) {
|
||||
|
|
@ -157,7 +155,7 @@ public class ConstructorArgumentValues {
|
|||
* @return unmodifiable Map with Integer index as key and ValueHolder as value
|
||||
* @see ValueHolder
|
||||
*/
|
||||
public Map getIndexedArgumentValues() {
|
||||
public Map<Integer, ValueHolder> getIndexedArgumentValues() {
|
||||
return Collections.unmodifiableMap(this.indexedArgumentValues);
|
||||
}
|
||||
|
||||
|
|
@ -220,8 +218,7 @@ public class ConstructorArgumentValues {
|
|||
* @return the ValueHolder for the argument, or <code>null</code> if none found
|
||||
*/
|
||||
public ValueHolder getGenericArgumentValue(Class requiredType, Set usedValueHolders) {
|
||||
for (Iterator it = this.genericArgumentValues.iterator(); it.hasNext();) {
|
||||
ValueHolder valueHolder = (ValueHolder) it.next();
|
||||
for (ValueHolder valueHolder : this.genericArgumentValues) {
|
||||
if (usedValueHolders == null || !usedValueHolders.contains(valueHolder)) {
|
||||
if (requiredType != null) {
|
||||
// Check matching type.
|
||||
|
|
@ -250,7 +247,7 @@ public class ConstructorArgumentValues {
|
|||
* @return unmodifiable List of ValueHolders
|
||||
* @see ValueHolder
|
||||
*/
|
||||
public List getGenericArgumentValues() {
|
||||
public List<ValueHolder> getGenericArgumentValues() {
|
||||
return Collections.unmodifiableList(this.genericArgumentValues);
|
||||
}
|
||||
|
||||
|
|
@ -334,10 +331,9 @@ public class ConstructorArgumentValues {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
for (Iterator it = this.indexedArgumentValues.entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
ValueHolder vh1 = (ValueHolder) entry.getValue();
|
||||
ValueHolder vh2 = (ValueHolder) that.indexedArgumentValues.get(entry.getKey());
|
||||
for (Map.Entry<Integer, ValueHolder> entry : this.indexedArgumentValues.entrySet()) {
|
||||
ValueHolder vh1 = entry.getValue();
|
||||
ValueHolder vh2 = that.indexedArgumentValues.get(entry.getKey());
|
||||
if (!vh1.contentEquals(vh2)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -348,16 +344,12 @@ public class ConstructorArgumentValues {
|
|||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = 7;
|
||||
for (Iterator it = this.genericArgumentValues.iterator(); it.hasNext();) {
|
||||
ValueHolder valueHolder = (ValueHolder) it.next();
|
||||
for (ValueHolder valueHolder : this.genericArgumentValues) {
|
||||
hashCode = 31 * hashCode + valueHolder.contentHashCode();
|
||||
}
|
||||
hashCode = 29 * hashCode;
|
||||
for (Iterator it = this.indexedArgumentValues.entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
Integer key = (Integer) entry.getKey();
|
||||
ValueHolder value = (ValueHolder) entry.getValue();
|
||||
hashCode = 31 * hashCode + (value.contentHashCode() ^ key.hashCode());
|
||||
for (Map.Entry<Integer, ValueHolder> entry : this.indexedArgumentValues.entrySet()) {
|
||||
hashCode = 31 * hashCode + (entry.getValue().contentHashCode() ^ entry.getKey().hashCode());
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,7 +134,8 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
|||
|
||||
private boolean autowireCandidate = true;
|
||||
|
||||
private final Map qualifiers = new LinkedHashMap();
|
||||
private final Map<String, AutowireCandidateQualifier> qualifiers =
|
||||
new LinkedHashMap<String, AutowireCandidateQualifier>();
|
||||
|
||||
private boolean primary = false;
|
||||
|
||||
|
|
@ -521,8 +522,8 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
|||
// If it has a no-arg constructor it's deemed to be setter autowiring,
|
||||
// otherwise we'll try constructor autowiring.
|
||||
Constructor[] constructors = getBeanClass().getConstructors();
|
||||
for (int i = 0; i < constructors.length; i++) {
|
||||
if (constructors[i].getParameterTypes().length == 0) {
|
||||
for (Constructor constructor : constructors) {
|
||||
if (constructor.getParameterTypes().length == 0) {
|
||||
return AUTOWIRE_BY_TYPE;
|
||||
}
|
||||
}
|
||||
|
|
@ -605,15 +606,15 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
|||
* Return the qualifier mapped to the provided type name.
|
||||
*/
|
||||
public AutowireCandidateQualifier getQualifier(String typeName) {
|
||||
return (AutowireCandidateQualifier) this.qualifiers.get(typeName);
|
||||
return this.qualifiers.get(typeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all registered qualifiers.
|
||||
* @return the Set of {@link AutowireCandidateQualifier} objects.
|
||||
*/
|
||||
public Set getQualifiers() {
|
||||
return new LinkedHashSet(this.qualifiers.values());
|
||||
public Set<AutowireCandidateQualifier> getQualifiers() {
|
||||
return new LinkedHashSet<AutowireCandidateQualifier>(this.qualifiers.values());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -885,8 +886,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
|||
// Check that lookup methods exists.
|
||||
MethodOverrides methodOverrides = getMethodOverrides();
|
||||
if (!methodOverrides.isEmpty()) {
|
||||
for (Iterator it = methodOverrides.getOverrides().iterator(); it.hasNext(); ) {
|
||||
MethodOverride mo = (MethodOverride) it.next();
|
||||
for (MethodOverride mo : methodOverrides.getOverrides()) {
|
||||
prepareMethodOverride(mo);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2008 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.
|
||||
|
|
@ -38,4 +38,12 @@ public interface AutowireCandidateResolver {
|
|||
*/
|
||||
boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor);
|
||||
|
||||
/**
|
||||
* Determine whether a default value is suggested for the given dependency.
|
||||
* @param descriptor the descriptor for the target method parameter or field
|
||||
* @return the value suggested (typically an expression String),
|
||||
* or <code>null</code> if none found
|
||||
*/
|
||||
Object getSuggestedValue(DependencyDescriptor descriptor);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import java.lang.reflect.Constructor;
|
|||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
|
@ -182,7 +181,7 @@ class ConstructorResolver {
|
|||
}
|
||||
|
||||
ArgumentsHolder args = null;
|
||||
List causes = null;
|
||||
List<Exception> causes = null;
|
||||
|
||||
if (resolvedValues != null) {
|
||||
// Try to resolve arguments for current constructor.
|
||||
|
|
@ -197,8 +196,8 @@ class ConstructorResolver {
|
|||
}
|
||||
if (i == candidates.length - 1 && constructorToUse == null) {
|
||||
if (causes != null) {
|
||||
for (Iterator it = causes.iterator(); it.hasNext();) {
|
||||
this.beanFactory.onSuppressedException((Exception) it.next());
|
||||
for (Exception cause : causes) {
|
||||
this.beanFactory.onSuppressedException(cause);
|
||||
}
|
||||
}
|
||||
throw ex;
|
||||
|
|
@ -206,7 +205,7 @@ class ConstructorResolver {
|
|||
else {
|
||||
// Swallow and try next constructor.
|
||||
if (causes == null) {
|
||||
causes = new LinkedList();
|
||||
causes = new LinkedList<Exception>();
|
||||
}
|
||||
causes.add(ex);
|
||||
continue;
|
||||
|
|
@ -348,7 +347,7 @@ class ConstructorResolver {
|
|||
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
|
||||
}
|
||||
|
||||
List causes = null;
|
||||
List<Exception> causes = null;
|
||||
|
||||
for (int i = 0; i < candidates.length; i++) {
|
||||
Method candidate = candidates[i];
|
||||
|
|
@ -373,8 +372,8 @@ class ConstructorResolver {
|
|||
}
|
||||
if (i == candidates.length - 1 && factoryMethodToUse == null) {
|
||||
if (causes != null) {
|
||||
for (Iterator it = causes.iterator(); it.hasNext();) {
|
||||
this.beanFactory.onSuppressedException((Exception) it.next());
|
||||
for (Exception cause : causes) {
|
||||
this.beanFactory.onSuppressedException(cause);
|
||||
}
|
||||
}
|
||||
throw ex;
|
||||
|
|
@ -382,7 +381,7 @@ class ConstructorResolver {
|
|||
else {
|
||||
// Swallow and try next overloaded factory method.
|
||||
if (causes == null) {
|
||||
causes = new LinkedList();
|
||||
causes = new LinkedList<Exception>();
|
||||
}
|
||||
causes.add(ex);
|
||||
continue;
|
||||
|
|
@ -455,9 +454,8 @@ class ConstructorResolver {
|
|||
|
||||
int minNrOfArgs = cargs.getArgumentCount();
|
||||
|
||||
for (Iterator it = cargs.getIndexedArgumentValues().entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
int index = ((Integer) entry.getKey()).intValue();
|
||||
for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
|
||||
int index = entry.getKey();
|
||||
if (index < 0) {
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||
"Invalid constructor argument index: " + index);
|
||||
|
|
@ -465,8 +463,7 @@ class ConstructorResolver {
|
|||
if (index > minNrOfArgs) {
|
||||
minNrOfArgs = index + 1;
|
||||
}
|
||||
ConstructorArgumentValues.ValueHolder valueHolder =
|
||||
(ConstructorArgumentValues.ValueHolder) entry.getValue();
|
||||
ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
|
||||
if (valueHolder.isConverted()) {
|
||||
resolvedValues.addIndexedArgumentValue(index, valueHolder);
|
||||
}
|
||||
|
|
@ -480,9 +477,7 @@ class ConstructorResolver {
|
|||
}
|
||||
}
|
||||
|
||||
for (Iterator it = cargs.getGenericArgumentValues().iterator(); it.hasNext();) {
|
||||
ConstructorArgumentValues.ValueHolder valueHolder =
|
||||
(ConstructorArgumentValues.ValueHolder) it.next();
|
||||
for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
|
||||
if (valueHolder.isConverted()) {
|
||||
resolvedValues.addGenericArgumentValue(valueHolder);
|
||||
}
|
||||
|
|
@ -512,8 +507,9 @@ class ConstructorResolver {
|
|||
TypeConverter converter = (this.typeConverter != null ? this.typeConverter : bw);
|
||||
|
||||
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
|
||||
Set usedValueHolders = new HashSet(paramTypes.length);
|
||||
Set autowiredBeanNames = new LinkedHashSet(4);
|
||||
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders =
|
||||
new HashSet<ConstructorArgumentValues.ValueHolder>(paramTypes.length);
|
||||
Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
|
||||
boolean resolveNecessary = false;
|
||||
|
||||
for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
|
||||
|
|
@ -589,8 +585,7 @@ class ConstructorResolver {
|
|||
}
|
||||
}
|
||||
|
||||
for (Iterator it = autowiredBeanNames.iterator(); it.hasNext();) {
|
||||
String autowiredBeanName = (String) it.next();
|
||||
for (String autowiredBeanName : autowiredBeanNames) {
|
||||
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
|
||||
if (this.beanFactory.logger.isDebugEnabled()) {
|
||||
this.beanFactory.logger.debug("Autowiring by type from bean name '" + beanName +
|
||||
|
|
@ -612,7 +607,7 @@ class ConstructorResolver {
|
|||
* Template method for resolving the specified argument which is supposed to be autowired.
|
||||
*/
|
||||
protected Object resolveAutowiredArgument(
|
||||
MethodParameter param, String beanName, Set autowiredBeanNames, TypeConverter typeConverter) {
|
||||
MethodParameter param, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) {
|
||||
|
||||
return this.autowireFactory.resolveDependency(
|
||||
new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ import org.springframework.beans.factory.FactoryBean;
|
|||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.SmartFactoryBean;
|
||||
import org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
|
|
@ -87,8 +86,11 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
/** Whether to allow eager class loading even for lazy-init beans */
|
||||
private boolean allowEagerClassLoading = true;
|
||||
|
||||
/** Whether bean definition metadata may be cached for all beans */
|
||||
private boolean configurationFrozen = false;
|
||||
/** Resolver to use for checking if a bean definition is an autowire candidate */
|
||||
private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
|
||||
|
||||
/** Map from dependency type to corresponding autowired value */
|
||||
private final Map<Class, Object> resolvableDependencies = new HashMap<Class, Object>();
|
||||
|
||||
/** Map of bean definition objects, keyed by bean name */
|
||||
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
|
||||
|
|
@ -96,15 +98,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
/** List of bean definition names, in registration order */
|
||||
private final List<String> beanDefinitionNames = new ArrayList<String>();
|
||||
|
||||
/** Whether bean definition metadata may be cached for all beans */
|
||||
private boolean configurationFrozen = false;
|
||||
|
||||
/** Cached array of bean definition names in case of frozen configuration */
|
||||
private String[] frozenBeanDefinitionNames;
|
||||
|
||||
/** Resolver to use for checking if a bean definition is an autowire candidate */
|
||||
private AutowireCandidateResolver autowireCandidateResolver = new QualifierAnnotationAutowireCandidateResolver();
|
||||
|
||||
/** Map from dependency type to corresponding autowired value */
|
||||
private final Map<Class, Object> resolvableDependencies = new HashMap<Class, Object>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new DefaultListableBeanFactory.
|
||||
|
|
@ -122,23 +121,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a custom autowire candidate resolver for this BeanFactory to use
|
||||
* when deciding whether a bean definition should be considered as a
|
||||
* candidate for autowiring.
|
||||
*/
|
||||
public void setAutowireCandidateResolver(AutowireCandidateResolver autowireCandidateResolver) {
|
||||
Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null");
|
||||
this.autowireCandidateResolver = autowireCandidateResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the autowire candidate resolver for this BeanFactory (never <code>null</code>).
|
||||
*/
|
||||
public AutowireCandidateResolver getAutowireCandidateResolver() {
|
||||
return this.autowireCandidateResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether it should be allowed to override bean definitions by registering
|
||||
* a different definition with the same name, automatically replacing the former.
|
||||
|
|
@ -164,6 +146,23 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
this.allowEagerClassLoading = allowEagerClassLoading;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a custom autowire candidate resolver for this BeanFactory to use
|
||||
* when deciding whether a bean definition should be considered as a
|
||||
* candidate for autowiring.
|
||||
*/
|
||||
public void setAutowireCandidateResolver(AutowireCandidateResolver autowireCandidateResolver) {
|
||||
Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null");
|
||||
this.autowireCandidateResolver = autowireCandidateResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the autowire candidate resolver for this BeanFactory (never <code>null</code>).
|
||||
*/
|
||||
public AutowireCandidateResolver getAutowireCandidateResolver() {
|
||||
return this.autowireCandidateResolver;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
|
||||
|
|
@ -172,6 +171,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
DefaultListableBeanFactory otherListableFactory = (DefaultListableBeanFactory) otherFactory;
|
||||
this.allowBeanDefinitionOverriding = otherListableFactory.allowBeanDefinitionOverriding;
|
||||
this.allowEagerClassLoading = otherListableFactory.allowEagerClassLoading;
|
||||
this.autowireCandidateResolver = otherListableFactory.autowireCandidateResolver;
|
||||
this.resolvableDependencies.putAll(otherListableFactory.resolvableDependencies);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -542,6 +543,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
|
||||
|
||||
Class type = descriptor.getDependencyType();
|
||||
|
||||
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
|
||||
if (value != null) {
|
||||
if (value instanceof String) {
|
||||
value = evaluateBeanDefinitionString((String) value, getMergedBeanDefinition(beanName));
|
||||
}
|
||||
return typeConverter.convertIfNecessary(value, type);
|
||||
}
|
||||
|
||||
if (type.isArray()) {
|
||||
Class componentType = type.getComponentType();
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, descriptor);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2008 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.
|
||||
|
|
@ -18,7 +18,6 @@ package org.springframework.beans.factory.support;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
|
@ -35,7 +34,7 @@ import java.util.Set;
|
|||
*/
|
||||
public class MethodOverrides {
|
||||
|
||||
private final Set overrides = new HashSet();
|
||||
private final Set<MethodOverride> overrides = new HashSet<MethodOverride>();
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -73,7 +72,7 @@ public class MethodOverrides {
|
|||
* @return Set of MethodOverride objects
|
||||
* @see MethodOverride
|
||||
*/
|
||||
public Set getOverrides() {
|
||||
public Set<MethodOverride> getOverrides() {
|
||||
return this.overrides;
|
||||
}
|
||||
|
||||
|
|
@ -90,25 +89,25 @@ public class MethodOverrides {
|
|||
* @return the method override, or <code>null</code> if none
|
||||
*/
|
||||
public MethodOverride getOverride(Method method) {
|
||||
for (Iterator it = this.overrides.iterator(); it.hasNext();) {
|
||||
MethodOverride methodOverride = (MethodOverride) it.next();
|
||||
if (methodOverride.matches(method)) {
|
||||
return methodOverride;
|
||||
}
|
||||
for (MethodOverride override : this.overrides) {
|
||||
if (override.matches(method)) {
|
||||
return override;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof MethodOverrides)) {
|
||||
return false;
|
||||
}
|
||||
MethodOverrides that = (MethodOverrides) other;
|
||||
return this.overrides.equals(that.overrides);
|
||||
|
||||
MethodOverrides that = (MethodOverrides) o;
|
||||
|
||||
if (!this.overrides.equals(that.overrides)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2008 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.
|
||||
|
|
@ -36,10 +36,12 @@ public class SimpleAutowireCandidateResolver implements AutowireCandidateResolve
|
|||
* <p>To be considered a candidate the bean's <em>autowire-candidate</em>
|
||||
* attribute must not have been set to 'false'.
|
||||
*/
|
||||
public boolean isAutowireCandidate(
|
||||
BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
|
||||
|
||||
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
|
||||
return bdHolder.getBeanDefinition().isAutowireCandidate();
|
||||
}
|
||||
|
||||
public Object getSuggestedValue(DependencyDescriptor descriptor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ public class AnnotationConfigUtils {
|
|||
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
|
||||
|
||||
// Default infrastructure bean: lowest order value; role infrastructure.
|
||||
definition.getPropertyValues().addPropertyValue("order", new Integer(Ordered.LOWEST_PRECEDENCE));
|
||||
definition.getPropertyValues().addPropertyValue("order", Ordered.LOWEST_PRECEDENCE);
|
||||
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
||||
registry.registerBeanDefinition(beanName, definition);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.springframework.context.support;
|
|||
import java.io.IOException;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
|
@ -195,11 +196,12 @@ public abstract class AbstractRefreshableApplicationContext extends AbstractAppl
|
|||
*/
|
||||
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
|
||||
if (this.allowBeanDefinitionOverriding != null) {
|
||||
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding.booleanValue());
|
||||
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
|
||||
}
|
||||
if (this.allowCircularReferences != null) {
|
||||
beanFactory.setAllowCircularReferences(this.allowCircularReferences.booleanValue());
|
||||
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
|
||||
}
|
||||
beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import java.io.IOException;
|
|||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
|
|
@ -97,6 +98,7 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
|
|||
*/
|
||||
public GenericApplicationContext() {
|
||||
this.beanFactory = new DefaultListableBeanFactory();
|
||||
this.beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -20,8 +20,13 @@ import junit.framework.TestCase;
|
|||
|
||||
import org.springframework.beans.TestBean;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.config.Scope;
|
||||
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.context.annotation.AnnotationConfigUtils;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
|
||||
/**
|
||||
|
|
@ -31,6 +36,8 @@ public class ApplicationContextExpressionTests extends TestCase {
|
|||
|
||||
public void testGenericApplicationContext() {
|
||||
GenericApplicationContext ac = new GenericApplicationContext();
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(ac);
|
||||
|
||||
ac.getBeanFactory().registerScope("myScope", new Scope() {
|
||||
public Object get(String name, ObjectFactory objectFactory) {
|
||||
return objectFactory.getObject();
|
||||
|
|
@ -52,28 +59,143 @@ public class ApplicationContextExpressionTests extends TestCase {
|
|||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
GenericBeanDefinition bd0 = new GenericBeanDefinition();
|
||||
bd0.setBeanClass(TestBean.class);
|
||||
bd0.getPropertyValues().addPropertyValue("name", "myName");
|
||||
bd0.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "original"));
|
||||
ac.registerBeanDefinition("tb0", bd0);
|
||||
|
||||
GenericBeanDefinition bd1 = new GenericBeanDefinition();
|
||||
bd1.setBeanClass(TestBean.class);
|
||||
bd1.getPropertyValues().addPropertyValue("name", "myName");
|
||||
bd1.setScope("myScope");
|
||||
bd1.getConstructorArgumentValues().addGenericArgumentValue("XXX#{tb0.name}YYY#{mySpecialAttr}ZZZ");
|
||||
bd1.getConstructorArgumentValues().addGenericArgumentValue("#{mySpecialAttr}");
|
||||
ac.registerBeanDefinition("tb1", bd1);
|
||||
|
||||
GenericBeanDefinition bd2 = new GenericBeanDefinition();
|
||||
bd2.setBeanClass(TestBean.class);
|
||||
bd2.setScope("myScope");
|
||||
bd2.getPropertyValues().addPropertyValue("name", "XXX#{tb1.name}YYY#{mySpecialAttr}ZZZ");
|
||||
bd2.getPropertyValues().addPropertyValue("name", "XXX#{tb0.name}YYY#{mySpecialAttr}ZZZ");
|
||||
bd2.getPropertyValues().addPropertyValue("age", "#{mySpecialAttr}");
|
||||
bd2.getPropertyValues().addPropertyValue("country", "#{systemProperties.country}");
|
||||
ac.registerBeanDefinition("tb2", bd2);
|
||||
|
||||
GenericBeanDefinition bd3 = new GenericBeanDefinition();
|
||||
bd3.setBeanClass(ValueTestBean.class);
|
||||
bd3.setScope("myScope");
|
||||
ac.registerBeanDefinition("tb3", bd3);
|
||||
|
||||
GenericBeanDefinition bd4 = new GenericBeanDefinition();
|
||||
bd4.setBeanClass(ConstructorValueTestBean.class);
|
||||
bd4.setScope("myScope");
|
||||
ac.registerBeanDefinition("tb4", bd4);
|
||||
|
||||
GenericBeanDefinition bd5 = new GenericBeanDefinition();
|
||||
bd5.setBeanClass(MethodValueTestBean.class);
|
||||
bd5.setScope("myScope");
|
||||
ac.registerBeanDefinition("tb5", bd5);
|
||||
|
||||
System.getProperties().put("country", "UK");
|
||||
try {
|
||||
ac.refresh();
|
||||
TestBean tb2 = (TestBean) ac.getBean("tb2");
|
||||
|
||||
TestBean tb0 = ac.getBean("tb0", TestBean.class);
|
||||
|
||||
TestBean tb1 = ac.getBean("tb1", TestBean.class);
|
||||
assertEquals("XXXmyNameYYY42ZZZ", tb1.getName());
|
||||
assertEquals(42, tb1.getAge());
|
||||
|
||||
TestBean tb2 = ac.getBean("tb2", TestBean.class);
|
||||
assertEquals("XXXmyNameYYY42ZZZ", tb2.getName());
|
||||
assertEquals(42, tb2.getAge());
|
||||
assertEquals("UK", tb2.getCountry());
|
||||
|
||||
ValueTestBean tb3 = ac.getBean("tb3", ValueTestBean.class);
|
||||
assertEquals("XXXmyNameYYY42ZZZ", tb3.name);
|
||||
assertEquals(42, tb3.age);
|
||||
assertEquals("UK", tb3.country);
|
||||
assertSame(tb0, tb3.tb);
|
||||
|
||||
ConstructorValueTestBean tb4 = ac.getBean("tb4", ConstructorValueTestBean.class);
|
||||
assertEquals("XXXmyNameYYY42ZZZ", tb4.name);
|
||||
assertEquals(42, tb4.age);
|
||||
assertEquals("UK", tb4.country);
|
||||
assertSame(tb0, tb4.tb);
|
||||
|
||||
MethodValueTestBean tb5 = ac.getBean("tb5", MethodValueTestBean.class);
|
||||
assertEquals("XXXmyNameYYY42ZZZ", tb5.name);
|
||||
assertEquals(42, tb5.age);
|
||||
assertEquals("UK", tb5.country);
|
||||
assertSame(tb0, tb5.tb);
|
||||
}
|
||||
finally {
|
||||
System.getProperties().remove("country");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ValueTestBean {
|
||||
|
||||
@Autowired @Value("XXX#{tb0.name}YYY#{mySpecialAttr}ZZZ")
|
||||
public String name;
|
||||
|
||||
@Autowired @Value("#{mySpecialAttr}")
|
||||
public int age;
|
||||
|
||||
@Value("#{systemProperties.country}")
|
||||
public String country;
|
||||
|
||||
@Qualifier("original")
|
||||
public TestBean tb;
|
||||
}
|
||||
|
||||
|
||||
public static class ConstructorValueTestBean {
|
||||
|
||||
public String name;
|
||||
|
||||
public int age;
|
||||
|
||||
public String country;
|
||||
|
||||
public TestBean tb;
|
||||
|
||||
@Autowired
|
||||
public ConstructorValueTestBean(
|
||||
@Value("XXX#{tb0.name}YYY#{mySpecialAttr}ZZZ") String name,
|
||||
@Value("#{mySpecialAttr}")int age,
|
||||
@Qualifier("original") TestBean tb,
|
||||
@Value("#{systemProperties.country}") String country) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
this.country = country;
|
||||
this.tb = tb;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class MethodValueTestBean {
|
||||
|
||||
public String name;
|
||||
|
||||
public int age;
|
||||
|
||||
public String country;
|
||||
|
||||
public TestBean tb;
|
||||
|
||||
@Autowired
|
||||
public void configure(
|
||||
@Qualifier("original") TestBean tb,
|
||||
@Value("XXX#{tb0.name}YYY#{mySpecialAttr}ZZZ") String name,
|
||||
@Value("#{mySpecialAttr}")int age,
|
||||
@Value("#{systemProperties.country}") String country) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
this.country = country;
|
||||
this.tb = tb;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ import org.springframework.util.Assert;
|
|||
public abstract class AnnotationUtils {
|
||||
|
||||
/** The attribute name for annotations with a single element */
|
||||
static final String VALUE = "value";
|
||||
static final String VALUE = "value";
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2008 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.
|
||||
|
|
@ -76,6 +76,10 @@ public class CustomAutowireConfigurerTests extends TestCase {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object getSuggestedValue(DependencyDescriptor descriptor) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue