Browse Source

Avoid Autowired shortcut resolution for NullBean values

Includes getBean documentation against NullBean values.

Closes gh-30485
pull/30619/head
Juergen Hoeller 2 years ago
parent
commit
8b8d147480
  1. 13
      spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java
  2. 4
      spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java
  3. 20
      spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java

13
spring-beans/src/main/java/org/springframework/beans/factory/BeanFactory.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 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.
@ -136,7 +136,10 @@ public interface BeanFactory { @@ -136,7 +136,10 @@ public interface BeanFactory {
* <p>Translates aliases back to the corresponding canonical bean name.
* <p>Will ask the parent factory if the bean cannot be found in this factory instance.
* @param name the name of the bean to retrieve
* @return an instance of the bean
* @return an instance of the bean.
* Note that the return value will never be {@code null} but possibly a stub for
* {@code null} returned from a factory method, to be checked via {@code equals(null)}.
* Consider using {@link #getBeanProvider(Class)} for resolving optional dependencies.
* @throws NoSuchBeanDefinitionException if there is no bean with the specified name
* @throws BeansException if the bean could not be obtained
*/
@ -152,7 +155,11 @@ public interface BeanFactory { @@ -152,7 +155,11 @@ public interface BeanFactory {
* <p>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 requiredType type the bean must match; can be an interface or superclass
* @return an instance of the bean
* @return an instance of the bean.
* Note that the return value will never be {@code null}. In case of a stub for
* {@code null} from a factory method having been resolved for the requested bean, a
* {@code BeanNotOfRequiredTypeException} against the NullBean stub will be raised.
* Consider using {@link #getBeanProvider(Class)} for resolving optional dependencies.
* @throws NoSuchBeanDefinitionException if there is no such bean definition
* @throws BeanNotOfRequiredTypeException if the bean is not of the required type
* @throws BeansException if the bean could not be created

4
spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java

@ -719,7 +719,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA @@ -719,7 +719,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
if (value != null || this.required) {
cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
if (value != null && autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
@ -829,7 +829,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA @@ -829,7 +829,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
Class<?>[] paramTypes = method.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
String autowiredBeanName = it.next();
if (beanFactory.containsBean(autowiredBeanName) &&
if (arguments[i] != null && beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
descriptors[i], autowiredBeanName, paramTypes[i]);

20
spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java

@ -130,6 +130,26 @@ public class AutowiredAnnotationBeanPostProcessorTests { @@ -130,6 +130,26 @@ public class AutowiredAnnotationBeanPostProcessorTests {
assertThat(bean.getTestBean2()).isSameAs(tb);
}
@Test
void resourceInjectionWithNullBean() {
RootBeanDefinition bd = new RootBeanDefinition(NonPublicResourceInjectionBean.class);
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
bf.registerBeanDefinition("annotatedBean", bd);
RootBeanDefinition tb = new RootBeanDefinition(NullFactoryMethods.class);
tb.setFactoryMethodName("createTestBean");
bf.registerBeanDefinition("testBean", tb);
NonPublicResourceInjectionBean bean = (NonPublicResourceInjectionBean) bf.getBean("annotatedBean");
assertThat(bean.getTestBean()).isNull();
assertThat(bean.getTestBean2()).isNull();
assertThat(bean.getTestBean3()).isNull();
bean = (NonPublicResourceInjectionBean) bf.getBean("annotatedBean");
assertThat(bean.getTestBean()).isNull();
assertThat(bean.getTestBean2()).isNull();
assertThat(bean.getTestBean3()).isNull();
}
@Test
void extendedResourceInjection() {
RootBeanDefinition bd = new RootBeanDefinition(TypedExtendedResourceInjectionBean.class);

Loading…
Cancel
Save