initial JSR-330 injection support

This commit is contained in:
Juergen Hoeller
2009-09-15 12:00:55 +00:00
parent 429d78b902
commit e1a3e44485
24 changed files with 2315 additions and 252 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2009 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.
@@ -39,6 +39,8 @@ import org.springframework.util.StringUtils;
* themselves annotated with
* {@link org.springframework.stereotype.Component @Component}.
*
* <p>Also supports JSR-330's {@link javax.inject.Named} annotation, if available.
*
* <p>If the annotation's value doesn't indicate a bean name, an appropriate
* name will be built based on the short name of the class (with the first
* letter lower-cased). For example:
@@ -52,6 +54,7 @@ import org.springframework.util.StringUtils;
* @see org.springframework.stereotype.Repository#value()
* @see org.springframework.stereotype.Service#value()
* @see org.springframework.stereotype.Controller#value()
* @see javax.inject.Named#value()
*/
public class AnnotationBeanNameGenerator implements BeanNameGenerator {
@@ -107,7 +110,8 @@ public class AnnotationBeanNameGenerator implements BeanNameGenerator {
Set<String> metaAnnotationTypes, Map<String, Object> attributes) {
boolean isStereotype = annotationType.equals(COMPONENT_ANNOTATION_CLASSNAME) ||
(metaAnnotationTypes != null && metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME));
(metaAnnotationTypes != null && metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME)) ||
annotationType.equals("javax.inject.Named");
return (isStereotype && attributes != null && attributes.containsKey("value"));
}

View File

@@ -199,6 +199,8 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
for (String basePackage : basePackages) {
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
@@ -219,8 +221,7 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
definitionHolder = applyScope(definitionHolder, scopeMetadata);
definitionHolder = applyScopedProxyMode(definitionHolder, scopeMetadata);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
@@ -301,19 +302,17 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
/**
* Apply the specified scope to the given bean definition.
* @param definitionHolder the bean definition to configure
* @param scopeMetadata the corresponding scope metadata
* @param definition the bean definition to configure
* @param metadata the corresponding scope metadata
* @return the final bean definition to use (potentially a proxy)
*/
private BeanDefinitionHolder applyScope(BeanDefinitionHolder definitionHolder, ScopeMetadata scopeMetadata) {
String scope = scopeMetadata.getScopeName();
ScopedProxyMode scopedProxyMode = scopeMetadata.getScopedProxyMode();
definitionHolder.getBeanDefinition().setScope(scope);
private BeanDefinitionHolder applyScopedProxyMode(BeanDefinitionHolder definition, ScopeMetadata metadata) {
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
return definitionHolder;
return definition;
}
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
return ScopedProxyCreator.createScopedProxy(definitionHolder, this.registry, proxyTargetClass);
return ScopedProxyCreator.createScopedProxy(definition, this.registry, proxyTargetClass);
}

View File

@@ -17,6 +17,7 @@
package org.springframework.context.annotation;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
@@ -164,8 +165,20 @@ public class ClassPathScanningCandidateComponentProvider implements ResourceLoad
* {@link Repository @Repository}, {@link Service @Service}, and
* {@link Controller @Controller} stereotype annotations.
*/
@SuppressWarnings("unchecked")
protected void registerDefaultFilters() {
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
this.includeFilters.add(new AnnotationTypeFilter(Scope.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) cl.loadClass("javax.inject.Named"))));
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) cl.loadClass("javax.inject.Scope"))));
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}

View File

@@ -0,0 +1,691 @@
/*
* Copyright 2002-2009 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.support;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Qualifier;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.aop.scope.ScopedProxyUtils;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.UnsatisfiedDependencyException;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.support.GenericApplicationContext;
/**
* Integration tests for handling JSR-303 {@link javax.inject.Qualifier} annotations.
*
* @author Juergen Hoeller
* @since 3.0
*/
public class InjectAnnotationAutowireContextTests {
private static final String JUERGEN = "juergen";
private static final String MARK = "mark";
@Test
public void testAutowiredFieldWithSingleNonQualifiedCandidate() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person = new RootBeanDefinition(Person.class, cavs, null);
context.registerBeanDefinition(JUERGEN, person);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedFieldTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
try {
context.refresh();
fail("expected BeanCreationException");
}
catch (BeanCreationException e) {
assertTrue(e.getRootCause() instanceof NoSuchBeanDefinitionException);
assertEquals("autowired", e.getBeanName());
}
}
@Test
public void testAutowiredMethodParameterWithSingleNonQualifiedCandidate() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person = new RootBeanDefinition(Person.class, cavs, null);
context.registerBeanDefinition(JUERGEN, person);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedMethodParameterTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
try {
context.refresh();
fail("expected BeanCreationException");
}
catch (BeanCreationException e) {
assertTrue(e.getRootCause() instanceof NoSuchBeanDefinitionException);
assertEquals("autowired", e.getBeanName());
}
}
@Test
public void testAutowiredConstructorArgumentWithSingleNonQualifiedCandidate() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person = new RootBeanDefinition(Person.class, cavs, null);
context.registerBeanDefinition(JUERGEN, person);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedConstructorArgumentTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
try {
context.refresh();
fail("expected BeanCreationException");
}
catch (BeanCreationException e) {
assertTrue(e instanceof UnsatisfiedDependencyException);
assertEquals("autowired", e.getBeanName());
}
}
@Test
public void testAutowiredFieldWithSingleQualifiedCandidate() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person = new RootBeanDefinition(Person.class, cavs, null);
person.addQualifier(new AutowireCandidateQualifier(TestQualifier.class));
context.registerBeanDefinition(JUERGEN, person);
context.registerBeanDefinition("autowired", new RootBeanDefinition(QualifiedFieldTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
context.refresh();
QualifiedFieldTestBean bean = (QualifiedFieldTestBean) context.getBean("autowired");
assertEquals(JUERGEN, bean.getPerson().getName());
}
@Test
public void testAutowiredMethodParameterWithSingleQualifiedCandidate() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person = new RootBeanDefinition(Person.class, cavs, null);
person.addQualifier(new AutowireCandidateQualifier(TestQualifier.class));
context.registerBeanDefinition(JUERGEN, person);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedMethodParameterTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
context.refresh();
QualifiedMethodParameterTestBean bean =
(QualifiedMethodParameterTestBean) context.getBean("autowired");
assertEquals(JUERGEN, bean.getPerson().getName());
}
@Test
public void testAutowiredMethodParameterWithStaticallyQualifiedCandidate() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person = new RootBeanDefinition(QualifiedPerson.class, cavs, null);
context.registerBeanDefinition(JUERGEN,
ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(person, JUERGEN), context, true).getBeanDefinition());
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedMethodParameterTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
context.refresh();
QualifiedMethodParameterTestBean bean =
(QualifiedMethodParameterTestBean) context.getBean("autowired");
assertEquals(JUERGEN, bean.getPerson().getName());
}
@Test
public void testAutowiredMethodParameterWithStaticallyQualifiedCandidateAmongOthers() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person = new RootBeanDefinition(QualifiedPerson.class, cavs, null);
ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
cavs2.addGenericArgumentValue(MARK);
RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
context.registerBeanDefinition(JUERGEN, person);
context.registerBeanDefinition(MARK, person2);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedMethodParameterTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
context.refresh();
QualifiedMethodParameterTestBean bean =
(QualifiedMethodParameterTestBean) context.getBean("autowired");
assertEquals(JUERGEN, bean.getPerson().getName());
}
@Test
public void testAutowiredConstructorArgumentWithSingleQualifiedCandidate() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
cavs.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person = new RootBeanDefinition(Person.class, cavs, null);
person.addQualifier(new AutowireCandidateQualifier(TestQualifier.class));
context.registerBeanDefinition(JUERGEN, person);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedConstructorArgumentTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
context.refresh();
QualifiedConstructorArgumentTestBean bean =
(QualifiedConstructorArgumentTestBean) context.getBean("autowired");
assertEquals(JUERGEN, bean.getPerson().getName());
}
@Test
public void testAutowiredFieldWithMultipleNonQualifiedCandidates() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
cavs1.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
cavs2.addGenericArgumentValue(MARK);
RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
context.registerBeanDefinition(JUERGEN, person1);
context.registerBeanDefinition(MARK, person2);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedFieldTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
try {
context.refresh();
fail("expected BeanCreationException");
}
catch (BeanCreationException e) {
assertTrue(e.getRootCause() instanceof NoSuchBeanDefinitionException);
assertEquals("autowired", e.getBeanName());
}
}
@Test
public void testAutowiredMethodParameterWithMultipleNonQualifiedCandidates() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
cavs1.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
cavs2.addGenericArgumentValue(MARK);
RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
context.registerBeanDefinition(JUERGEN, person1);
context.registerBeanDefinition(MARK, person2);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedMethodParameterTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
try {
context.refresh();
fail("expected BeanCreationException");
}
catch (BeanCreationException e) {
assertTrue(e.getRootCause() instanceof NoSuchBeanDefinitionException);
assertEquals("autowired", e.getBeanName());
}
}
@Test
public void testAutowiredConstructorArgumentWithMultipleNonQualifiedCandidates() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
cavs1.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
cavs2.addGenericArgumentValue(MARK);
RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
context.registerBeanDefinition(JUERGEN, person1);
context.registerBeanDefinition(MARK, person2);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedConstructorArgumentTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
try {
context.refresh();
fail("expected BeanCreationException");
}
catch (BeanCreationException e) {
assertTrue(e instanceof UnsatisfiedDependencyException);
assertEquals("autowired", e.getBeanName());
}
}
@Test
public void testAutowiredFieldResolvesQualifiedCandidate() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
cavs1.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
person1.addQualifier(new AutowireCandidateQualifier(TestQualifier.class));
ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
cavs2.addGenericArgumentValue(MARK);
RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
context.registerBeanDefinition(JUERGEN, person1);
context.registerBeanDefinition(MARK, person2);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedFieldTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
context.refresh();
QualifiedFieldTestBean bean = (QualifiedFieldTestBean) context.getBean("autowired");
assertEquals(JUERGEN, bean.getPerson().getName());
}
@Test
public void testAutowiredMethodParameterResolvesQualifiedCandidate() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
cavs1.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
person1.addQualifier(new AutowireCandidateQualifier(TestQualifier.class));
ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
cavs2.addGenericArgumentValue(MARK);
RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
context.registerBeanDefinition(JUERGEN, person1);
context.registerBeanDefinition(MARK, person2);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedMethodParameterTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
context.refresh();
QualifiedMethodParameterTestBean bean =
(QualifiedMethodParameterTestBean) context.getBean("autowired");
assertEquals(JUERGEN, bean.getPerson().getName());
}
@Test
public void testAutowiredConstructorArgumentResolvesQualifiedCandidate() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
cavs1.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
person1.addQualifier(new AutowireCandidateQualifier(TestQualifier.class));
ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
cavs2.addGenericArgumentValue(MARK);
RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
context.registerBeanDefinition(JUERGEN, person1);
context.registerBeanDefinition(MARK, person2);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedConstructorArgumentTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
context.refresh();
QualifiedConstructorArgumentTestBean bean =
(QualifiedConstructorArgumentTestBean) context.getBean("autowired");
assertEquals(JUERGEN, bean.getPerson().getName());
}
@Test
public void testAutowiredFieldResolvesQualifiedCandidateWithDefaultValueAndNoValueOnBeanDefinition() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
cavs1.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
// qualifier added, but includes no value
person1.addQualifier(new AutowireCandidateQualifier(TestQualifierWithDefaultValue.class));
ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
cavs2.addGenericArgumentValue(MARK);
RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
context.registerBeanDefinition(JUERGEN, person1);
context.registerBeanDefinition(MARK, person2);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedFieldWithDefaultValueTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
context.refresh();
QualifiedFieldWithDefaultValueTestBean bean =
(QualifiedFieldWithDefaultValueTestBean) context.getBean("autowired");
assertEquals(JUERGEN, bean.getPerson().getName());
}
@Test
public void testAutowiredFieldDoesNotResolveCandidateWithDefaultValueAndConflictingValueOnBeanDefinition() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
cavs1.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
// qualifier added, and non-default value specified
person1.addQualifier(new AutowireCandidateQualifier(TestQualifierWithDefaultValue.class, "not the default"));
ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
cavs2.addGenericArgumentValue(MARK);
RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
context.registerBeanDefinition(JUERGEN, person1);
context.registerBeanDefinition(MARK, person2);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedFieldWithDefaultValueTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
try {
context.refresh();
fail("expected BeanCreationException");
}
catch (BeanCreationException e) {
assertTrue(e.getRootCause() instanceof NoSuchBeanDefinitionException);
assertEquals("autowired", e.getBeanName());
}
}
@Test
public void testAutowiredFieldResolvesWithDefaultValueAndExplicitDefaultValueOnBeanDefinition() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
cavs1.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
// qualifier added, and value matches the default
person1.addQualifier(new AutowireCandidateQualifier(TestQualifierWithDefaultValue.class, "default"));
ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
cavs2.addGenericArgumentValue(MARK);
RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
context.registerBeanDefinition(JUERGEN, person1);
context.registerBeanDefinition(MARK, person2);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedFieldWithDefaultValueTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
context.refresh();
QualifiedFieldWithDefaultValueTestBean bean =
(QualifiedFieldWithDefaultValueTestBean) context.getBean("autowired");
assertEquals(JUERGEN, bean.getPerson().getName());
}
@Test
public void testAutowiredFieldResolvesWithMultipleQualifierValues() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
cavs1.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(TestQualifierWithMultipleAttributes.class);
qualifier.setAttribute("number", 456);
person1.addQualifier(qualifier);
ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
cavs2.addGenericArgumentValue(MARK);
RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
AutowireCandidateQualifier qualifier2 = new AutowireCandidateQualifier(TestQualifierWithMultipleAttributes.class);
qualifier2.setAttribute("number", 123);
person2.addQualifier(qualifier2);
context.registerBeanDefinition(JUERGEN, person1);
context.registerBeanDefinition(MARK, person2);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedFieldWithMultipleAttributesTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
context.refresh();
QualifiedFieldWithMultipleAttributesTestBean bean =
(QualifiedFieldWithMultipleAttributesTestBean) context.getBean("autowired");
assertEquals(MARK, bean.getPerson().getName());
}
@Test
public void testAutowiredFieldDoesNotResolveWithMultipleQualifierValuesAndConflictingDefaultValue() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
cavs1.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(TestQualifierWithMultipleAttributes.class);
qualifier.setAttribute("number", 456);
person1.addQualifier(qualifier);
ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
cavs2.addGenericArgumentValue(MARK);
RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
AutowireCandidateQualifier qualifier2 = new AutowireCandidateQualifier(TestQualifierWithMultipleAttributes.class);
qualifier2.setAttribute("number", 123);
qualifier2.setAttribute("value", "not the default");
person2.addQualifier(qualifier2);
context.registerBeanDefinition(JUERGEN, person1);
context.registerBeanDefinition(MARK, person2);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedFieldWithMultipleAttributesTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
try {
context.refresh();
fail("expected BeanCreationException");
}
catch (BeanCreationException e) {
assertTrue(e.getRootCause() instanceof NoSuchBeanDefinitionException);
assertEquals("autowired", e.getBeanName());
}
}
@Test
public void testAutowiredFieldResolvesWithMultipleQualifierValuesAndExplicitDefaultValue() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
cavs1.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(TestQualifierWithMultipleAttributes.class);
qualifier.setAttribute("number", 456);
person1.addQualifier(qualifier);
ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
cavs2.addGenericArgumentValue(MARK);
RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
AutowireCandidateQualifier qualifier2 = new AutowireCandidateQualifier(TestQualifierWithMultipleAttributes.class);
qualifier2.setAttribute("number", 123);
qualifier2.setAttribute("value", "default");
person2.addQualifier(qualifier2);
context.registerBeanDefinition(JUERGEN, person1);
context.registerBeanDefinition(MARK, person2);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedFieldWithMultipleAttributesTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
context.refresh();
QualifiedFieldWithMultipleAttributesTestBean bean =
(QualifiedFieldWithMultipleAttributesTestBean) context.getBean("autowired");
assertEquals(MARK, bean.getPerson().getName());
}
@Test
public void testAutowiredFieldDoesNotResolveWithMultipleQualifierValuesAndMultipleMatchingCandidates() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
cavs1.addGenericArgumentValue(JUERGEN);
RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(TestQualifierWithMultipleAttributes.class);
qualifier.setAttribute("number", 123);
person1.addQualifier(qualifier);
ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
cavs2.addGenericArgumentValue(MARK);
RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
AutowireCandidateQualifier qualifier2 = new AutowireCandidateQualifier(TestQualifierWithMultipleAttributes.class);
qualifier2.setAttribute("number", 123);
qualifier2.setAttribute("value", "default");
person2.addQualifier(qualifier2);
context.registerBeanDefinition(JUERGEN, person1);
context.registerBeanDefinition(MARK, person2);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedFieldWithMultipleAttributesTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
try {
context.refresh();
fail("expected BeanCreationException");
}
catch (BeanCreationException e) {
assertTrue(e.getRootCause() instanceof NoSuchBeanDefinitionException);
assertEquals("autowired", e.getBeanName());
}
}
@Test
public void testAutowiredFieldDoesNotResolveWithBaseQualifierAndNonDefaultValueAndMultipleMatchingCandidates() {
GenericApplicationContext context = new GenericApplicationContext();
ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
cavs1.addGenericArgumentValue("the real juergen");
RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
person1.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "juergen"));
ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
cavs2.addGenericArgumentValue("juergen imposter");
RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
person2.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "juergen"));
context.registerBeanDefinition("juergen1", person1);
context.registerBeanDefinition("juergen2", person2);
context.registerBeanDefinition("autowired",
new RootBeanDefinition(QualifiedConstructorArgumentWithBaseQualifierNonDefaultValueTestBean.class));
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
try {
context.refresh();
fail("expected BeanCreationException");
}
catch (BeanCreationException e) {
assertTrue(e instanceof UnsatisfiedDependencyException);
assertEquals("autowired", e.getBeanName());
}
}
private static class QualifiedFieldTestBean {
@Inject
@TestQualifier
private Person person;
public Person getPerson() {
return this.person;
}
}
private static class QualifiedMethodParameterTestBean {
private Person person;
@Inject
public void setPerson(@TestQualifier Person person) {
this.person = person;
}
public Person getPerson() {
return this.person;
}
}
private static class QualifiedConstructorArgumentTestBean {
private Person person;
@Inject
public QualifiedConstructorArgumentTestBean(@TestQualifier Person person) {
this.person = person;
}
public Person getPerson() {
return this.person;
}
}
public static class QualifiedFieldWithDefaultValueTestBean {
@Inject
@TestQualifierWithDefaultValue
private Person person;
public Person getPerson() {
return this.person;
}
}
public static class QualifiedFieldWithMultipleAttributesTestBean {
@Inject
@TestQualifierWithMultipleAttributes(number=123)
private Person person;
public Person getPerson() {
return this.person;
}
}
private static class QualifiedFieldWithBaseQualifierDefaultValueTestBean {
@Inject
private Person person;
public Person getPerson() {
return this.person;
}
}
public static class QualifiedConstructorArgumentWithBaseQualifierNonDefaultValueTestBean {
private Person person;
@Inject
public QualifiedConstructorArgumentWithBaseQualifierNonDefaultValueTestBean(
@Named("juergen") Person person) {
this.person = person;
}
public Person getPerson() {
return this.person;
}
}
private static class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
@TestQualifier
private static class QualifiedPerson extends Person {
public QualifiedPerson() {
super(null);
}
public QualifiedPerson(String name) {
super(name);
}
}
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public static @interface TestQualifier {
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public static @interface TestQualifierWithDefaultValue {
public abstract String value() default "default";
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public static @interface TestQualifierWithMultipleAttributes {
public abstract String value() default "default";
public abstract int number();
}
}

View File

@@ -16,6 +16,12 @@
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Retention;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
@@ -69,6 +75,15 @@ public final class AnnotationScopeMetadataResolverTests {
assertEquals(ScopedProxyMode.TARGET_CLASS, scopeMetadata.getScopedProxyMode());
}
@Test
public void testCustomRequestScope() {
AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(AnnotatedWithCustomRequestScope.class);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd);
assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata);
assertEquals("request", scopeMetadata.getScopeName());
assertEquals(ScopedProxyMode.NO, scopeMetadata.getScopedProxyMode());
}
@Test(expected=IllegalArgumentException.class)
public void testCtorWithNullScopedProxyMode() {
new AnnotationScopeMetadataResolver(null);
@@ -94,4 +109,17 @@ public final class AnnotationScopeMetadataResolverTests {
private static final class AnnotatedWithScopedProxy {
}
@CustomRequestScope
private static final class AnnotatedWithCustomRequestScope {
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Scope("request")
public @interface CustomRequestScope {
}
}