提交 890819f8 编写于 作者: J Juergen Hoeller

SmartObjectFactory provides getObject(args) variant as well

Issue: SPR-13956
上级 5ed90468
...@@ -28,8 +28,20 @@ import org.springframework.beans.BeansException; ...@@ -28,8 +28,20 @@ import org.springframework.beans.BeansException;
public interface SmartObjectFactory<T> extends ObjectFactory<T> { public interface SmartObjectFactory<T> extends ObjectFactory<T> {
/** /**
* Return an instance (possibly shared or independent) * Return an instance (possibly shared or independent) of the object
* of the object managed by this factory. * managed by this factory.
* <p>Allows for specifying explicit construction arguments, along the
* lines of {@link BeanFactory#getBean(String, Object...)}.
* @param args arguments to use when creating a corresponding instance
* @return an instance of the bean
* @throws BeansException in case of creation errors
* @see #getObject()
*/
T getObject(Object... args) throws BeansException;
/**
* Return an instance (possibly shared or independent) of the object
* managed by this factory.
* @return an instance of the bean, or {@code null} if not available * @return an instance of the bean, or {@code null} if not available
* @throws BeansException in case of creation errors * @throws BeansException in case of creation errors
* @see #getObject() * @see #getObject()
...@@ -37,8 +49,8 @@ public interface SmartObjectFactory<T> extends ObjectFactory<T> { ...@@ -37,8 +49,8 @@ public interface SmartObjectFactory<T> extends ObjectFactory<T> {
T getIfAvailable() throws BeansException; T getIfAvailable() throws BeansException;
/** /**
* Return an instance (possibly shared or independent) * Return an instance (possibly shared or independent) of the object
* of the object managed by this factory. * managed by this factory.
* @return an instance of the bean, or {@code null} if not available or * @return an instance of the bean, or {@code null} if not available or
* not unique (i.e. multiple candidates found with none marked as primary) * not unique (i.e. multiple candidates found with none marked as primary)
* @throws BeansException in case of creation errors * @throws BeansException in case of creation errors
......
...@@ -26,6 +26,7 @@ import java.lang.reflect.Type; ...@@ -26,6 +26,7 @@ import java.lang.reflect.Type;
import java.util.Map; import java.util.Map;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException; import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.core.GenericCollectionTypeResolver; import org.springframework.core.GenericCollectionTypeResolver;
import org.springframework.core.GenericTypeResolver; import org.springframework.core.GenericTypeResolver;
...@@ -200,6 +201,20 @@ public class DependencyDescriptor implements Serializable { ...@@ -200,6 +201,20 @@ public class DependencyDescriptor implements Serializable {
throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet()); throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
} }
/**
* Resolve the specified bean name, as a candidate result of the matching
* algorithm for this dependency, to a bean instance from the given factory.
* <p>The default implementation calls {@link BeanFactory#getBean(String)}.
* Subclasses may provide additional arguments or other customizations.
* @param beanName the bean name, as a candidate result for this dependency
* @param beanFactory the associated factory
* @return the bean instance (never {@code null})
* @see BeanFactory#getBean(String)
*/
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
return beanFactory.getBean(beanName);
}
/** /**
* Increase this descriptor's nesting level. * Increase this descriptor's nesting level.
......
...@@ -1052,7 +1052,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto ...@@ -1052,7 +1052,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (matchingBeans.size() > 1) { if (matchingBeans.size() > 1) {
String primaryBeanName = determineAutowireCandidate(matchingBeans, descriptor); String primaryBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (primaryBeanName == null) { if (primaryBeanName == null) {
if (!indicatesMultipleBeans(type) || descriptor.isRequired()) { if (descriptor.isRequired() || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(type, matchingBeans); return descriptor.resolveNotUnique(type, matchingBeans);
} }
else { else {
...@@ -1198,7 +1198,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto ...@@ -1198,7 +1198,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
} }
for (String candidateName : candidateNames) { for (String candidateName : candidateNames) {
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) { if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) {
result.put(candidateName, getBean(candidateName)); result.put(candidateName, descriptor.resolveCandidate(candidateName, this));
} }
} }
if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) { if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
...@@ -1206,14 +1206,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto ...@@ -1206,14 +1206,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch(); DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidateName : candidateNames) { for (String candidateName : candidateNames) {
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) { if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
result.put(candidateName, getBean(candidateName)); result.put(candidateName, descriptor.resolveCandidate(candidateName, this));
} }
} }
if (result.isEmpty()) { if (result.isEmpty()) {
// Consider self references before as a final pass // Consider self references before as a final pass
for (String candidateName : candidateNames) { for (String candidateName : candidateNames) {
if (isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) { if (isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
result.put(candidateName, getBean(candidateName)); result.put(candidateName, descriptor.resolveCandidate(candidateName, this));
} }
} }
} }
...@@ -1462,12 +1462,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto ...@@ -1462,12 +1462,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@UsesJava8 @UsesJava8
private class OptionalDependencyFactory { private class OptionalDependencyFactory {
public Object createOptionalDependency(DependencyDescriptor descriptor, String beanName) { public Object createOptionalDependency(DependencyDescriptor descriptor, String beanName, final Object... args) {
DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) { DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) {
@Override @Override
public boolean isRequired() { public boolean isRequired() {
return false; return false;
} }
@Override
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, args) :
super.resolveCandidate(beanName, beanFactory));
}
}; };
descriptorToUse.increaseNestingLevel(); descriptorToUse.increaseNestingLevel();
return Optional.ofNullable(doResolveDependency(descriptorToUse, beanName, null, null)); return Optional.ofNullable(doResolveDependency(descriptorToUse, beanName, null, null));
...@@ -1503,6 +1508,22 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto ...@@ -1503,6 +1508,22 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
} }
} }
@Override
public Object getObject(final Object... args) throws BeansException {
if (this.optional) {
return new OptionalDependencyFactory().createOptionalDependency(this.descriptor, this.beanName, args);
}
else {
DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) {
@Override
public Object resolveCandidate(String beanName, BeanFactory beanFactory) {
return beanFactory.getBean(beanName, args);
}
};
return doResolveDependency(descriptorToUse, this.beanName, null, null);
}
}
@Override @Override
public Object getIfAvailable() throws BeansException { public Object getIfAvailable() throws BeansException {
if (this.optional) { if (this.optional) {
......
...@@ -1047,7 +1047,26 @@ public class AutowiredAnnotationBeanPostProcessorTests { ...@@ -1047,7 +1047,26 @@ public class AutowiredAnnotationBeanPostProcessorTests {
} }
@Test @Test
public void testSmartObjectFactoryInjection() { public void testSmartObjectFactoryInjectionWithPrototype() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
bpp.setBeanFactory(bf);
bf.addBeanPostProcessor(bpp);
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SmartObjectFactoryInjectionBean.class));
RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class);
tbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
bf.registerBeanDefinition("testBean", tbd);
SmartObjectFactoryInjectionBean bean = (SmartObjectFactoryInjectionBean) bf.getBean("annotatedBean");
assertEquals(bf.getBean("testBean"), bean.getTestBean());
assertEquals(bf.getBean("testBean", "myName"), bean.getTestBean("myName"));
assertEquals(bf.getBean("testBean"), bean.getOptionalTestBean());
assertEquals(bf.getBean("testBean"), bean.getUniqueTestBean());
bf.destroySingletons();
}
@Test
public void testSmartObjectFactoryInjectionWithSingletonTarget() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
bpp.setBeanFactory(bf); bpp.setBeanFactory(bf);
...@@ -2557,6 +2576,10 @@ public class AutowiredAnnotationBeanPostProcessorTests { ...@@ -2557,6 +2576,10 @@ public class AutowiredAnnotationBeanPostProcessorTests {
return this.testBeanFactory.getObject(); return this.testBeanFactory.getObject();
} }
public TestBean getTestBean(String name) {
return this.testBeanFactory.getObject(name);
}
public TestBean getOptionalTestBean() { public TestBean getOptionalTestBean() {
return this.testBeanFactory.getIfAvailable(); return this.testBeanFactory.getIfAvailable();
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册