diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java index 5832b90cdb5..ae889fc7056 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java @@ -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. + *
The default autowired annotation type is the Spring-provided + * {@link Autowired} annotation. + *
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
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/CustomAutowireConfigurer.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/CustomAutowireConfigurer.java
index 7baf644e4e9..91bc3b5bfe3 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/CustomAutowireConfigurer.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/CustomAutowireConfigurer.java
@@ -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;
}
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/InjectionMetadata.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/InjectionMetadata.java
index f26bc1ff655..89b55da372e 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/InjectionMetadata.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/InjectionMetadata.java
@@ -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 {
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java
index f4497ad316e..6b1cbc3ed6f 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java
@@ -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 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.
* 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.
+ * The default value annotation type is the Spring-provided
+ * {@link Value} annotation.
+ * 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.
* To be considered a candidate the bean's autowire-candidate
@@ -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;
+ }
+
}
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/Value.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/Value.java
index beaba9be815..da290eccaf4 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/Value.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/Value.java
@@ -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.
+ *
+ * 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();
}
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java
index 94c3cc627d4..49eba911199 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java
@@ -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 To be considered a candidate the bean's autowire-candidate
* 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;
+ }
+
}
diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java
index 5c05e22dabe..362b5aad45b 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java
@@ -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);
diff --git a/org.springframework.context/src/main/java/org/springframework/context/support/AbstractRefreshableApplicationContext.java b/org.springframework.context/src/main/java/org/springframework/context/support/AbstractRefreshableApplicationContext.java
index df6f5061bfa..4d76a1d696f 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/support/AbstractRefreshableApplicationContext.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/support/AbstractRefreshableApplicationContext.java
@@ -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());
}
/**
diff --git a/org.springframework.context/src/main/java/org/springframework/context/support/GenericApplicationContext.java b/org.springframework.context/src/main/java/org/springframework/context/support/GenericApplicationContext.java
index 23bfecf00c6..b8fab005bbe 100644
--- a/org.springframework.context/src/main/java/org/springframework/context/support/GenericApplicationContext.java
+++ b/org.springframework.context/src/main/java/org/springframework/context/support/GenericApplicationContext.java
@@ -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());
}
/**
diff --git a/org.springframework.context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java b/org.springframework.context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java
index 38e82eeaa33..6659be1bc04 100644
--- a/org.springframework.context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java
+++ b/org.springframework.context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java
@@ -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;
+ }
+ }
+
}
diff --git a/org.springframework.core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java b/org.springframework.core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java
index 5e38149b444..94af2c95bd2 100644
--- a/org.springframework.core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java
+++ b/org.springframework.core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java
@@ -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";
/**
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/annotation/CustomAutowireConfigurerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/annotation/CustomAutowireConfigurerTests.java
index 22310cc587c..f752db1a842 100644
--- a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/annotation/CustomAutowireConfigurerTests.java
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/annotation/CustomAutowireConfigurerTests.java
@@ -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;
+ }
}
}
null 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 Listnull if none found
+ */
+ Object getSuggestedValue(DependencyDescriptor descriptor);
+
}
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java
index 87b2a8aa175..2585a913523 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java
@@ -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;
+ Listnull).
- */
- 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 null).
+ */
+ 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
Setnull 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;
-
- MethodOverrides that = (MethodOverrides) o;
-
- if (!this.overrides.equals(that.overrides)) 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);
- return true;
}
@Override
diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java
index 92830ddf46f..3eb526fd6f2 100644
--- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java
+++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java
@@ -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
*