@Resource provides dependency descriptor for resolving beans by name
Closes gh-22359
This commit is contained in:
parent
5f4c461d4f
commit
e9626779ee
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2018 the original author or authors.
|
* Copyright 2002-2019 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -133,8 +133,7 @@ public interface BeanFactory {
|
||||||
* Will ask the parent factory if the bean cannot be found in this factory instance.
|
* Will ask the parent factory if the bean cannot be found in this factory instance.
|
||||||
* @param name the name of the bean to retrieve
|
* @param name the name of the bean to retrieve
|
||||||
* @return an instance of the bean
|
* @return an instance of the bean
|
||||||
* @throws NoSuchBeanDefinitionException if there is no bean definition
|
* @throws NoSuchBeanDefinitionException if there is no bean with the specified name
|
||||||
* with the specified name
|
|
||||||
* @throws BeansException if the bean could not be obtained
|
* @throws BeansException if the bean could not be obtained
|
||||||
*/
|
*/
|
||||||
Object getBean(String name) throws BeansException;
|
Object getBean(String name) throws BeansException;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2019 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -29,6 +29,8 @@ import org.springframework.util.ObjectUtils;
|
||||||
/**
|
/**
|
||||||
* A simple descriptor for an injection point, pointing to a method/constructor
|
* A simple descriptor for an injection point, pointing to a method/constructor
|
||||||
* parameter or a field. Exposed by {@link UnsatisfiedDependencyException}.
|
* parameter or a field. Exposed by {@link UnsatisfiedDependencyException}.
|
||||||
|
* Also available as an argument for factory methods, reacting to the
|
||||||
|
* requesting injection point for building a customized bean instance.
|
||||||
*
|
*
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 4.3
|
* @since 4.3
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2018 the original author or authors.
|
* Copyright 2002-2019 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -337,8 +337,7 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||||
* including its bean name.
|
* including its bean name.
|
||||||
* <p>This is effectively a variant of {@link #getBean(Class)} which preserves the
|
* <p>This is effectively a variant of {@link #getBean(Class)} which preserves the
|
||||||
* bean name of the matching instance.
|
* bean name of the matching instance.
|
||||||
* @param requiredType type the bean must match; can be an interface or superclass.
|
* @param requiredType type the bean must match; can be an interface or superclass
|
||||||
* {@code null} is disallowed.
|
|
||||||
* @return the bean name plus bean instance
|
* @return the bean name plus bean instance
|
||||||
* @throws NoSuchBeanDefinitionException if no matching bean was found
|
* @throws NoSuchBeanDefinitionException if no matching bean was found
|
||||||
* @throws NoUniqueBeanDefinitionException if more than one matching bean was found
|
* @throws NoUniqueBeanDefinitionException if more than one matching bean was found
|
||||||
|
@ -348,6 +347,22 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||||
*/
|
*/
|
||||||
<T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;
|
<T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve a bean instance for the given bean name, providing a dependency descriptor
|
||||||
|
* for exposure to target factory methods.
|
||||||
|
* <p>This is effectively a variant of {@link #getBean(String, Class)} which supports
|
||||||
|
* factory methods with an {@link org.springframework.beans.factory.InjectionPoint}
|
||||||
|
* argument.
|
||||||
|
* @param name the name of the bean to look up
|
||||||
|
* @param descriptor the dependency descriptor for the requesting injection point
|
||||||
|
* @return the corresponding bean instance
|
||||||
|
* @throws NoSuchBeanDefinitionException if there is no bean with the specified name
|
||||||
|
* @throws BeansException if the bean could not be created
|
||||||
|
* @since 5.1.5
|
||||||
|
* @see #getBean(String, Class)
|
||||||
|
*/
|
||||||
|
Object resolveBeanByName(String name, DependencyDescriptor descriptor) throws BeansException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve the specified dependency against the beans defined in this factory.
|
* Resolve the specified dependency against the beans defined in this factory.
|
||||||
* @param descriptor the descriptor for the dependency (field/method/constructor)
|
* @param descriptor the descriptor for the dependency (field/method/constructor)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2018 the original author or authors.
|
* Copyright 2002-2019 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -58,6 +58,7 @@ import org.springframework.beans.factory.BeanFactoryAware;
|
||||||
import org.springframework.beans.factory.BeanNameAware;
|
import org.springframework.beans.factory.BeanNameAware;
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.InjectionPoint;
|
||||||
import org.springframework.beans.factory.UnsatisfiedDependencyException;
|
import org.springframework.beans.factory.UnsatisfiedDependencyException;
|
||||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
@ -337,12 +338,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
return initializeBean(beanName, existingBean, bd);
|
return initializeBean(beanName, existingBean, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException {
|
|
||||||
return resolveDependency(descriptor, requestingBeanName, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// Specialized methods for fine-grained control over the bean lifecycle
|
// Specialized methods for fine-grained control over the bean lifecycle
|
||||||
|
@ -446,6 +441,28 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Delegate methods for resolving injection points
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object resolveBeanByName(String name, DependencyDescriptor descriptor) {
|
||||||
|
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
|
||||||
|
try {
|
||||||
|
return getBean(name, descriptor.getDependencyType());
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException {
|
||||||
|
return resolveDependency(descriptor, requestingBeanName, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
// Implementation of relevant AbstractBeanFactory template methods
|
// Implementation of relevant AbstractBeanFactory template methods
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2018 the original author or authors.
|
* Copyright 2002-2019 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -512,15 +512,21 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||||
Set<String> autowiredBeanNames;
|
Set<String> autowiredBeanNames;
|
||||||
String name = element.name;
|
String name = element.name;
|
||||||
|
|
||||||
if (this.fallbackToDefaultTypeMatch && element.isDefaultName &&
|
if (factory instanceof AutowireCapableBeanFactory) {
|
||||||
factory instanceof AutowireCapableBeanFactory && !factory.containsBean(name)) {
|
AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
|
||||||
|
DependencyDescriptor descriptor = element.getDependencyDescriptor();
|
||||||
|
if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {
|
||||||
autowiredBeanNames = new LinkedHashSet<>();
|
autowiredBeanNames = new LinkedHashSet<>();
|
||||||
resource = ((AutowireCapableBeanFactory) factory).resolveDependency(
|
resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
|
||||||
element.getDependencyDescriptor(), requestingBeanName, autowiredBeanNames, null);
|
|
||||||
if (resource == null) {
|
if (resource == null) {
|
||||||
throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
|
throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
resource = beanFactory.resolveBeanByName(name, descriptor);
|
||||||
|
autowiredBeanNames = Collections.singleton(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
resource = factory.getBean(name, element.lookupType);
|
resource = factory.getBean(name, element.lookupType);
|
||||||
autowiredBeanNames = Collections.singleton(name);
|
autowiredBeanNames = Collections.singleton(name);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2018 the original author or authors.
|
* Copyright 2002-2019 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -21,6 +21,7 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
|
@ -228,6 +229,22 @@ public class ConfigurationClassProcessingTests {
|
||||||
ctx.close();
|
ctx.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void configurationWithAdaptiveResourcePrototypes() {
|
||||||
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||||
|
ctx.register(ConfigWithPrototypeBean.class, AdaptiveResourceInjectionPoints.class);
|
||||||
|
ctx.refresh();
|
||||||
|
|
||||||
|
AdaptiveResourceInjectionPoints adaptive = ctx.getBean(AdaptiveResourceInjectionPoints.class);
|
||||||
|
assertEquals("adaptiveInjectionPoint1", adaptive.adaptiveInjectionPoint1.getName());
|
||||||
|
assertEquals("setAdaptiveInjectionPoint2", adaptive.adaptiveInjectionPoint2.getName());
|
||||||
|
|
||||||
|
adaptive = ctx.getBean(AdaptiveResourceInjectionPoints.class);
|
||||||
|
assertEquals("adaptiveInjectionPoint1", adaptive.adaptiveInjectionPoint1.getName());
|
||||||
|
assertEquals("setAdaptiveInjectionPoint2", adaptive.adaptiveInjectionPoint2.getName());
|
||||||
|
ctx.close();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void configurationWithPostProcessor() {
|
public void configurationWithPostProcessor() {
|
||||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||||
|
@ -444,6 +461,21 @@ public class ConfigurationClassProcessingTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Scope("prototype")
|
||||||
|
static class AdaptiveResourceInjectionPoints {
|
||||||
|
|
||||||
|
@Resource(name = "adaptive1")
|
||||||
|
public TestBean adaptiveInjectionPoint1;
|
||||||
|
|
||||||
|
public TestBean adaptiveInjectionPoint2;
|
||||||
|
|
||||||
|
@Resource(name = "adaptive2")
|
||||||
|
public void setAdaptiveInjectionPoint2(TestBean adaptiveInjectionPoint2) {
|
||||||
|
this.adaptiveInjectionPoint2 = adaptiveInjectionPoint2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static class ConfigWithPostProcessor extends ConfigWithPrototypeBean {
|
static class ConfigWithPostProcessor extends ConfigWithPrototypeBean {
|
||||||
|
|
||||||
@Value("${myProp}")
|
@Value("${myProp}")
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2018 the original author or authors.
|
* Copyright 2002-2019 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -411,6 +411,11 @@ class StubWebApplicationContext implements WebApplicationContext {
|
||||||
throw new UnsupportedOperationException("Dependency resolution not supported");
|
throw new UnsupportedOperationException("Dependency resolution not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object resolveBeanByName(String name, DependencyDescriptor descriptor) throws BeansException {
|
||||||
|
throw new UnsupportedOperationException("Dependency resolution not supported");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) {
|
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) {
|
||||||
|
|
Loading…
Reference in New Issue