Browse Source

Merge branch '6.2.x'

pull/34716/head
Juergen Hoeller 10 months ago
parent
commit
cdfe0895f9
  1. 6
      spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
  2. 27
      spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java
  3. 11
      spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java
  4. 38
      spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassEnhancerTests.java

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

@ -1656,7 +1656,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (autowiredBeanNames != null) { if (autowiredBeanNames != null) {
autowiredBeanNames.add(dependencyName); autowiredBeanNames.add(dependencyName);
} }
boolean preExisting = containsSingleton(dependencyName);
Object dependencyBean = getBean(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); return resolveInstance(dependencyBean, descriptor, type, dependencyName);
} }
} }
@ -1736,7 +1741,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
throw new BeanNotOfRequiredTypeException(name, type, candidate.getClass()); throw new BeanNotOfRequiredTypeException(name, type, candidate.getClass());
} }
return result; return result;
} }
private @Nullable Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName, private @Nullable Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,

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

@ -960,11 +960,34 @@ class AutowiredAnnotationBeanPostProcessorTests {
@Test @Test
void constructorResourceInjectionWithNoCandidatesAndNoFallback() { void constructorResourceInjectionWithNoCandidatesAndNoFallback() {
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ConstructorWithoutFallbackBean.class)); bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ConstructorWithoutFallbackBean.class));
assertThatExceptionOfType(UnsatisfiedDependencyException.class) assertThatExceptionOfType(UnsatisfiedDependencyException.class)
.isThrownBy(() -> bf.getBean("annotatedBean")) .isThrownBy(() -> bf.getBean("annotatedBean"))
.satisfies(methodParameterDeclaredOn(ConstructorWithoutFallbackBean.class)); .satisfies(methodParameterDeclaredOn(ConstructorWithoutFallbackBean.class));
} }
@Test
void constructorResourceInjectionWithCandidateAndNoFallback() {
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ConstructorWithoutFallbackBean.class));
RootBeanDefinition tb = new RootBeanDefinition(NullFactoryMethods.class);
tb.setFactoryMethodName("createTestBean");
bf.registerBeanDefinition("testBean", tb);
bf.getBean("testBean");
assertThat(bf.getBean("annotatedBean", ConstructorWithoutFallbackBean.class).getTestBean3()).isNull();
}
@Test
void constructorResourceInjectionWithNameMatchingCandidateAndNoFallback() {
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ConstructorWithoutFallbackBean.class));
RootBeanDefinition tb = new RootBeanDefinition(NullFactoryMethods.class);
tb.setFactoryMethodName("createTestBean");
bf.registerBeanDefinition("testBean3", tb);
bf.getBean("testBean3");
assertThat(bf.getBean("annotatedBean", ConstructorWithoutFallbackBean.class).getTestBean3()).isNull();
}
@Test @Test
void constructorResourceInjectionWithSometimesNullBeanEarly() { void constructorResourceInjectionWithSometimesNullBeanEarly() {
RootBeanDefinition bd = new RootBeanDefinition(ConstructorWithNullableArgument.class); RootBeanDefinition bd = new RootBeanDefinition(ConstructorWithNullableArgument.class);
@ -1193,6 +1216,7 @@ class AutowiredAnnotationBeanPostProcessorTests {
@Test @Test
void singleConstructorInjectionWithMissingDependency() { void singleConstructorInjectionWithMissingDependency() {
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SingleConstructorOptionalCollectionBean.class)); bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SingleConstructorOptionalCollectionBean.class));
assertThatExceptionOfType(UnsatisfiedDependencyException.class) assertThatExceptionOfType(UnsatisfiedDependencyException.class)
.isThrownBy(() -> bf.getBean("annotatedBean")); .isThrownBy(() -> bf.getBean("annotatedBean"));
} }
@ -1203,6 +1227,7 @@ class AutowiredAnnotationBeanPostProcessorTests {
RootBeanDefinition tb = new RootBeanDefinition(NullFactoryMethods.class); RootBeanDefinition tb = new RootBeanDefinition(NullFactoryMethods.class);
tb.setFactoryMethodName("createTestBean"); tb.setFactoryMethodName("createTestBean");
bf.registerBeanDefinition("testBean", tb); bf.registerBeanDefinition("testBean", tb);
assertThatExceptionOfType(UnsatisfiedDependencyException.class) assertThatExceptionOfType(UnsatisfiedDependencyException.class)
.isThrownBy(() -> bf.getBean("annotatedBean")); .isThrownBy(() -> bf.getBean("annotatedBean"));
} }
@ -3060,7 +3085,6 @@ class AutowiredAnnotationBeanPostProcessorTests {
protected ITestBean testBean3; protected ITestBean testBean3;
@Autowired(required = false)
public ConstructorWithoutFallbackBean(ITestBean testBean3) { public ConstructorWithoutFallbackBean(ITestBean testBean3) {
this.testBean3 = testBean3; this.testBean3 = testBean3;
} }
@ -3075,7 +3099,6 @@ class AutowiredAnnotationBeanPostProcessorTests {
protected ITestBean testBean3; protected ITestBean testBean3;
@Autowired(required = false)
public ConstructorWithNullableArgument(@Nullable ITestBean testBean3) { public ConstructorWithNullableArgument(@Nullable ITestBean testBean3) {
this.testBean3 = testBean3; this.testBean3 = testBean3;
} }

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

@ -16,6 +16,7 @@
package org.springframework.context.annotation; package org.springframework.context.annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
@ -139,14 +140,20 @@ class ConfigurationClassEnhancer {
} }
/** /**
* Checks whether the given config class relies on package visibility, * Checks whether the given config class relies on package visibility, either for
* either for the class itself or for any of its {@code @Bean} methods. * the class and any of its constructors or for any of its {@code @Bean} methods.
*/ */
private boolean reliesOnPackageVisibility(Class<?> configSuperClass) { private boolean reliesOnPackageVisibility(Class<?> configSuperClass) {
int mod = configSuperClass.getModifiers(); int mod = configSuperClass.getModifiers();
if (!Modifier.isPublic(mod) && !Modifier.isProtected(mod)) { if (!Modifier.isPublic(mod) && !Modifier.isProtected(mod)) {
return true; return true;
} }
for (Constructor<?> ctor : configSuperClass.getDeclaredConstructors()) {
mod = ctor.getModifiers();
if (!Modifier.isPublic(mod) && !Modifier.isProtected(mod)) {
return true;
}
}
for (Method method : ReflectionUtils.getDeclaredMethods(configSuperClass)) { for (Method method : ReflectionUtils.getDeclaredMethods(configSuperClass)) {
if (BeanAnnotationHelper.isBeanAnnotated(method)) { if (BeanAnnotationHelper.isBeanAnnotated(method)) {
mod = method.getModifiers(); mod = method.getModifiers();

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

@ -104,6 +104,31 @@ class ConfigurationClassEnhancerTests {
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent()); assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
} }
@Test
void withNonPublicConstructor() {
ConfigurationClassEnhancer configurationClassEnhancer = new ConfigurationClassEnhancer();
ClassLoader classLoader = new URLClassLoader(new URL[0], getClass().getClassLoader());
Class<?> enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicConstructor.class, classLoader);
assertThat(MyConfigWithNonPublicConstructor.class).isAssignableFrom(enhancedClass);
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
classLoader = new OverridingClassLoader(getClass().getClassLoader());
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicConstructor.class, classLoader);
assertThat(MyConfigWithNonPublicConstructor.class).isAssignableFrom(enhancedClass);
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
classLoader = new CustomSmartClassLoader(getClass().getClassLoader());
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicConstructor.class, classLoader);
assertThat(MyConfigWithNonPublicConstructor.class).isAssignableFrom(enhancedClass);
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
classLoader = new BasicSmartClassLoader(getClass().getClassLoader());
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicConstructor.class, classLoader);
assertThat(MyConfigWithNonPublicConstructor.class).isAssignableFrom(enhancedClass);
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
}
@Test @Test
void withNonPublicMethod() { void withNonPublicMethod() {
ConfigurationClassEnhancer configurationClassEnhancer = new ConfigurationClassEnhancer(); ConfigurationClassEnhancer configurationClassEnhancer = new ConfigurationClassEnhancer();
@ -160,6 +185,19 @@ class ConfigurationClassEnhancerTests {
} }
@Configuration
public static class MyConfigWithNonPublicConstructor {
MyConfigWithNonPublicConstructor() {
}
@Bean
public String myBean() {
return "bean";
}
}
@Configuration @Configuration
public static class MyConfigWithNonPublicMethod { public static class MyConfigWithNonPublicMethod {

Loading…
Cancel
Save