diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java
index 58b2fd97bb6..49d235a6595 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 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.
@@ -153,12 +153,12 @@ public interface BeanFactory {
/**
* Return the bean instance that uniquely matches the given object type, if any.
- * @param requiredType type the bean must match; can be an interface or superclass.
- * {@code null} is disallowed.
*
This method goes into {@link ListableBeanFactory} by-type lookup territory
* but may also be translated into a conventional by-name lookup based on the name
* of the given type. For more extensive retrieval operations across sets of beans,
* use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
+ * @param requiredType type the bean must match; can be an interface or superclass.
+ * {@code null} is disallowed.
* @return an instance of the single bean matching the required type
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/NamedBean.java b/spring-beans/src/main/java/org/springframework/beans/factory/NamedBean.java
index e1e5ed33f57..9f2453ff653 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/NamedBean.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/NamedBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2006 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,10 +17,10 @@
package org.springframework.beans.factory;
/**
- * Counterpart of BeanNameAware. Returns the bean name of an object.
+ * Counterpart of {@link BeanNameAware}. Returns the bean name of an object.
*
- *
This interface can be introduced to avoid a brittle dependence
- * on bean name in objects used with Spring IoC and Spring AOP.
+ *
This interface can be introduced to avoid a brittle dependence on
+ * bean name in objects used with Spring IoC and Spring AOP.
*
* @author Rod Johnson
* @since 2.0
@@ -29,7 +29,7 @@ package org.springframework.beans.factory;
public interface NamedBean {
/**
- * Return the name of this bean in a Spring bean factory.
+ * Return the name of this bean in a Spring bean factory, if known.
*/
String getBeanName();
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java
index 43602b48ebf..bde3d36e59b 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/AutowireCapableBeanFactory.java
@@ -21,6 +21,8 @@ import java.util.Set;
import org.springframework.beans.BeansException;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
/**
* Extension of the {@link org.springframework.beans.factory.BeanFactory}
@@ -154,15 +156,6 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
*/
Object configureBean(Object existingBean, String beanName) throws BeansException;
- /**
- * Resolve the specified dependency against the beans defined in this factory.
- * @param descriptor the descriptor for the dependency
- * @param beanName the name of the bean which declares the present dependency
- * @return the resolved object, or {@code null} if none found
- * @throws BeansException if dependency resolution failed
- */
- Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException;
-
//-------------------------------------------------------------------------
// Specialized methods for fine-grained control over the bean lifecycle
@@ -312,18 +305,55 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
*/
void destroyBean(Object existingBean);
+
+ //-------------------------------------------------------------------------
+ // Delegate methods for resolving injection points
+ //-------------------------------------------------------------------------
+
+ /**
+ * Resolve the bean instance that uniquely matches the given object type, if any,
+ * including its bean name.
+ *
This is effectively a variant of {@link #getBean(Class)} which preserves the
+ * bean name of the matching instance.
+ * @param requiredType type the bean must match; can be an interface or superclass.
+ * {@code null} is disallowed.
+ * @return the bean name plus bean instance
+ * @throws NoSuchBeanDefinitionException if no bean of the given type was found
+ * @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
+ * @throws BeansException if the bean could not be created
+ * @since 4.3.3
+ * @see #getBean(Class)
+ */
+ NamedBeanHolder resolveNamedBean(Class requiredType) throws BeansException;
+
+ /**
+ * Resolve the specified dependency against the beans defined in this factory.
+ * @param descriptor the descriptor for the dependency
+ * @param requestingBeanName the name of the bean which declares the present dependency
+ * @return the resolved object, or {@code null} if none found
+ * @throws NoSuchBeanDefinitionException if no matching bean was found
+ * @throws NoUniqueBeanDefinitionException if more than one matching bean was found
+ * @throws BeansException if dependency resolution failed for any other reason
+ * @see #resolveDependency(DependencyDescriptor, String, Set, TypeConverter)
+ * @since 2.5
+ */
+ Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName) throws BeansException;
+
/**
* Resolve the specified dependency against the beans defined in this factory.
* @param descriptor the descriptor for the dependency
- * @param beanName the name of the bean which declares the present dependency
- * @param autowiredBeanNames a Set that all names of autowired beans (used for
- * resolving the present dependency) are supposed to be added to
- * @param typeConverter the TypeConverter to use for populating arrays and
- * collections
+ * @param requestingBeanName the name of the bean which declares the present dependency
+ * @param autowiredBeanNames a Set that all names of autowired beans (used for resolving
+ * the present dependency) are supposed to be added to
+ * @param typeConverter the TypeConverter to use for populating arrays and collections
* @return the resolved object, or {@code null} if none found
- * @throws BeansException if dependency resolution failed
+ * @throws NoSuchBeanDefinitionException if no matching bean was found
+ * @throws NoUniqueBeanDefinitionException if more than one matching bean was found
+ * @throws BeansException if dependency resolution failed for any other reason
+ * @see DependencyDescriptor
+ * @since 2.5
*/
- Object resolveDependency(DependencyDescriptor descriptor, String beanName,
+ Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
Set autowiredBeanNames, TypeConverter typeConverter) throws BeansException;
}
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/NamedBeanHolder.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/NamedBeanHolder.java
new file mode 100644
index 00000000000..b950aef98db
--- /dev/null
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/NamedBeanHolder.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2002-2016 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.config;
+
+import org.springframework.beans.factory.NamedBean;
+
+/**
+ * A simple holder for a given bean name plus bean instance.
+ *
+ * @author Juergen Hoeller
+ * @since 4.3.3
+ * @see AutowireCapableBeanFactory#resolveNamedBean(Class)
+ */
+public class NamedBeanHolder implements NamedBean {
+
+ private final String beanName;
+
+ private final T beanInstance;
+
+
+ /**
+ * Create a new holder for the given bean name plus instance.
+ */
+ public NamedBeanHolder(String beanName, T beanInstance) {
+ this.beanName = beanName;
+ this.beanInstance = beanInstance;
+ }
+
+
+ @Override
+ public String getBeanName() {
+ return this.beanName;
+ }
+
+ /**
+ * Return the corresponding bean instance.
+ */
+ public T getBeanInstance() {
+ return this.beanInstance;
+ }
+
+}
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
index c30e6740dfb..2e47ff2be7c 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
@@ -32,7 +32,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -62,11 +61,13 @@ import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
+import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
+import org.springframework.beans.factory.config.NamedBeanHolder;
import org.springframework.core.OrderComparator;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationUtils;
@@ -326,43 +327,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@Override
public T getBean(Class requiredType, Object... args) throws BeansException {
- Assert.notNull(requiredType, "Required type must not be null");
- String[] beanNames = getBeanNamesForType(requiredType);
- if (beanNames.length > 1) {
- ArrayList autowireCandidates = new ArrayList<>();
- for (String beanName : beanNames) {
- if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
- autowireCandidates.add(beanName);
- }
- }
- if (autowireCandidates.size() > 0) {
- beanNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
- }
- }
- if (beanNames.length == 1) {
- return getBean(beanNames[0], requiredType, args);
- }
- else if (beanNames.length > 1) {
- Map candidates = new HashMap<>();
- for (String beanName : beanNames) {
- candidates.put(beanName, getBean(beanName, requiredType, args));
- }
- String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
- if (primaryCandidate != null) {
- return getBean(primaryCandidate, requiredType, args);
- }
- String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
- if (priorityCandidate != null) {
- return getBean(priorityCandidate, requiredType, args);
- }
- throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
- }
- else if (getParentBeanFactory() != null) {
- return getParentBeanFactory().getBean(requiredType, args);
+ NamedBeanHolder namedBean = resolveNamedBean(requiredType, args);
+ if (namedBean != null) {
+ return namedBean.getBeanInstance();
}
- else {
- throw new NoSuchBeanDefinitionException(requiredType);
+ BeanFactory parent = getParentBeanFactory();
+ if (parent != null) {
+ return parent.getBean(requiredType, args);
}
+ throw new NoSuchBeanDefinitionException(requiredType);
}
@@ -642,13 +615,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
else if (containsSingleton(beanName)) {
return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor, resolver);
}
- else if (getParentBeanFactory() instanceof DefaultListableBeanFactory) {
+
+ BeanFactory parent = getParentBeanFactory();
+ if (parent instanceof DefaultListableBeanFactory) {
// No bean definition found in this factory -> delegate to parent.
- return ((DefaultListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor, resolver);
+ return ((DefaultListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor, resolver);
}
- else if (getParentBeanFactory() instanceof ConfigurableListableBeanFactory) {
+ else if (parent instanceof ConfigurableListableBeanFactory) {
// If no DefaultListableBeanFactory, can't pass the resolver along.
- return ((ConfigurableListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor);
+ return ((ConfigurableListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor);
}
else {
return true;
@@ -989,24 +964,74 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
//---------------------------------------------------------------------
@Override
- public Object resolveDependency(DependencyDescriptor descriptor, String beanName,
+ public NamedBeanHolder resolveNamedBean(Class requiredType) throws BeansException {
+ NamedBeanHolder namedBean = resolveNamedBean(requiredType, (Object[]) null);
+ if (namedBean != null) {
+ return namedBean;
+ }
+ BeanFactory parent = getParentBeanFactory();
+ if (parent instanceof AutowireCapableBeanFactory) {
+ return ((AutowireCapableBeanFactory) parent).resolveNamedBean(requiredType);
+ }
+ return null;
+ }
+
+ private NamedBeanHolder resolveNamedBean(Class requiredType, Object... args) throws BeansException {
+ Assert.notNull(requiredType, "Required type must not be null");
+ String[] beanNames = getBeanNamesForType(requiredType);
+ if (beanNames.length > 1) {
+ ArrayList autowireCandidates = new ArrayList<>();
+ for (String beanName : beanNames) {
+ if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
+ autowireCandidates.add(beanName);
+ }
+ }
+ if (!autowireCandidates.isEmpty()) {
+ beanNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
+ }
+ }
+ if (beanNames.length == 1) {
+ String beanName = beanNames[0];
+ return new NamedBeanHolder<>(beanName, getBean(beanName, requiredType, args));
+ }
+ else if (beanNames.length > 1) {
+ Map candidates = new LinkedHashMap<>();
+ for (String beanName : beanNames) {
+ candidates.put(beanName, getBean(beanName, requiredType, args));
+ }
+ String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
+ if (primaryCandidate != null) {
+ return new NamedBeanHolder<>(primaryCandidate, getBean(primaryCandidate, requiredType, args));
+ }
+ String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
+ if (priorityCandidate != null) {
+ return new NamedBeanHolder<>(priorityCandidate, getBean(priorityCandidate, requiredType, args));
+ }
+ throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
+ }
+ return null;
+ }
+
+ @Override
+ public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
Set autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
- return createOptionalDependency(descriptor, beanName);
+ return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
- return new DependencyObjectProvider(descriptor, beanName);
+ return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
- return new Jsr330ProviderFactory().createDependencyProvider(descriptor, beanName);
+ return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
- Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, beanName);
+ Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
+ descriptor, requestingBeanName);
if (result == null) {
- result = doResolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter);
+ result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
@@ -1337,9 +1362,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (containsBeanDefinition(beanName)) {
return getMergedLocalBeanDefinition(beanName).isPrimary();
}
- BeanFactory parentFactory = getParentBeanFactory();
- return (parentFactory instanceof DefaultListableBeanFactory &&
- ((DefaultListableBeanFactory) parentFactory).isPrimary(beanName, beanInstance));
+ BeanFactory parent = getParentBeanFactory();
+ return (parent instanceof DefaultListableBeanFactory &&
+ ((DefaultListableBeanFactory) parent).isPrimary(beanName, beanInstance));
}
/**
@@ -1415,8 +1440,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
}
- if (getParentBeanFactory() instanceof DefaultListableBeanFactory) {
- ((DefaultListableBeanFactory) getParentBeanFactory()).checkBeanNotOfRequiredType(type, descriptor);
+ BeanFactory parent = getParentBeanFactory();
+ if (parent instanceof DefaultListableBeanFactory) {
+ ((DefaultListableBeanFactory) parent).checkBeanNotOfRequiredType(type, descriptor);
}
}
diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java b/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java
index 47a89cc7df2..df0dad47658 100644
--- a/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java
+++ b/spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java
@@ -41,14 +41,14 @@ import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
-import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
-import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
+import org.springframework.beans.factory.config.NamedBeanHolder;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.BridgeMethodResolver;
@@ -569,21 +569,16 @@ public class PersistenceAnnotationBeanPostProcessor
protected EntityManagerFactory findDefaultEntityManagerFactory(String requestingBeanName)
throws NoSuchBeanDefinitionException {
- String[] beanNames =
- BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, EntityManagerFactory.class);
- if (beanNames.length == 1) {
- String unitName = beanNames[0];
- EntityManagerFactory emf = (EntityManagerFactory) this.beanFactory.getBean(unitName);
- if (this.beanFactory instanceof ConfigurableBeanFactory) {
- ((ConfigurableBeanFactory) this.beanFactory).registerDependentBean(unitName, requestingBeanName);
- }
- return emf;
- }
- else if (beanNames.length > 1) {
- throw new NoUniqueBeanDefinitionException(EntityManagerFactory.class, beanNames);
+ if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
+ // Fancy variant with dependency registration
+ ConfigurableListableBeanFactory clbf = (ConfigurableListableBeanFactory) this.beanFactory;
+ NamedBeanHolder emfHolder = clbf.resolveNamedBean(EntityManagerFactory.class);
+ clbf.registerDependentBean(emfHolder.getBeanName(), requestingBeanName);
+ return emfHolder.getBeanInstance();
}
else {
- throw new NoSuchBeanDefinitionException(EntityManagerFactory.class);
+ // Plain variant: just find a default bean
+ return this.beanFactory.getBean(EntityManagerFactory.class);
}
}
diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/setup/StubWebApplicationContext.java b/spring-test/src/main/java/org/springframework/test/web/servlet/setup/StubWebApplicationContext.java
index 600c8e921e3..972515686a0 100644
--- a/spring-test/src/main/java/org/springframework/test/web/servlet/setup/StubWebApplicationContext.java
+++ b/spring-test/src/main/java/org/springframework/test/web/servlet/setup/StubWebApplicationContext.java
@@ -31,6 +31,7 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
+import org.springframework.beans.factory.config.NamedBeanHolder;
import org.springframework.beans.factory.support.StaticListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -393,12 +394,17 @@ class StubWebApplicationContext implements WebApplicationContext {
}
@Override
- public Object resolveDependency(DependencyDescriptor descriptor, String beanName) {
+ public NamedBeanHolder resolveNamedBean(Class requiredType) throws BeansException {
throw new UnsupportedOperationException("Dependency resolution not supported");
}
@Override
- public Object resolveDependency(DependencyDescriptor descriptor, String beanName,
+ public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName) {
+ throw new UnsupportedOperationException("Dependency resolution not supported");
+ }
+
+ @Override
+ public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
Set autowiredBeanNames, TypeConverter typeConverter) {
throw new UnsupportedOperationException("Dependency resolution not supported");
}