Programmatic ObjectProvider retrieval through BeanFactory API

Introduces getBeanProvider(Class) and getBeanProvider(ResolvableType), also narrowing getBean(String, Class) and isTypeMatch(String, Class) to a non-null Class argument and enriching NoUniqueBeanDefinitionException with a full ResolvableType. In addition, ObjectProvider supports iterable/stream access for collection-style resolution of multiple matching beans now, and collection injection falls back to an empty collection in a single-constructor case with non-null arguments.

Issue: SPR-17075
Issue: SPR-11419
Issue: SPR-15338
This commit is contained in:
Juergen Hoeller
2018-07-24 00:42:03 +02:00
parent 82194f4ee0
commit 1603c4ab2f
16 changed files with 918 additions and 100 deletions

View File

@@ -35,6 +35,7 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.CachedIntrospectionResults;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
@@ -1083,7 +1084,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
}
@Override
public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name, requiredType);
}
@@ -1106,6 +1107,18 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
return getBeanFactory().getBean(requiredType, args);
}
@Override
public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType) {
assertBeanFactoryActive();
return getBeanFactory().getBeanProvider(requiredType);
}
@Override
public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType) {
assertBeanFactoryActive();
return getBeanFactory().getBeanProvider(requiredType);
}
@Override
public boolean containsBean(String name) {
return getBeanFactory().containsBean(name);
@@ -1130,7 +1143,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
}
@Override
public boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
public boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
assertBeanFactoryActive();
return getBeanFactory().isTypeMatch(name, typeToMatch);
}

View File

@@ -29,6 +29,8 @@ import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.core.ResolvableType;
import org.springframework.jndi.JndiLocatorSupport;
import org.springframework.jndi.TypeMismatchNamingException;
@@ -107,7 +109,7 @@ public class SimpleJndiBeanFactory extends JndiLocatorSupport implements BeanFac
}
@Override
public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
try {
if (isSingleton(name)) {
return doGetSingleton(name, requiredType);
@@ -150,6 +152,49 @@ public class SimpleJndiBeanFactory extends JndiLocatorSupport implements BeanFac
return getBean(requiredType);
}
@Override
public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType) {
return new ObjectProvider<T>() {
@Override
public T getObject() throws BeansException {
return getBean(requiredType);
}
@Override
public T getObject(Object... args) throws BeansException {
return getBean(requiredType, args);
}
@Override
@Nullable
public T getIfAvailable() throws BeansException {
try {
return getBean(requiredType);
}
catch (NoUniqueBeanDefinitionException ex) {
throw ex;
}
catch (NoSuchBeanDefinitionException ex) {
return null;
}
}
@Override
@Nullable
public T getIfUnique() throws BeansException {
try {
return getBean(requiredType);
}
catch (NoSuchBeanDefinitionException ex) {
return null;
}
}
};
}
@Override
public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType) {
throw new UnsupportedOperationException(
"SimpleJndiBeanFactory does not support resolution by ResolvableType");
}
@Override
public boolean containsBean(String name) {
if (this.singletonObjects.containsKey(name) || this.resourceTypes.containsKey(name)) {