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 @@ -1656,7 +1656,12 @@ 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);
}
}
@ -1736,7 +1741,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto @@ -1736,7 +1741,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
throw new BeanNotOfRequiredTypeException(name, type, candidate.getClass());
}
return result;
}
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 { @@ -960,11 +960,34 @@ class AutowiredAnnotationBeanPostProcessorTests {
@Test
void constructorResourceInjectionWithNoCandidatesAndNoFallback() {
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ConstructorWithoutFallbackBean.class));
assertThatExceptionOfType(UnsatisfiedDependencyException.class)
.isThrownBy(() -> bf.getBean("annotatedBean"))
.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
void constructorResourceInjectionWithSometimesNullBeanEarly() {
RootBeanDefinition bd = new RootBeanDefinition(ConstructorWithNullableArgument.class);
@ -1193,6 +1216,7 @@ class AutowiredAnnotationBeanPostProcessorTests { @@ -1193,6 +1216,7 @@ class AutowiredAnnotationBeanPostProcessorTests {
@Test
void singleConstructorInjectionWithMissingDependency() {
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SingleConstructorOptionalCollectionBean.class));
assertThatExceptionOfType(UnsatisfiedDependencyException.class)
.isThrownBy(() -> bf.getBean("annotatedBean"));
}
@ -1203,6 +1227,7 @@ class AutowiredAnnotationBeanPostProcessorTests { @@ -1203,6 +1227,7 @@ class AutowiredAnnotationBeanPostProcessorTests {
RootBeanDefinition tb = new RootBeanDefinition(NullFactoryMethods.class);
tb.setFactoryMethodName("createTestBean");
bf.registerBeanDefinition("testBean", tb);
assertThatExceptionOfType(UnsatisfiedDependencyException.class)
.isThrownBy(() -> bf.getBean("annotatedBean"));
}
@ -3060,7 +3085,6 @@ class AutowiredAnnotationBeanPostProcessorTests { @@ -3060,7 +3085,6 @@ class AutowiredAnnotationBeanPostProcessorTests {
protected ITestBean testBean3;
@Autowired(required = false)
public ConstructorWithoutFallbackBean(ITestBean testBean3) {
this.testBean3 = testBean3;
}
@ -3075,7 +3099,6 @@ class AutowiredAnnotationBeanPostProcessorTests { @@ -3075,7 +3099,6 @@ class AutowiredAnnotationBeanPostProcessorTests {
protected ITestBean testBean3;
@Autowired(required = false)
public ConstructorWithNullableArgument(@Nullable ITestBean testBean3) {
this.testBean3 = testBean3;
}

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

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

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

@ -104,6 +104,31 @@ class ConfigurationClassEnhancerTests { @@ -104,6 +104,31 @@ class ConfigurationClassEnhancerTests {
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
void withNonPublicMethod() {
ConfigurationClassEnhancer configurationClassEnhancer = new ConfigurationClassEnhancer();
@ -160,6 +185,19 @@ class ConfigurationClassEnhancerTests { @@ -160,6 +185,19 @@ class ConfigurationClassEnhancerTests {
}
@Configuration
public static class MyConfigWithNonPublicConstructor {
MyConfigWithNonPublicConstructor() {
}
@Bean
public String myBean() {
return "bean";
}
}
@Configuration
public static class MyConfigWithNonPublicMethod {

Loading…
Cancel
Save