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