Merge branch '6.2.x'
This commit is contained in:
@@ -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
|
||||
throw new BeanNotOfRequiredTypeException(name, type, candidate.getClass());
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private @Nullable Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
|
||||
|
||||
@@ -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 {
|
||||
@Test
|
||||
void singleConstructorInjectionWithMissingDependency() {
|
||||
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(SingleConstructorOptionalCollectionBean.class));
|
||||
|
||||
assertThatExceptionOfType(UnsatisfiedDependencyException.class)
|
||||
.isThrownBy(() -> bf.getBean("annotatedBean"));
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
protected ITestBean testBean3;
|
||||
|
||||
@Autowired(required = false)
|
||||
public ConstructorWithoutFallbackBean(ITestBean testBean3) {
|
||||
this.testBean3 = testBean3;
|
||||
}
|
||||
@@ -3075,7 +3099,6 @@ class AutowiredAnnotationBeanPostProcessorTests {
|
||||
|
||||
protected ITestBean testBean3;
|
||||
|
||||
@Autowired(required = false)
|
||||
public ConstructorWithNullableArgument(@Nullable ITestBean testBean3) {
|
||||
this.testBean3 = testBean3;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
public static class MyConfigWithNonPublicConstructor {
|
||||
|
||||
MyConfigWithNonPublicConstructor() {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public String myBean() {
|
||||
return "bean";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
public static class MyConfigWithNonPublicMethod {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user