initial JSR-330 injection support
This commit is contained in:
parent
429d78b902
commit
e1a3e44485
|
|
@ -8,6 +8,7 @@
|
|||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-sources-1.1.1.jar"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.core"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.el/com.springsource.javax.el/1.0.0/com.springsource.javax.el-1.0.0.jar" sourcepath="/IVY_CACHE/javax.el/com.springsource.javax.el/1.0.0/com.springsource.javax.el-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.inject/com.springsource.javax.inject/0.9.0.PFD/com.springsource.javax.inject-0.9.0.PFD.jar" sourcepath="/IVY_CACHE/javax.inject/com.springsource.javax.inject/0.9.0.PFD/com.springsource.javax.inject-sources-0.9.0.PFD.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.2.0/com.springsource.net.sf.cglib-2.2.0.jar" sourcepath="/IVY_CACHE/net.sourceforge.cglib/com.springsource.net.sf.cglib/2.1.3/com.springsource.net.sf.cglib-sources-2.1.3.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-1.2.15.jar" sourcepath="/IVY_CACHE/org.apache.log4j/com.springsource.org.apache.log4j/1.2.15/com.springsource.org.apache.log4j-sources-1.2.15.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.6.0.jar"/>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
<orderEntry type="library" name="Commons Logging" level="project" />
|
||||
<orderEntry type="library" name="EasyMock" level="project" />
|
||||
<orderEntry type="library" name="javax.el" level="project" />
|
||||
<orderEntry type="library" name="javax.inject" level="project" />
|
||||
<orderEntry type="library" name="JUnit" level="project" />
|
||||
<orderEntry type="library" name="Log4j" level="project" />
|
||||
</component>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
<dependencies>
|
||||
<dependency org="javax.el" name="com.springsource.javax.el" rev="2.1.0" conf="provided->compile"/>
|
||||
<dependency org="javax.inject" name="com.springsource.javax.inject" rev="0.9.0.PFD" conf="provided->compile"/>
|
||||
<dependency org="net.sourceforge.cglib" name="com.springsource.net.sf.cglib" rev="2.2.0" conf="optional, bytecode-proxy->compile"/>
|
||||
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.logging" rev="1.1.1" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.core" rev="latest.integration" conf="compile->compile"/>
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ import org.springframework.util.ReflectionUtils;
|
|||
* a special case of such a general config method. Such config methods
|
||||
* do not have to be public.
|
||||
*
|
||||
* <p>Also supports JSR-330's {@link javax.inject.Inject} annotation, if available.
|
||||
*
|
||||
* <p>Note: A default AutowiredAnnotationBeanPostProcessor will be registered
|
||||
* by the "context:annotation-config" and "context:component-scan" XML tags.
|
||||
* Remove or turn off the default annotation configuration there if you intend
|
||||
|
|
@ -100,8 +102,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
|||
|
||||
protected final Log logger = LogFactory.getLog(AutowiredAnnotationBeanPostProcessor.class);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class<? extends Annotation>[] autowiredAnnotationTypes = new Class[] {Autowired.class, Value.class};
|
||||
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes =
|
||||
new LinkedHashSet<Class<? extends Annotation>>();
|
||||
|
||||
private String requiredParameterName = "required";
|
||||
|
||||
|
|
@ -119,20 +121,24 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
|||
|
||||
|
||||
/**
|
||||
* Set the 'autowired' annotation types, 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, as well as {@link Value} and raw
|
||||
* use of the {@link Qualifier} annotation.
|
||||
* <p>This setter property exists so that developers can provide their own
|
||||
* (non-Spring-specific) annotation types to indicate that a member is
|
||||
* supposed to be autowired.
|
||||
* Create a new AutowiredAnnotationBeanPostProcessor
|
||||
* for Spring's standard {@link Autowired} annotation.
|
||||
* <p>Also supports JSR-330's {@link javax.inject.Inject} annotation, if available.
|
||||
*/
|
||||
public void setAutowiredAnnotationTypes(Class<? extends Annotation>[] autowiredAnnotationTypes) {
|
||||
Assert.notEmpty(autowiredAnnotationTypes, "'autowiredAnnotationTypes' must not be empty");
|
||||
this.autowiredAnnotationTypes = autowiredAnnotationTypes;
|
||||
@SuppressWarnings("unchecked")
|
||||
public AutowiredAnnotationBeanPostProcessor() {
|
||||
this.autowiredAnnotationTypes.add(Autowired.class);
|
||||
this.autowiredAnnotationTypes.add(Value.class);
|
||||
ClassLoader cl = AutowiredAnnotationBeanPostProcessor.class.getClassLoader();
|
||||
try {
|
||||
this.autowiredAnnotationTypes.add((Class<? extends Annotation>) cl.loadClass("javax.inject.Inject"));
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// JSR-330 API not available - simply skip.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the 'autowired' annotation type, to be used on constructors, fields,
|
||||
* setter methods and arbitrary config methods.
|
||||
|
|
@ -142,10 +148,26 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
|||
* (non-Spring-specific) annotation type to indicate that a member is
|
||||
* supposed to be autowired.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setAutowiredAnnotationType(Class<? extends Annotation> autowiredAnnotationType) {
|
||||
Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null");
|
||||
this.autowiredAnnotationTypes = new Class[] {autowiredAnnotationType};
|
||||
this.autowiredAnnotationTypes.clear();
|
||||
this.autowiredAnnotationTypes.add(autowiredAnnotationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'autowired' annotation types, 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, as well as {@link Value} and raw
|
||||
* use of the {@link Qualifier} annotation.
|
||||
* <p>This setter property exists so that developers can provide their own
|
||||
* (non-Spring-specific) annotation types to indicate that a member is
|
||||
* supposed to be autowired.
|
||||
*/
|
||||
public void setAutowiredAnnotationTypes(Set<Class<? extends Annotation>> autowiredAnnotationTypes) {
|
||||
Assert.notEmpty(autowiredAnnotationTypes, "'autowiredAnnotationTypes' must not be empty");
|
||||
this.autowiredAnnotationTypes.clear();
|
||||
this.autowiredAnnotationTypes.addAll(autowiredAnnotationTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ package org.springframework.beans.factory.annotation;
|
|||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
|
@ -38,9 +38,11 @@ import org.springframework.util.ClassUtils;
|
|||
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.
|
||||
* {@link AutowireCandidateResolver} implementation that matches bean definition qualifiers
|
||||
* against {@link Qualifier qualifier annotations} on the field or parameter to be autowired.
|
||||
* Also supports suggested expression values through a {@link Value value} annotation.
|
||||
*
|
||||
* <p>Also supports JSR-330's {@link javax.inject.Qualifier} annotation, if available.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
|
|
@ -51,7 +53,7 @@ import org.springframework.util.ObjectUtils;
|
|||
*/
|
||||
public class QualifierAnnotationAutowireCandidateResolver implements AutowireCandidateResolver, BeanFactoryAware {
|
||||
|
||||
private final Set<Class<? extends Annotation>> qualifierTypes;
|
||||
private final Set<Class<? extends Annotation>> qualifierTypes = new LinkedHashSet<Class<? extends Annotation>>();
|
||||
|
||||
private Class<? extends Annotation> valueAnnotationType = Value.class;
|
||||
|
||||
|
|
@ -61,10 +63,18 @@ public class QualifierAnnotationAutowireCandidateResolver implements AutowireCan
|
|||
/**
|
||||
* Create a new QualifierAnnotationAutowireCandidateResolver
|
||||
* for Spring's standard {@link Qualifier} annotation.
|
||||
* <p>Also supports JSR-330's {@link javax.inject.Qualifier} annotation, if available.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public QualifierAnnotationAutowireCandidateResolver() {
|
||||
this.qualifierTypes = new HashSet<Class<? extends Annotation>>(1);
|
||||
this.qualifierTypes.add(Qualifier.class);
|
||||
ClassLoader cl = QualifierAnnotationAutowireCandidateResolver.class.getClassLoader();
|
||||
try {
|
||||
this.qualifierTypes.add((Class<? extends Annotation>) cl.loadClass("javax.inject.Qualifier"));
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// JSR-330 API not available - simply skip.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -74,7 +84,6 @@ public class QualifierAnnotationAutowireCandidateResolver implements AutowireCan
|
|||
*/
|
||||
public QualifierAnnotationAutowireCandidateResolver(Class<? extends Annotation> qualifierType) {
|
||||
Assert.notNull(qualifierType, "'qualifierType' must not be null");
|
||||
this.qualifierTypes = new HashSet<Class<? extends Annotation>>(1);
|
||||
this.qualifierTypes.add(qualifierType);
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +94,7 @@ public class QualifierAnnotationAutowireCandidateResolver implements AutowireCan
|
|||
*/
|
||||
public QualifierAnnotationAutowireCandidateResolver(Set<Class<? extends Annotation>> qualifierTypes) {
|
||||
Assert.notNull(qualifierTypes, "'qualifierTypes' must not be null");
|
||||
this.qualifierTypes = new HashSet<Class<? extends Annotation>>(qualifierTypes);
|
||||
this.qualifierTypes.addAll(qualifierTypes);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -43,6 +43,7 @@ public interface AutowireCandidateResolver {
|
|||
* @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
|
||||
* @since 3.0
|
||||
*/
|
||||
Object getSuggestedValue(DependencyDescriptor descriptor);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import javax.inject.Provider;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
|
|
@ -642,9 +643,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
|
||||
|
||||
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
|
||||
if (ObjectFactory.class.equals(descriptor.getDependencyType())) {
|
||||
if (descriptor.getDependencyType().equals(ObjectFactory.class)) {
|
||||
return new DependencyObjectFactory(descriptor, beanName);
|
||||
}
|
||||
else if (descriptor.getDependencyType().getName().equals("javax.inject.Provider")) {
|
||||
return new DependencyProviderFactory().createDependencyProvider(descriptor, beanName);
|
||||
}
|
||||
else {
|
||||
return doResolveDependency(descriptor, descriptor.getDependencyType(), beanName, autowiredBeanNames, typeConverter);
|
||||
}
|
||||
|
|
@ -961,4 +965,30 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializable ObjectFactory for lazy resolution of a dependency.
|
||||
*/
|
||||
private class DependencyProvider extends DependencyObjectFactory implements Provider {
|
||||
|
||||
public DependencyProvider(DependencyDescriptor descriptor, String beanName) {
|
||||
super(descriptor, beanName);
|
||||
}
|
||||
|
||||
public Object get() throws BeansException {
|
||||
return getObject();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Separate inner class for avoiding a hard dependency on the <code>javax.inject</code> API.
|
||||
*/
|
||||
private class DependencyProviderFactory {
|
||||
|
||||
public Object createDependencyProvider(DependencyDescriptor descriptor, String beanName) {
|
||||
return new DependencyProvider(descriptor, beanName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -573,6 +573,7 @@ public final class AutowiredAnnotationBeanPostProcessorTests {
|
|||
@Test
|
||||
public void testObjectFactoryQualifierInjection() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
|
|
@ -580,6 +581,7 @@ public final class AutowiredAnnotationBeanPostProcessorTests {
|
|||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "testBean"));
|
||||
bf.registerBeanDefinition("testBean", bd);
|
||||
bf.registerBeanDefinition("testBean2", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
ObjectFactoryQualifierInjectionBean bean = (ObjectFactoryQualifierInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("testBean"), bean.getTestBean());
|
||||
|
|
@ -1282,7 +1284,7 @@ public final class AutowiredAnnotationBeanPostProcessorTests {
|
|||
public static class ObjectFactoryQualifierInjectionBean {
|
||||
|
||||
@Autowired
|
||||
//@Qualifier("testBean")
|
||||
@Qualifier("testBean")
|
||||
private ObjectFactory<?> testBeanFactory;
|
||||
|
||||
public TestBean getTestBean() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,867 @@
|
|||
/*
|
||||
* 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.annotation;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.IndexedTestBean;
|
||||
import test.beans.NestedTestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor}
|
||||
* processing the JSR-303 {@link javax.inject.Inject} annotation.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class InjectAnnotationBeanPostProcessorTests {
|
||||
|
||||
@Test
|
||||
public void testIncompleteBeanDefinition() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("testBean", new GenericBeanDefinition());
|
||||
try {
|
||||
bf.getBean("testBean");
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
assertTrue(ex.getRootCause() instanceof IllegalStateException);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceInjection() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
RootBeanDefinition bd = new RootBeanDefinition(ResourceInjectionBean.class);
|
||||
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
bf.registerBeanDefinition("annotatedBean", bd);
|
||||
TestBean tb = new TestBean();
|
||||
bf.registerSingleton("testBean", tb);
|
||||
|
||||
ResourceInjectionBean bean = (ResourceInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(tb, bean.getTestBean());
|
||||
assertSame(tb, bean.getTestBean2());
|
||||
|
||||
bean = (ResourceInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(tb, bean.getTestBean());
|
||||
assertSame(tb, bean.getTestBean2());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtendedResourceInjection() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerResolvableDependency(BeanFactory.class, bf);
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TypedExtendedResourceInjectionBean.class);
|
||||
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
bf.registerBeanDefinition("annotatedBean", bd);
|
||||
TestBean tb = new TestBean();
|
||||
bf.registerSingleton("testBean", tb);
|
||||
NestedTestBean ntb = new NestedTestBean();
|
||||
bf.registerSingleton("nestedTestBean", ntb);
|
||||
|
||||
TypedExtendedResourceInjectionBean bean = (TypedExtendedResourceInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(tb, bean.getTestBean());
|
||||
assertSame(tb, bean.getTestBean2());
|
||||
assertSame(tb, bean.getTestBean3());
|
||||
assertSame(tb, bean.getTestBean4());
|
||||
assertSame(ntb, bean.getNestedTestBean());
|
||||
assertSame(bf, bean.getBeanFactory());
|
||||
|
||||
bean = (TypedExtendedResourceInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(tb, bean.getTestBean());
|
||||
assertSame(tb, bean.getTestBean2());
|
||||
assertSame(tb, bean.getTestBean3());
|
||||
assertSame(tb, bean.getTestBean4());
|
||||
assertSame(ntb, bean.getNestedTestBean());
|
||||
assertSame(bf, bean.getBeanFactory());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtendedResourceInjectionWithOverriding() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerResolvableDependency(BeanFactory.class, bf);
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
RootBeanDefinition annotatedBd = new RootBeanDefinition(TypedExtendedResourceInjectionBean.class);
|
||||
TestBean tb2 = new TestBean();
|
||||
annotatedBd.getPropertyValues().addPropertyValue("testBean2", tb2);
|
||||
bf.registerBeanDefinition("annotatedBean", annotatedBd);
|
||||
TestBean tb = new TestBean();
|
||||
bf.registerSingleton("testBean", tb);
|
||||
NestedTestBean ntb = new NestedTestBean();
|
||||
bf.registerSingleton("nestedTestBean", ntb);
|
||||
|
||||
TypedExtendedResourceInjectionBean bean = (TypedExtendedResourceInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(tb, bean.getTestBean());
|
||||
assertSame(tb2, bean.getTestBean2());
|
||||
assertSame(tb, bean.getTestBean3());
|
||||
assertSame(tb, bean.getTestBean4());
|
||||
assertSame(ntb, bean.getNestedTestBean());
|
||||
assertSame(bf, bean.getBeanFactory());
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtendedResourceInjectionWithAtRequired() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerResolvableDependency(BeanFactory.class, bf);
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.addBeanPostProcessor(new RequiredAnnotationBeanPostProcessor());
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TypedExtendedResourceInjectionBean.class);
|
||||
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
bf.registerBeanDefinition("annotatedBean", bd);
|
||||
TestBean tb = new TestBean();
|
||||
bf.registerSingleton("testBean", tb);
|
||||
NestedTestBean ntb = new NestedTestBean();
|
||||
bf.registerSingleton("nestedTestBean", ntb);
|
||||
|
||||
TypedExtendedResourceInjectionBean bean = (TypedExtendedResourceInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(tb, bean.getTestBean());
|
||||
assertSame(tb, bean.getTestBean2());
|
||||
assertSame(tb, bean.getTestBean3());
|
||||
assertSame(tb, bean.getTestBean4());
|
||||
assertSame(ntb, bean.getNestedTestBean());
|
||||
assertSame(bf, bean.getBeanFactory());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorResourceInjection() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerResolvableDependency(BeanFactory.class, bf);
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
RootBeanDefinition bd = new RootBeanDefinition(ConstructorResourceInjectionBean.class);
|
||||
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
bf.registerBeanDefinition("annotatedBean", bd);
|
||||
TestBean tb = new TestBean();
|
||||
bf.registerSingleton("testBean", tb);
|
||||
NestedTestBean ntb = new NestedTestBean();
|
||||
bf.registerSingleton("nestedTestBean", ntb);
|
||||
|
||||
ConstructorResourceInjectionBean bean = (ConstructorResourceInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(tb, bean.getTestBean());
|
||||
assertSame(tb, bean.getTestBean2());
|
||||
assertSame(tb, bean.getTestBean3());
|
||||
assertSame(tb, bean.getTestBean4());
|
||||
assertSame(ntb, bean.getNestedTestBean());
|
||||
assertSame(bf, bean.getBeanFactory());
|
||||
|
||||
bean = (ConstructorResourceInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(tb, bean.getTestBean());
|
||||
assertSame(tb, bean.getTestBean2());
|
||||
assertSame(tb, bean.getTestBean3());
|
||||
assertSame(tb, bean.getTestBean4());
|
||||
assertSame(ntb, bean.getNestedTestBean());
|
||||
assertSame(bf, bean.getBeanFactory());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorResourceInjectionWithMultipleCandidatesAsCollection() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(
|
||||
ConstructorsCollectionResourceInjectionBean.class));
|
||||
TestBean tb = new TestBean();
|
||||
bf.registerSingleton("testBean", tb);
|
||||
NestedTestBean ntb1 = new NestedTestBean();
|
||||
bf.registerSingleton("nestedTestBean1", ntb1);
|
||||
NestedTestBean ntb2 = new NestedTestBean();
|
||||
bf.registerSingleton("nestedTestBean2", ntb2);
|
||||
|
||||
ConstructorsCollectionResourceInjectionBean bean = (ConstructorsCollectionResourceInjectionBean) bf.getBean("annotatedBean");
|
||||
assertNull(bean.getTestBean3());
|
||||
assertSame(tb, bean.getTestBean4());
|
||||
assertEquals(2, bean.getNestedTestBeans().size());
|
||||
assertSame(ntb1, bean.getNestedTestBeans().get(0));
|
||||
assertSame(ntb2, bean.getNestedTestBeans().get(1));
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorResourceInjectionWithMultipleCandidatesAndFallback() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ConstructorsResourceInjectionBean.class));
|
||||
TestBean tb = new TestBean();
|
||||
bf.registerSingleton("testBean", tb);
|
||||
|
||||
ConstructorsResourceInjectionBean bean = (ConstructorsResourceInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(tb, bean.getTestBean3());
|
||||
assertNull(bean.getTestBean4());
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorInjectionWithMap() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
RootBeanDefinition bd = new RootBeanDefinition(MapConstructorInjectionBean.class);
|
||||
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
bf.registerBeanDefinition("annotatedBean", bd);
|
||||
TestBean tb1 = new TestBean();
|
||||
TestBean tb2 = new TestBean();
|
||||
bf.registerSingleton("testBean1", tb1);
|
||||
bf.registerSingleton("testBean2", tb1);
|
||||
|
||||
MapConstructorInjectionBean bean = (MapConstructorInjectionBean) bf.getBean("annotatedBean");
|
||||
assertEquals(2, bean.getTestBeanMap().size());
|
||||
assertTrue(bean.getTestBeanMap().keySet().contains("testBean1"));
|
||||
assertTrue(bean.getTestBeanMap().keySet().contains("testBean2"));
|
||||
assertTrue(bean.getTestBeanMap().values().contains(tb1));
|
||||
assertTrue(bean.getTestBeanMap().values().contains(tb2));
|
||||
|
||||
bean = (MapConstructorInjectionBean) bf.getBean("annotatedBean");
|
||||
assertEquals(2, bean.getTestBeanMap().size());
|
||||
assertTrue(bean.getTestBeanMap().keySet().contains("testBean1"));
|
||||
assertTrue(bean.getTestBeanMap().keySet().contains("testBean2"));
|
||||
assertTrue(bean.getTestBeanMap().values().contains(tb1));
|
||||
assertTrue(bean.getTestBeanMap().values().contains(tb2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFieldInjectionWithMap() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
RootBeanDefinition bd = new RootBeanDefinition(MapFieldInjectionBean.class);
|
||||
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
bf.registerBeanDefinition("annotatedBean", bd);
|
||||
TestBean tb1 = new TestBean();
|
||||
TestBean tb2 = new TestBean();
|
||||
bf.registerSingleton("testBean1", tb1);
|
||||
bf.registerSingleton("testBean2", tb1);
|
||||
|
||||
MapFieldInjectionBean bean = (MapFieldInjectionBean) bf.getBean("annotatedBean");
|
||||
assertEquals(2, bean.getTestBeanMap().size());
|
||||
assertTrue(bean.getTestBeanMap().keySet().contains("testBean1"));
|
||||
assertTrue(bean.getTestBeanMap().keySet().contains("testBean2"));
|
||||
assertTrue(bean.getTestBeanMap().values().contains(tb1));
|
||||
assertTrue(bean.getTestBeanMap().values().contains(tb2));
|
||||
|
||||
bean = (MapFieldInjectionBean) bf.getBean("annotatedBean");
|
||||
assertEquals(2, bean.getTestBeanMap().size());
|
||||
assertTrue(bean.getTestBeanMap().keySet().contains("testBean1"));
|
||||
assertTrue(bean.getTestBeanMap().keySet().contains("testBean2"));
|
||||
assertTrue(bean.getTestBeanMap().values().contains(tb1));
|
||||
assertTrue(bean.getTestBeanMap().values().contains(tb2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMethodInjectionWithMap() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
RootBeanDefinition bd = new RootBeanDefinition(MapMethodInjectionBean.class);
|
||||
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||
bf.registerBeanDefinition("annotatedBean", bd);
|
||||
TestBean tb = new TestBean();
|
||||
bf.registerSingleton("testBean", tb);
|
||||
|
||||
MapMethodInjectionBean bean = (MapMethodInjectionBean) bf.getBean("annotatedBean");
|
||||
assertEquals(1, bean.getTestBeanMap().size());
|
||||
assertTrue(bean.getTestBeanMap().keySet().contains("testBean"));
|
||||
assertTrue(bean.getTestBeanMap().values().contains(tb));
|
||||
assertSame(tb, bean.getTestBean());
|
||||
|
||||
bean = (MapMethodInjectionBean) bf.getBean("annotatedBean");
|
||||
assertEquals(1, bean.getTestBeanMap().size());
|
||||
assertTrue(bean.getTestBeanMap().keySet().contains("testBean"));
|
||||
assertTrue(bean.getTestBeanMap().values().contains(tb));
|
||||
assertSame(tb, bean.getTestBean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMethodInjectionWithMapAndMultipleMatches() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(MapMethodInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean1", new RootBeanDefinition(TestBean.class));
|
||||
bf.registerBeanDefinition("testBean2", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
try {
|
||||
bf.getBean("annotatedBean");
|
||||
fail("should have failed, more than one bean of type");
|
||||
}
|
||||
catch (BeanCreationException e) {
|
||||
// expected
|
||||
}
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMethodInjectionWithMapAndMultipleMatchesButOnlyOneAutowireCandidate() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(MapMethodInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean1", new RootBeanDefinition(TestBean.class));
|
||||
RootBeanDefinition rbd2 = new RootBeanDefinition(TestBean.class);
|
||||
rbd2.setAutowireCandidate(false);
|
||||
bf.registerBeanDefinition("testBean2", rbd2);
|
||||
|
||||
MapMethodInjectionBean bean = (MapMethodInjectionBean) bf.getBean("annotatedBean");
|
||||
TestBean tb = (TestBean) bf.getBean("testBean1");
|
||||
assertEquals(1, bean.getTestBeanMap().size());
|
||||
assertTrue(bean.getTestBeanMap().keySet().contains("testBean1"));
|
||||
assertTrue(bean.getTestBeanMap().values().contains(tb));
|
||||
assertSame(tb, bean.getTestBean());
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryInjection() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryQualifierInjectionBean.class));
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "testBean"));
|
||||
bf.registerBeanDefinition("testBean", bd);
|
||||
bf.registerBeanDefinition("testBean2", new RootBeanDefinition(TestBean.class));
|
||||
|
||||
ObjectFactoryQualifierInjectionBean bean = (ObjectFactoryQualifierInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("testBean"), bean.getTestBean());
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactoryQualifierInjection() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryQualifierInjectionBean.class));
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "testBean"));
|
||||
bf.registerBeanDefinition("testBean", bd);
|
||||
|
||||
ObjectFactoryQualifierInjectionBean bean = (ObjectFactoryQualifierInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("testBean"), bean.getTestBean());
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectFactorySerialization() throws Exception {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectFactoryInjectionBean.class));
|
||||
bf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class));
|
||||
bf.setSerializationId("test");
|
||||
|
||||
ObjectFactoryInjectionBean bean = (ObjectFactoryInjectionBean) bf.getBean("annotatedBean");
|
||||
assertSame(bf.getBean("testBean"), bean.getTestBean());
|
||||
bean = (ObjectFactoryInjectionBean) SerializationTestUtils.serializeAndDeserialize(bean);
|
||||
assertSame(bf.getBean("testBean"), bean.getTestBean());
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a dependency on a {@link org.springframework.beans.factory.FactoryBean} can be autowired via
|
||||
* {@link org.springframework.beans.factory.annotation.Autowired @Inject}, specifically addressing the JIRA issue
|
||||
* raised in <a
|
||||
* href="http://opensource.atlassian.com/projects/spring/browse/SPR-4040"
|
||||
* target="_blank">SPR-4040</a>.
|
||||
*/
|
||||
@Test
|
||||
public void testBeanAutowiredWithFactoryBean() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("factoryBeanDependentBean", new RootBeanDefinition(FactoryBeanDependentBean.class));
|
||||
bf.registerSingleton("stringFactoryBean", new StringFactoryBean());
|
||||
|
||||
final StringFactoryBean factoryBean = (StringFactoryBean) bf.getBean("&stringFactoryBean");
|
||||
final FactoryBeanDependentBean bean = (FactoryBeanDependentBean) bf.getBean("factoryBeanDependentBean");
|
||||
|
||||
assertNotNull("The singleton StringFactoryBean should have been registered.", factoryBean);
|
||||
assertNotNull("The factoryBeanDependentBean should have been registered.", bean);
|
||||
assertEquals("The FactoryBeanDependentBean should have been autowired 'by type' with the StringFactoryBean.",
|
||||
factoryBean, bean.getFactoryBean());
|
||||
|
||||
bf.destroySingletons();
|
||||
}
|
||||
|
||||
|
||||
public static class ResourceInjectionBean {
|
||||
|
||||
@Inject
|
||||
private TestBean testBean;
|
||||
|
||||
private TestBean testBean2;
|
||||
|
||||
|
||||
@Inject
|
||||
public void setTestBean2(TestBean testBean2) {
|
||||
if (this.testBean2 != null) {
|
||||
throw new IllegalStateException("Already called");
|
||||
}
|
||||
this.testBean2 = testBean2;
|
||||
}
|
||||
|
||||
public TestBean getTestBean() {
|
||||
return this.testBean;
|
||||
}
|
||||
|
||||
public TestBean getTestBean2() {
|
||||
return this.testBean2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ExtendedResourceInjectionBean<T> extends ResourceInjectionBean {
|
||||
|
||||
@Inject
|
||||
protected ITestBean testBean3;
|
||||
|
||||
private T nestedTestBean;
|
||||
|
||||
private ITestBean testBean4;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
public ExtendedResourceInjectionBean() {
|
||||
}
|
||||
|
||||
@Inject @Required
|
||||
public void setTestBean2(TestBean testBean2) {
|
||||
super.setTestBean2(testBean2);
|
||||
}
|
||||
|
||||
@Inject
|
||||
private void inject(ITestBean testBean4, T nestedTestBean) {
|
||||
this.testBean4 = testBean4;
|
||||
this.nestedTestBean = nestedTestBean;
|
||||
}
|
||||
|
||||
@Inject
|
||||
protected void initBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
public ITestBean getTestBean3() {
|
||||
return this.testBean3;
|
||||
}
|
||||
|
||||
public ITestBean getTestBean4() {
|
||||
return this.testBean4;
|
||||
}
|
||||
|
||||
public T getNestedTestBean() {
|
||||
return this.nestedTestBean;
|
||||
}
|
||||
|
||||
public BeanFactory getBeanFactory() {
|
||||
return this.beanFactory;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class TypedExtendedResourceInjectionBean extends ExtendedResourceInjectionBean<NestedTestBean> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class OptionalResourceInjectionBean extends ResourceInjectionBean {
|
||||
|
||||
@Inject
|
||||
protected ITestBean testBean3;
|
||||
|
||||
private IndexedTestBean indexedTestBean;
|
||||
|
||||
private NestedTestBean[] nestedTestBeans;
|
||||
|
||||
@Inject
|
||||
public NestedTestBean[] nestedTestBeansField;
|
||||
|
||||
private ITestBean testBean4;
|
||||
|
||||
@Inject
|
||||
public void setTestBean2(TestBean testBean2) {
|
||||
super.setTestBean2(testBean2);
|
||||
}
|
||||
|
||||
@Inject
|
||||
private void inject(ITestBean testBean4, NestedTestBean[] nestedTestBeans, IndexedTestBean indexedTestBean) {
|
||||
this.testBean4 = testBean4;
|
||||
this.indexedTestBean = indexedTestBean;
|
||||
this.nestedTestBeans = nestedTestBeans;
|
||||
}
|
||||
|
||||
public ITestBean getTestBean3() {
|
||||
return this.testBean3;
|
||||
}
|
||||
|
||||
public ITestBean getTestBean4() {
|
||||
return this.testBean4;
|
||||
}
|
||||
|
||||
public IndexedTestBean getIndexedTestBean() {
|
||||
return this.indexedTestBean;
|
||||
}
|
||||
|
||||
public NestedTestBean[] getNestedTestBeans() {
|
||||
return this.nestedTestBeans;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class OptionalCollectionResourceInjectionBean extends ResourceInjectionBean {
|
||||
|
||||
@Inject
|
||||
protected ITestBean testBean3;
|
||||
|
||||
private IndexedTestBean indexedTestBean;
|
||||
|
||||
private List<NestedTestBean> nestedTestBeans;
|
||||
|
||||
public List<NestedTestBean> nestedTestBeansSetter;
|
||||
|
||||
@Inject
|
||||
public List<NestedTestBean> nestedTestBeansField;
|
||||
|
||||
private ITestBean testBean4;
|
||||
|
||||
@Inject
|
||||
public void setTestBean2(TestBean testBean2) {
|
||||
super.setTestBean2(testBean2);
|
||||
}
|
||||
|
||||
@Inject
|
||||
private void inject(ITestBean testBean4, List<NestedTestBean> nestedTestBeans, IndexedTestBean indexedTestBean) {
|
||||
this.testBean4 = testBean4;
|
||||
this.indexedTestBean = indexedTestBean;
|
||||
this.nestedTestBeans = nestedTestBeans;
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setNestedTestBeans(List<NestedTestBean> nestedTestBeans) {
|
||||
this.nestedTestBeansSetter = nestedTestBeans;
|
||||
}
|
||||
|
||||
public ITestBean getTestBean3() {
|
||||
return this.testBean3;
|
||||
}
|
||||
|
||||
public ITestBean getTestBean4() {
|
||||
return this.testBean4;
|
||||
}
|
||||
|
||||
public IndexedTestBean getIndexedTestBean() {
|
||||
return this.indexedTestBean;
|
||||
}
|
||||
|
||||
public List<NestedTestBean> getNestedTestBeans() {
|
||||
return this.nestedTestBeans;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ConstructorResourceInjectionBean extends ResourceInjectionBean {
|
||||
|
||||
@Inject
|
||||
protected ITestBean testBean3;
|
||||
|
||||
private ITestBean testBean4;
|
||||
|
||||
private NestedTestBean nestedTestBean;
|
||||
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
|
||||
public ConstructorResourceInjectionBean() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public ConstructorResourceInjectionBean(ITestBean testBean3) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Inject
|
||||
public ConstructorResourceInjectionBean(ITestBean testBean4, NestedTestBean nestedTestBean,
|
||||
ConfigurableListableBeanFactory beanFactory) {
|
||||
this.testBean4 = testBean4;
|
||||
this.nestedTestBean = nestedTestBean;
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
public ConstructorResourceInjectionBean(NestedTestBean nestedTestBean) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public ConstructorResourceInjectionBean(ITestBean testBean3, ITestBean testBean4, NestedTestBean nestedTestBean) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setTestBean2(TestBean testBean2) {
|
||||
super.setTestBean2(testBean2);
|
||||
}
|
||||
|
||||
public ITestBean getTestBean3() {
|
||||
return this.testBean3;
|
||||
}
|
||||
|
||||
public ITestBean getTestBean4() {
|
||||
return this.testBean4;
|
||||
}
|
||||
|
||||
public NestedTestBean getNestedTestBean() {
|
||||
return this.nestedTestBean;
|
||||
}
|
||||
|
||||
public ConfigurableListableBeanFactory getBeanFactory() {
|
||||
return this.beanFactory;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ConstructorsResourceInjectionBean {
|
||||
|
||||
protected ITestBean testBean3;
|
||||
|
||||
private ITestBean testBean4;
|
||||
|
||||
private NestedTestBean[] nestedTestBeans;
|
||||
|
||||
public ConstructorsResourceInjectionBean() {
|
||||
}
|
||||
|
||||
@Inject
|
||||
public ConstructorsResourceInjectionBean(ITestBean testBean3) {
|
||||
this.testBean3 = testBean3;
|
||||
}
|
||||
|
||||
public ConstructorsResourceInjectionBean(ITestBean testBean4, NestedTestBean[] nestedTestBeans) {
|
||||
this.testBean4 = testBean4;
|
||||
this.nestedTestBeans = nestedTestBeans;
|
||||
}
|
||||
|
||||
public ConstructorsResourceInjectionBean(NestedTestBean nestedTestBean) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public ConstructorsResourceInjectionBean(ITestBean testBean3, ITestBean testBean4, NestedTestBean nestedTestBean) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public ITestBean getTestBean3() {
|
||||
return this.testBean3;
|
||||
}
|
||||
|
||||
public ITestBean getTestBean4() {
|
||||
return this.testBean4;
|
||||
}
|
||||
|
||||
public NestedTestBean[] getNestedTestBeans() {
|
||||
return this.nestedTestBeans;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ConstructorsCollectionResourceInjectionBean {
|
||||
|
||||
protected ITestBean testBean3;
|
||||
|
||||
private ITestBean testBean4;
|
||||
|
||||
private List<NestedTestBean> nestedTestBeans;
|
||||
|
||||
public ConstructorsCollectionResourceInjectionBean() {
|
||||
}
|
||||
|
||||
public ConstructorsCollectionResourceInjectionBean(ITestBean testBean3) {
|
||||
this.testBean3 = testBean3;
|
||||
}
|
||||
|
||||
@Inject
|
||||
public ConstructorsCollectionResourceInjectionBean(ITestBean testBean4, List<NestedTestBean> nestedTestBeans) {
|
||||
this.testBean4 = testBean4;
|
||||
this.nestedTestBeans = nestedTestBeans;
|
||||
}
|
||||
|
||||
public ConstructorsCollectionResourceInjectionBean(NestedTestBean nestedTestBean) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public ConstructorsCollectionResourceInjectionBean(ITestBean testBean3, ITestBean testBean4,
|
||||
NestedTestBean nestedTestBean) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public ITestBean getTestBean3() {
|
||||
return this.testBean3;
|
||||
}
|
||||
|
||||
public ITestBean getTestBean4() {
|
||||
return this.testBean4;
|
||||
}
|
||||
|
||||
public List<NestedTestBean> getNestedTestBeans() {
|
||||
return this.nestedTestBeans;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class MapConstructorInjectionBean {
|
||||
|
||||
private Map<String, TestBean> testBeanMap;
|
||||
|
||||
@Inject
|
||||
public MapConstructorInjectionBean(Map<String, TestBean> testBeanMap) {
|
||||
this.testBeanMap = testBeanMap;
|
||||
}
|
||||
|
||||
public Map<String, TestBean> getTestBeanMap() {
|
||||
return this.testBeanMap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class MapFieldInjectionBean {
|
||||
|
||||
@Inject
|
||||
private Map<String, TestBean> testBeanMap;
|
||||
|
||||
|
||||
public Map<String, TestBean> getTestBeanMap() {
|
||||
return this.testBeanMap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class MapMethodInjectionBean {
|
||||
|
||||
private TestBean testBean;
|
||||
|
||||
private Map<String, TestBean> testBeanMap;
|
||||
|
||||
@Inject
|
||||
public void setTestBeanMap(TestBean testBean, Map<String, TestBean> testBeanMap) {
|
||||
this.testBean = testBean;
|
||||
this.testBeanMap = testBeanMap;
|
||||
}
|
||||
|
||||
public TestBean getTestBean() {
|
||||
return this.testBean;
|
||||
}
|
||||
|
||||
public Map<String, TestBean> getTestBeanMap() {
|
||||
return this.testBeanMap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ObjectFactoryInjectionBean implements Serializable {
|
||||
|
||||
@Inject
|
||||
private Provider<TestBean> testBeanFactory;
|
||||
|
||||
public TestBean getTestBean() {
|
||||
return this.testBeanFactory.get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ObjectFactoryQualifierInjectionBean {
|
||||
|
||||
@Inject
|
||||
@Named("testBean")
|
||||
private Provider<?> testBeanFactory;
|
||||
|
||||
public TestBean getTestBean() {
|
||||
return (TestBean) this.testBeanFactory.get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bean with a dependency on a {@link org.springframework.beans.factory.FactoryBean}.
|
||||
*/
|
||||
private static class FactoryBeanDependentBean {
|
||||
|
||||
@Inject
|
||||
private FactoryBean<?> factoryBean;
|
||||
|
||||
public final FactoryBean<?> getFactoryBean() {
|
||||
return this.factoryBean;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class StringFactoryBean implements FactoryBean<String> {
|
||||
|
||||
public String getObject() throws Exception {
|
||||
return "";
|
||||
}
|
||||
|
||||
public Class<String> getObjectType() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ Bundle-Vendor: SpringSource
|
|||
Bundle-ManifestVersion: 2
|
||||
Import-Template:
|
||||
javax.el.*;version="[1.0.0, 2.0.0)";resolution:=optional,
|
||||
javax.inject.*;version="[0.9.0, 2.0.0)";resolution:=optional,
|
||||
javax.xml.*;version="0";resolution:=optional,
|
||||
net.sf.cglib.*;version="[2.1.3, 2.2.0)";resolution:=optional,
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
<classpathentry kind="var" path="IVY_CACHE/com.sun.enterprise/com.springsource.com.sun.enterprise.loader/1.0.0/com.springsource.com.sun.enterprise.loader-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/com.oracle.oc4j/com.springsource.oracle.classloader/10.1.3.1/com.springsource.oracle.classloader-10.1.3.1.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.ejb/com.springsource.javax.ejb/3.0.0/com.springsource.javax.ejb-3.0.0.jar" sourcepath="/IVY_CACHE/javax.ejb/com.springsource.javax.ejb/3.0.0/com.springsource.javax.ejb-sources-3.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.inject/com.springsource.javax.inject/0.9.0.PFD/com.springsource.javax.inject-0.9.0.PFD.jar" sourcepath="/IVY_CACHE/javax.inject/com.springsource.javax.inject/0.9.0.PFD/com.springsource.javax.inject-sources-0.9.0.PFD.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.jms/com.springsource.javax.jms/1.1.0/com.springsource.javax.jms-1.1.0.jar" sourcepath="/IVY_CACHE/javax.jms/com.springsource.javax.jms/1.1.0/com.springsource.javax.jms-sources-1.1.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.persistence/com.springsource.javax.persistence/1.0.0/com.springsource.javax.persistence-1.0.0.jar" sourcepath="/IVY_CACHE/javax.persistence/com.springsource.javax.persistence/1.0.0/com.springsource.javax.persistence-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.transaction/com.springsource.javax.transaction/1.1.0/com.springsource.javax.transaction-1.1.0.jar" sourcepath="/IVY_CACHE/javax.transaction/com.springsource.javax.transaction/1.1.0/com.springsource.javax.transaction-sources-1.1.0.jar"/>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
<orderEntry type="library" name="Commons Logging" level="project" />
|
||||
<orderEntry type="library" name="Commons Pool" level="project" />
|
||||
<orderEntry type="library" name="EasyMock" level="project" />
|
||||
<orderEntry type="library" name="javax.inject" level="project" />
|
||||
<orderEntry type="library" name="JUnit" level="project" />
|
||||
<orderEntry type="library" name="Log4j" level="project" />
|
||||
<orderEntry type="library" name="SLF4j" level="project" />
|
||||
|
|
|
|||
|
|
@ -35,9 +35,10 @@
|
|||
<dependency org="edu.emory.mathcs.backport" name="com.springsource.edu.emory.mathcs.backport" rev="3.0.0" conf="optional, backport-util-concurrent->compile"/>
|
||||
<dependency org="javax.annotation" name="com.springsource.javax.annotation" rev="1.0.0" conf="provided, ejb->compile"/>
|
||||
<dependency org="javax.ejb" name="com.springsource.javax.ejb" rev="3.0.0" conf="provided, ejb->compile"/>
|
||||
<dependency org="javax.inject" name="com.springsource.javax.inject" rev="0.9.0.PFD" conf="provided->compile"/>
|
||||
<dependency org="javax.jms" name="com.springsource.javax.jms" rev="1.1.0" conf="provided, jms->compile"/>
|
||||
<dependency org="javax.persistence" name="com.springsource.javax.persistence" rev="1.0.0" conf="provided, jpa->compile"/>
|
||||
<dependency org="javax.validation" name="com.springsource.javax.validation" rev="1.0.0.CR3"/>
|
||||
<dependency org="javax.validation" name="com.springsource.javax.validation" rev="1.0.0.CR3" conf="provided->compile"/>
|
||||
<dependency org="javax.xml.ws" name="com.springsource.javax.xml.ws" rev="2.1.1" conf="provided, ws->compile"/>
|
||||
<dependency org="net.sourceforge.cglib" name="com.springsource.net.sf.cglib" rev="2.2.0" conf="optional, bytecode-proxy->compile"/>
|
||||
<dependency org="org.aopalliance" name="com.springsource.org.aopalliance" rev="1.0.0" conf="compile->compile"/>
|
||||
|
|
@ -45,7 +46,6 @@
|
|||
<dependency org="org.aspectj" name="com.springsource.org.aspectj.weaver" rev="1.6.5.RELEASE" conf="optional, aspectj->compile"/>
|
||||
<dependency org="org.beanshell" name="com.springsource.bsh" rev="2.0.0.b4" conf="optional, beanshell->compile"/>
|
||||
<dependency org="org.codehaus.groovy" name="com.springsource.org.codehaus.groovy" rev="1.6.3" conf="optional, groovy->compile"/>
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.validator" rev="4.0.0.Beta2"/>
|
||||
<dependency org="org.jruby" name="com.springsource.org.jruby" rev="1.2.0" conf="optional, jruby->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.asm" rev="latest.integration" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.aop" rev="latest.integration" conf="compile->compile"/>
|
||||
|
|
@ -60,6 +60,7 @@
|
|||
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.dbcp" rev="1.2.2.osgi" conf="test->runtime"/>
|
||||
<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="test->runtime"/>
|
||||
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.5.1" conf="test->compile"/>
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.validator" rev="4.0.0.Beta2" conf="test->runtime"/>
|
||||
<dependency org="org.junit" name="com.springsource.org.junit" rev="4.7.0" conf="test->runtime"/>
|
||||
<dependency org="org.slf4j" name="com.springsource.slf4j.jcl" rev="1.5.3" conf="test->runtime"/>
|
||||
</dependencies>
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ Import-Template:
|
|||
groovy.*;version="[1.5.0, 2.0.0)";resolution:=optional,
|
||||
javax.annotation.*;version="0";resolution:=optional,
|
||||
javax.ejb.*;version="[2.1.0, 4.0.0)";resolution:=optional,
|
||||
javax.inject.*;version="[0.9.0, 2.0.0)";resolution:=optional,
|
||||
javax.interceptor.*;version="[3.0.0, 4.0.0)";resolution:=optional,
|
||||
javax.jms.*;version="[1.1.0, 2.0.0)";resolution:=optional,
|
||||
javax.management.*;version="0";resolution:=optional,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
<classpathentry kind="var" path="IVY_CACHE/edu.emory.mathcs.backport/com.springsource.edu.emory.mathcs.backport/3.0.0/com.springsource.edu.emory.mathcs.backport-3.0.0.jar" sourcepath="/IVY_CACHE/edu.emory.mathcs.backport/com.springsource.edu.emory.mathcs.backport/3.0.0/com.springsource.edu.emory.mathcs.backport-sources-3.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.el/com.springsource.javax.el/1.0.0/com.springsource.javax.el-1.0.0.jar" sourcepath="/IVY_CACHE/javax.el/com.springsource.javax.el/1.0.0/com.springsource.javax.el-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.faces/com.springsource.javax.faces/1.2.0.08/com.springsource.javax.faces-1.2.0.08.jar" sourcepath="/IVY_CACHE/javax.faces/com.springsource.javax.faces/1.2.0.08/com.springsource.javax.faces-sources-1.2.0.08.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.inject/com.springsource.javax.inject/0.9.0.PFD/com.springsource.javax.inject-0.9.0.PFD.jar" sourcepath="/IVY_CACHE/javax.inject/com.springsource.javax.inject/0.9.0.PFD/com.springsource.javax.inject-sources-0.9.0.PFD.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.jdo/com.springsource.javax.jdo/2.1.0/com.springsource.javax.jdo-2.1.0.jar" sourcepath="/IVY_CACHE/javax.jdo/com.springsource.javax.jdo/2.1.0/com.springsource.javax.jdo-sources-2.1.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.jms/com.springsource.javax.jms/1.1.0/com.springsource.javax.jms-1.1.0.jar" sourcepath="/IVY_CACHE/javax.jms/com.springsource.javax.jms/1.1.0/com.springsource.javax.jms-sources-1.1.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.mail/com.springsource.javax.mail/1.4.0/com.springsource.javax.mail-1.4.0.jar" sourcepath="/IVY_CACHE/javax.mail/com.springsource.javax.mail/1.4.0/com.springsource.javax.mail-sources-1.4.0.jar"/>
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
<orderEntry type="library" name="Commons Logging" level="project" />
|
||||
<orderEntry type="library" name="EasyMock" level="project" />
|
||||
<orderEntry type="library" name="javax.el" level="project" />
|
||||
<orderEntry type="library" name="javax.inject" level="project" />
|
||||
<orderEntry type="library" name="JUnit" level="project" />
|
||||
<orderEntry type="library" name="Log4j" level="project" />
|
||||
<orderEntry type="module-library">
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
<dependency org="javax.ejb" name="com.springsource.javax.ejb" rev="3.0.0" conf="test->compile"/>
|
||||
<dependency org="javax.el" name="com.springsource.javax.el" rev="1.0.0" conf="test->compile"/>
|
||||
<dependency org="javax.faces" name="com.springsource.javax.faces" rev="1.2.0.08" conf="test->compile"/>
|
||||
<dependency org="javax.inject" name="com.springsource.javax.inject" rev="0.9.0.PFD" conf="test->compile"/>
|
||||
<dependency org="javax.jdo" name="com.springsource.javax.jdo" rev="2.1.0" conf="test->compile"/>
|
||||
<dependency org="javax.jms" name="com.springsource.javax.jms" rev="1.1.0" conf="test->compile"/>
|
||||
<dependency org="javax.mail" name="com.springsource.javax.mail" rev="1.4.0" conf="test->compile"/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,393 @@
|
|||
/*
|
||||
* 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.context.annotation.jsr330;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.junit.After;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
|
||||
import org.springframework.context.annotation.ScopeMetadata;
|
||||
import org.springframework.context.annotation.ScopeMetadataResolver;
|
||||
import org.springframework.context.annotation.ScopedProxyMode;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
|
||||
|
||||
private static final String DEFAULT_NAME = "default";
|
||||
|
||||
private static final String MODIFIED_NAME = "modified";
|
||||
|
||||
private ServletRequestAttributes oldRequestAttributes;
|
||||
|
||||
private ServletRequestAttributes newRequestAttributes;
|
||||
|
||||
private ServletRequestAttributes oldRequestAttributesWithSession;
|
||||
|
||||
private ServletRequestAttributes newRequestAttributesWithSession;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.oldRequestAttributes = new ServletRequestAttributes(new MockHttpServletRequest());
|
||||
this.newRequestAttributes = new ServletRequestAttributes(new MockHttpServletRequest());
|
||||
|
||||
MockHttpServletRequest oldRequestWithSession = new MockHttpServletRequest();
|
||||
oldRequestWithSession.setSession(new MockHttpSession());
|
||||
this.oldRequestAttributesWithSession = new ServletRequestAttributes(oldRequestWithSession);
|
||||
|
||||
MockHttpServletRequest newRequestWithSession = new MockHttpServletRequest();
|
||||
newRequestWithSession.setSession(new MockHttpSession());
|
||||
this.newRequestAttributesWithSession = new ServletRequestAttributes(newRequestWithSession);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
RequestContextHolder.setRequestAttributes(null);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPrototype() {
|
||||
ApplicationContext context = createContext(ScopedProxyMode.NO);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("prototype");
|
||||
assertTrue(context.isPrototype("prototype"));
|
||||
assertFalse(context.isSingleton("prototype"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingletonScopeWithNoProxy() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.NO);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("singleton");
|
||||
assertTrue(context.isSingleton("singleton"));
|
||||
assertFalse(context.isPrototype("singleton"));
|
||||
|
||||
// should not be a proxy
|
||||
assertFalse(AopUtils.isAopProxy(bean));
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// not a proxy so this should not have changed
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
|
||||
// singleton bean, so name should be modified even after lookup
|
||||
ScopedTestBean bean2 = (ScopedTestBean) context.getBean("singleton");
|
||||
assertEquals(MODIFIED_NAME, bean2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingletonScopeIgnoresProxyInterfaces() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.INTERFACES);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("singleton");
|
||||
|
||||
// should not be a proxy
|
||||
assertFalse(AopUtils.isAopProxy(bean));
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// not a proxy so this should not have changed
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
|
||||
// singleton bean, so name should be modified even after lookup
|
||||
ScopedTestBean bean2 = (ScopedTestBean) context.getBean("singleton");
|
||||
assertEquals(MODIFIED_NAME, bean2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingletonScopeIgnoresProxyTargetClass() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.TARGET_CLASS);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("singleton");
|
||||
|
||||
// should not be a proxy
|
||||
assertFalse(AopUtils.isAopProxy(bean));
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// not a proxy so this should not have changed
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
|
||||
// singleton bean, so name should be modified even after lookup
|
||||
ScopedTestBean bean2 = (ScopedTestBean) context.getBean("singleton");
|
||||
assertEquals(MODIFIED_NAME, bean2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestScopeWithNoProxy() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.NO);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("request");
|
||||
|
||||
// should not be a proxy
|
||||
assertFalse(AopUtils.isAopProxy(bean));
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// not a proxy so this should not have changed
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
|
||||
// but a newly retrieved bean should have the default name
|
||||
ScopedTestBean bean2 = (ScopedTestBean) context.getBean("request");
|
||||
assertEquals(DEFAULT_NAME, bean2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestScopeWithProxiedInterfaces() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.INTERFACES);
|
||||
IScopedTestBean bean = (IScopedTestBean) context.getBean("request");
|
||||
|
||||
// should be dynamic proxy, implementing both interfaces
|
||||
assertTrue(AopUtils.isJdkDynamicProxy(bean));
|
||||
assertTrue(bean instanceof AnotherScopeTestInterface);
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// this is a proxy so it should be reset to default
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestScopeWithProxiedTargetClass() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.TARGET_CLASS);
|
||||
IScopedTestBean bean = (IScopedTestBean) context.getBean("request");
|
||||
|
||||
// should be a class-based proxy
|
||||
assertTrue(AopUtils.isCglibProxy(bean));
|
||||
assertTrue(bean instanceof RequestScopedTestBean);
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributes);
|
||||
// this is a proxy so it should be reset to default
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributes);
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionScopeWithNoProxy() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.NO);
|
||||
ScopedTestBean bean = (ScopedTestBean) context.getBean("session");
|
||||
|
||||
// should not be a proxy
|
||||
assertFalse(AopUtils.isAopProxy(bean));
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributesWithSession);
|
||||
// not a proxy so this should not have changed
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
|
||||
// but a newly retrieved bean should have the default name
|
||||
ScopedTestBean bean2 = (ScopedTestBean) context.getBean("session");
|
||||
assertEquals(DEFAULT_NAME, bean2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionScopeWithProxiedInterfaces() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.INTERFACES);
|
||||
IScopedTestBean bean = (IScopedTestBean) context.getBean("session");
|
||||
|
||||
// should be dynamic proxy, implementing both interfaces
|
||||
assertTrue(AopUtils.isJdkDynamicProxy(bean));
|
||||
assertTrue(bean instanceof AnotherScopeTestInterface);
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributesWithSession);
|
||||
// this is a proxy so it should be reset to default
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
IScopedTestBean bean2 = (IScopedTestBean) context.getBean("session");
|
||||
assertEquals(MODIFIED_NAME, bean2.getName());
|
||||
bean2.setName(DEFAULT_NAME);
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionScopeWithProxiedTargetClass() {
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
ApplicationContext context = createContext(ScopedProxyMode.TARGET_CLASS);
|
||||
IScopedTestBean bean = (IScopedTestBean) context.getBean("session");
|
||||
|
||||
// should be a class-based proxy
|
||||
assertTrue(AopUtils.isCglibProxy(bean));
|
||||
assertTrue(bean instanceof ScopedTestBean);
|
||||
assertTrue(bean instanceof SessionScopedTestBean);
|
||||
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
RequestContextHolder.setRequestAttributes(newRequestAttributesWithSession);
|
||||
// this is a proxy so it should be reset to default
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
bean.setName(MODIFIED_NAME);
|
||||
|
||||
IScopedTestBean bean2 = (IScopedTestBean) context.getBean("session");
|
||||
assertEquals(MODIFIED_NAME, bean2.getName());
|
||||
bean2.setName(DEFAULT_NAME);
|
||||
assertEquals(DEFAULT_NAME, bean.getName());
|
||||
|
||||
RequestContextHolder.setRequestAttributes(oldRequestAttributesWithSession);
|
||||
assertEquals(MODIFIED_NAME, bean.getName());
|
||||
}
|
||||
|
||||
|
||||
private ApplicationContext createContext(final ScopedProxyMode scopedProxyMode) {
|
||||
GenericWebApplicationContext context = new GenericWebApplicationContext();
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
|
||||
scanner.setIncludeAnnotationConfig(false);
|
||||
scanner.setScopeMetadataResolver(new ScopeMetadataResolver() {
|
||||
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
|
||||
ScopeMetadata metadata = new ScopeMetadata();
|
||||
if (definition instanceof AnnotatedBeanDefinition) {
|
||||
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
|
||||
for (String type : annDef.getMetadata().getAnnotationTypes()) {
|
||||
if (type.equals(javax.inject.Singleton.class.getName())) {
|
||||
metadata.setScopeName(BeanDefinition.SCOPE_SINGLETON);
|
||||
break;
|
||||
}
|
||||
else if (annDef.getMetadata().getMetaAnnotationTypes(type).contains(javax.inject.Scope.class.getName())) {
|
||||
metadata.setScopeName(type.substring(type.length() - 13, type.length() - 6).toLowerCase());
|
||||
metadata.setScopedProxyMode(scopedProxyMode);
|
||||
break;
|
||||
}
|
||||
else if (type.startsWith("javax.inject")) {
|
||||
metadata.setScopeName(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
});
|
||||
|
||||
// Scan twice in order to find errors in the bean definition compatibility check.
|
||||
scanner.scan(getClass().getPackage().getName());
|
||||
scanner.scan(getClass().getPackage().getName());
|
||||
|
||||
context.registerAlias("classPathBeanDefinitionScannerJsr330ScopeIntegrationTests.SessionScopedTestBean", "session");
|
||||
context.refresh();
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
public static interface IScopedTestBean {
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
}
|
||||
|
||||
|
||||
public static abstract class ScopedTestBean implements IScopedTestBean {
|
||||
|
||||
private String name = DEFAULT_NAME;
|
||||
|
||||
public String getName() { return this.name; }
|
||||
|
||||
public void setName(String name) { this.name = name; }
|
||||
}
|
||||
|
||||
|
||||
@Named("prototype")
|
||||
public static class PrototypeScopedTestBean extends ScopedTestBean {
|
||||
}
|
||||
|
||||
|
||||
@Named("singleton")
|
||||
@Singleton
|
||||
public static class SingletonScopedTestBean extends ScopedTestBean {
|
||||
}
|
||||
|
||||
|
||||
public static interface AnotherScopeTestInterface {
|
||||
}
|
||||
|
||||
|
||||
@RequestScoped
|
||||
@Named("request")
|
||||
public static class RequestScopedTestBean extends ScopedTestBean implements AnotherScopeTestInterface {
|
||||
}
|
||||
|
||||
|
||||
@SessionScoped
|
||||
public static class SessionScopedTestBean extends ScopedTestBean implements AnotherScopeTestInterface {
|
||||
}
|
||||
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@javax.inject.Scope
|
||||
public static @interface RequestScoped {
|
||||
}
|
||||
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@javax.inject.Scope
|
||||
public static @interface SessionScoped {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
package org.springframework.context.annotation.scope;
|
||||
|
||||
import org.junit.After;
|
||||
import static org.junit.Assert.*;
|
||||
|
|
@ -26,6 +26,9 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
|||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.ScopedProxyMode;
|
||||
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
|
|
@ -279,15 +282,11 @@ public class ClassPathBeanDefinitionScannerScopeIntegrationTests {
|
|||
|
||||
private ApplicationContext createContext(ScopedProxyMode scopedProxyMode) {
|
||||
GenericWebApplicationContext context = new GenericWebApplicationContext();
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, false);
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
|
||||
scanner.setIncludeAnnotationConfig(false);
|
||||
scanner.addIncludeFilter(new AnnotationTypeFilter(ScopeTestComponent.class));
|
||||
scanner.setBeanNameGenerator(new BeanNameGenerator() {
|
||||
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
|
||||
String beanClassName = ClassUtils.getShortName(definition.getBeanClassName());
|
||||
int begin = beanClassName.lastIndexOf('.') + 1;
|
||||
int end = beanClassName.lastIndexOf("ScopedTestBean");
|
||||
return beanClassName.substring(begin, end).toLowerCase();
|
||||
return definition.getScope();
|
||||
}
|
||||
});
|
||||
scanner.setScopedProxyMode(scopedProxyMode);
|
||||
|
|
@ -301,10 +300,6 @@ public class ClassPathBeanDefinitionScannerScopeIntegrationTests {
|
|||
}
|
||||
|
||||
|
||||
public static @interface ScopeTestComponent {
|
||||
}
|
||||
|
||||
|
||||
public static interface IScopedTestBean {
|
||||
|
||||
String getName();
|
||||
|
|
@ -323,7 +318,7 @@ public class ClassPathBeanDefinitionScannerScopeIntegrationTests {
|
|||
}
|
||||
|
||||
|
||||
@ScopeTestComponent
|
||||
@Scope("singleton")
|
||||
public static class SingletonScopedTestBean extends ScopedTestBean {
|
||||
}
|
||||
|
||||
|
|
@ -333,13 +328,11 @@ public class ClassPathBeanDefinitionScannerScopeIntegrationTests {
|
|||
|
||||
|
||||
@Scope("request")
|
||||
@ScopeTestComponent
|
||||
public static class RequestScopedTestBean extends ScopedTestBean implements AnotherScopeTestInterface {
|
||||
}
|
||||
|
||||
|
||||
@Scope("session")
|
||||
@ScopeTestComponent
|
||||
public static class SessionScopedTestBean extends ScopedTestBean implements AnotherScopeTestInterface {
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue