Enforce consistent null check on injection points for pre-existing singleton beans
Includes consistent JSpecify nullness check on fields as optional injection points Closes gh-34952 See gh-34261
This commit is contained in:
@@ -34,6 +34,7 @@ import org.springframework.beans.factory.InjectionPoint;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.core.KotlinDetector;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.Nullness;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
@@ -162,7 +163,7 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
}
|
||||
|
||||
if (this.field != null) {
|
||||
return !(this.field.getType() == Optional.class || hasNullableAnnotation() ||
|
||||
return !(this.field.getType() == Optional.class || Nullness.forField(this.field) == Nullness.NULLABLE ||
|
||||
(KotlinDetector.isKotlinType(this.field.getDeclaringClass()) && KotlinDelegate.isNullable(this.field)));
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1656,12 +1656,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (autowiredBeanNames != null) {
|
||||
autowiredBeanNames.add(dependencyName);
|
||||
}
|
||||
boolean preExisting = containsSingleton(dependencyName);
|
||||
Object dependencyBean = getBean(dependencyName);
|
||||
if (preExisting && dependencyBean instanceof NullBean) {
|
||||
// for backwards compatibility with addCandidateEntry in the regular code path
|
||||
dependencyBean = null;
|
||||
}
|
||||
return resolveInstance(dependencyBean, descriptor, type, dependencyName);
|
||||
}
|
||||
}
|
||||
@@ -1972,7 +1967,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
else if (containsSingleton(candidateName) ||
|
||||
(descriptor instanceof StreamDependencyDescriptor streamDescriptor && streamDescriptor.isOrdered())) {
|
||||
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
|
||||
candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
|
||||
candidates.put(candidateName, beanInstance);
|
||||
}
|
||||
else {
|
||||
candidates.put(candidateName, getType(candidateName));
|
||||
|
||||
@@ -974,7 +974,9 @@ class AutowiredAnnotationBeanPostProcessorTests {
|
||||
bf.registerBeanDefinition("testBean", tb);
|
||||
|
||||
bf.getBean("testBean");
|
||||
assertThat(bf.getBean("annotatedBean", ConstructorWithoutFallbackBean.class).getTestBean3()).isNull();
|
||||
assertThatExceptionOfType(UnsatisfiedDependencyException.class)
|
||||
.isThrownBy(() -> bf.getBean("annotatedBean"))
|
||||
.satisfies(methodParameterDeclaredOn(ConstructorWithoutFallbackBean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -985,7 +987,9 @@ class AutowiredAnnotationBeanPostProcessorTests {
|
||||
bf.registerBeanDefinition("testBean3", tb);
|
||||
|
||||
bf.getBean("testBean3");
|
||||
assertThat(bf.getBean("annotatedBean", ConstructorWithoutFallbackBean.class).getTestBean3()).isNull();
|
||||
assertThatExceptionOfType(UnsatisfiedDependencyException.class)
|
||||
.isThrownBy(() -> bf.getBean("annotatedBean"))
|
||||
.satisfies(methodParameterDeclaredOn(ConstructorWithoutFallbackBean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -2733,22 +2737,22 @@ class AutowiredAnnotationBeanPostProcessorTests {
|
||||
public static class ResourceInjectionBean {
|
||||
|
||||
@Autowired(required = false)
|
||||
private TestBean testBean;
|
||||
private @Nullable TestBean testBean;
|
||||
|
||||
TestBean testBean2;
|
||||
@Nullable TestBean testBean2;
|
||||
|
||||
@Autowired
|
||||
public void setTestBean2(TestBean testBean2) {
|
||||
public void setTestBean2(@Nullable TestBean testBean2) {
|
||||
Assert.state(this.testBean != null, "Wrong initialization order");
|
||||
Assert.state(this.testBean2 == null, "Already called");
|
||||
this.testBean2 = testBean2;
|
||||
}
|
||||
|
||||
public TestBean getTestBean() {
|
||||
public @Nullable TestBean getTestBean() {
|
||||
return this.testBean;
|
||||
}
|
||||
|
||||
public TestBean getTestBean2() {
|
||||
public @Nullable TestBean getTestBean2() {
|
||||
return this.testBean2;
|
||||
}
|
||||
}
|
||||
@@ -2757,13 +2761,13 @@ class AutowiredAnnotationBeanPostProcessorTests {
|
||||
static class NonPublicResourceInjectionBean<T> extends ResourceInjectionBean {
|
||||
|
||||
@Autowired
|
||||
public final ITestBean testBean3 = null;
|
||||
public final @Nullable ITestBean testBean3 = null;
|
||||
|
||||
private T nestedTestBean;
|
||||
private @Nullable T nestedTestBean;
|
||||
|
||||
private ITestBean testBean4;
|
||||
private @Nullable ITestBean testBean4;
|
||||
|
||||
protected BeanFactory beanFactory;
|
||||
protected @Nullable BeanFactory beanFactory;
|
||||
|
||||
public boolean baseInjected = false;
|
||||
|
||||
@@ -2772,18 +2776,18 @@ class AutowiredAnnotationBeanPostProcessorTests {
|
||||
|
||||
@Override
|
||||
@Autowired
|
||||
public void setTestBean2(TestBean testBean2) {
|
||||
public void setTestBean2(@Nullable TestBean testBean2) {
|
||||
this.testBean2 = testBean2;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private void inject(ITestBean testBean4, T nestedTestBean) {
|
||||
private void inject(@Nullable ITestBean testBean4, @Nullable T nestedTestBean) {
|
||||
this.testBean4 = testBean4;
|
||||
this.nestedTestBean = nestedTestBean;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private void inject(ITestBean testBean4) {
|
||||
private void inject(@Nullable ITestBean testBean4) {
|
||||
this.baseInjected = true;
|
||||
}
|
||||
|
||||
@@ -2793,11 +2797,11 @@ class AutowiredAnnotationBeanPostProcessorTests {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
public ITestBean getTestBean3() {
|
||||
public @Nullable ITestBean getTestBean3() {
|
||||
return this.testBean3;
|
||||
}
|
||||
|
||||
public ITestBean getTestBean4() {
|
||||
public @Nullable ITestBean getTestBean4() {
|
||||
return this.testBean4;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user