Skip to content

Commit cdfe089

Browse files
committed
Merge branch '6.2.x'
2 parents 59299b9 + d9e261a commit cdfe089

File tree

4 files changed

+77
-5
lines changed

4 files changed

+77
-5
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1656,7 +1656,12 @@ else if (descriptor.supportsLazyResolution()) {
16561656
if (autowiredBeanNames != null) {
16571657
autowiredBeanNames.add(dependencyName);
16581658
}
1659+
boolean preExisting = containsSingleton(dependencyName);
16591660
Object dependencyBean = getBean(dependencyName);
1661+
if (preExisting && dependencyBean instanceof NullBean) {
1662+
// for backwards compatibility with addCandidateEntry in the regular code path
1663+
dependencyBean = null;
1664+
}
16601665
return resolveInstance(dependencyBean, descriptor, type, dependencyName);
16611666
}
16621667
}
@@ -1736,7 +1741,6 @@ else if (descriptor.supportsLazyResolution()) {
17361741
throw new BeanNotOfRequiredTypeException(name, type, candidate.getClass());
17371742
}
17381743
return result;
1739-
17401744
}
17411745

17421746
private @Nullable Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,

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

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -960,11 +960,34 @@ void constructorResourceInjectionWithMultipleCandidates() {
960960
@Test
961961
void constructorResourceInjectionWithNoCandidatesAndNoFallback() {
962962
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ConstructorWithoutFallbackBean.class));
963+
963964
assertThatExceptionOfType(UnsatisfiedDependencyException.class)
964965
.isThrownBy(() -> bf.getBean("annotatedBean"))
965966
.satisfies(methodParameterDeclaredOn(ConstructorWithoutFallbackBean.class));
966967
}
967968

969+
@Test
970+
void constructorResourceInjectionWithCandidateAndNoFallback() {
971+
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ConstructorWithoutFallbackBean.class));
972+
RootBeanDefinition tb = new RootBeanDefinition(NullFactoryMethods.class);
973+
tb.setFactoryMethodName("createTestBean");
974+
bf.registerBeanDefinition("testBean", tb);
975+
976+
bf.getBean("testBean");
977+
assertThat(bf.getBean("annotatedBean", ConstructorWithoutFallbackBean.class).getTestBean3()).isNull();
978+
}
979+
980+
@Test
981+
void constructorResourceInjectionWithNameMatchingCandidateAndNoFallback() {
982+
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ConstructorWithoutFallbackBean.class));
983+
RootBeanDefinition tb = new RootBeanDefinition(NullFactoryMethods.class);
984+
tb.setFactoryMethodName("createTestBean");
985+
bf.registerBeanDefinition("testBean3", tb);
986+
987+
bf.getBean("testBean3");
988+
assertThat(bf.getBean("annotatedBean", ConstructorWithoutFallbackBean.class).getTestBean3()).isNull();
989+
}
990+
968991
@Test
969992
void constructorResourceInjectionWithSometimesNullBeanEarly() {
970993
RootBeanDefinition bd = new RootBeanDefinition(ConstructorWithNullableArgument.class);
@@ -1193,6 +1216,7 @@ void singleConstructorInjectionWithEmptyCollectionAsNull() {
11931216
@Test
11941217
void singleConstructorInjectionWithMissingDependency() {
11951218
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SingleConstructorOptionalCollectionBean.class));
1219+
11961220
assertThatExceptionOfType(UnsatisfiedDependencyException.class)
11971221
.isThrownBy(() -> bf.getBean("annotatedBean"));
11981222
}
@@ -1203,6 +1227,7 @@ void singleConstructorInjectionWithNullDependency() {
12031227
RootBeanDefinition tb = new RootBeanDefinition(NullFactoryMethods.class);
12041228
tb.setFactoryMethodName("createTestBean");
12051229
bf.registerBeanDefinition("testBean", tb);
1230+
12061231
assertThatExceptionOfType(UnsatisfiedDependencyException.class)
12071232
.isThrownBy(() -> bf.getBean("annotatedBean"));
12081233
}
@@ -3060,7 +3085,6 @@ public static class ConstructorWithoutFallbackBean {
30603085

30613086
protected ITestBean testBean3;
30623087

3063-
@Autowired(required = false)
30643088
public ConstructorWithoutFallbackBean(ITestBean testBean3) {
30653089
this.testBean3 = testBean3;
30663090
}
@@ -3075,7 +3099,6 @@ public static class ConstructorWithNullableArgument {
30753099

30763100
protected ITestBean testBean3;
30773101

3078-
@Autowired(required = false)
30793102
public ConstructorWithNullableArgument(@Nullable ITestBean testBean3) {
30803103
this.testBean3 = testBean3;
30813104
}

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.context.annotation;
1818

19+
import java.lang.reflect.Constructor;
1920
import java.lang.reflect.Field;
2021
import java.lang.reflect.Method;
2122
import java.lang.reflect.Modifier;
@@ -139,14 +140,20 @@ public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader)
139140
}
140141

141142
/**
142-
* Checks whether the given config class relies on package visibility,
143-
* either for the class itself or for any of its {@code @Bean} methods.
143+
* Checks whether the given config class relies on package visibility, either for
144+
* the class and any of its constructors or for any of its {@code @Bean} methods.
144145
*/
145146
private boolean reliesOnPackageVisibility(Class<?> configSuperClass) {
146147
int mod = configSuperClass.getModifiers();
147148
if (!Modifier.isPublic(mod) && !Modifier.isProtected(mod)) {
148149
return true;
149150
}
151+
for (Constructor<?> ctor : configSuperClass.getDeclaredConstructors()) {
152+
mod = ctor.getModifiers();
153+
if (!Modifier.isPublic(mod) && !Modifier.isProtected(mod)) {
154+
return true;
155+
}
156+
}
150157
for (Method method : ReflectionUtils.getDeclaredMethods(configSuperClass)) {
151158
if (BeanAnnotationHelper.isBeanAnnotated(method)) {
152159
mod = method.getModifiers();

spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassEnhancerTests.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,31 @@ void withNonPublicClass() {
104104
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
105105
}
106106

107+
@Test
108+
void withNonPublicConstructor() {
109+
ConfigurationClassEnhancer configurationClassEnhancer = new ConfigurationClassEnhancer();
110+
111+
ClassLoader classLoader = new URLClassLoader(new URL[0], getClass().getClassLoader());
112+
Class<?> enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicConstructor.class, classLoader);
113+
assertThat(MyConfigWithNonPublicConstructor.class).isAssignableFrom(enhancedClass);
114+
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
115+
116+
classLoader = new OverridingClassLoader(getClass().getClassLoader());
117+
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicConstructor.class, classLoader);
118+
assertThat(MyConfigWithNonPublicConstructor.class).isAssignableFrom(enhancedClass);
119+
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
120+
121+
classLoader = new CustomSmartClassLoader(getClass().getClassLoader());
122+
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicConstructor.class, classLoader);
123+
assertThat(MyConfigWithNonPublicConstructor.class).isAssignableFrom(enhancedClass);
124+
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
125+
126+
classLoader = new BasicSmartClassLoader(getClass().getClassLoader());
127+
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicConstructor.class, classLoader);
128+
assertThat(MyConfigWithNonPublicConstructor.class).isAssignableFrom(enhancedClass);
129+
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
130+
}
131+
107132
@Test
108133
void withNonPublicMethod() {
109134
ConfigurationClassEnhancer configurationClassEnhancer = new ConfigurationClassEnhancer();
@@ -160,6 +185,19 @@ public String myBean() {
160185
}
161186

162187

188+
@Configuration
189+
public static class MyConfigWithNonPublicConstructor {
190+
191+
MyConfigWithNonPublicConstructor() {
192+
}
193+
194+
@Bean
195+
public String myBean() {
196+
return "bean";
197+
}
198+
}
199+
200+
163201
@Configuration
164202
public static class MyConfigWithNonPublicMethod {
165203

0 commit comments

Comments
 (0)