Skip to content

Commit

Permalink
@bean methods should be detected even no one declared locally with li…
Browse files Browse the repository at this point in the history
…te mode

ConfigurationClassUtils should check bean methods in super classes also

Fix spring-projectsGH-30449
  • Loading branch information
quaff committed May 15, 2023
1 parent 993a69d commit 09218a3
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 8 deletions.
Expand Up @@ -349,7 +349,7 @@ private void processMemberClasses(ConfigurationClass configClass, SourceClass so
if (!memberClasses.isEmpty()) {
List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
for (SourceClass memberClass : memberClasses) {
if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata(), this.metadataReaderFactory) &&
!memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
candidates.add(memberClass);
}
Expand Down
Expand Up @@ -490,7 +490,7 @@ public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFact
// or component class without @Bean methods.
boolean liteConfigurationCandidateWithoutBeanMethods =
(ConfigurationClassUtils.CONFIGURATION_CLASS_LITE.equals(configClassAttr) &&
annotationMetadata != null && !ConfigurationClassUtils.hasBeanMethods(annotationMetadata));
annotationMetadata != null && !ConfigurationClassUtils.hasBeanMethods(annotationMetadata, this.metadataReaderFactory));
if (!liteConfigurationCandidateWithoutBeanMethods) {
try {
abd.resolveBeanClass(this.beanClassLoader);
Expand Down
Expand Up @@ -36,6 +36,7 @@
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.lang.Nullable;
Expand All @@ -48,6 +49,7 @@
* @author Juergen Hoeller
* @author Sam Brannen
* @author Stephane Nicoll
* @author Yanming Zhou
* @since 6.0
*/
public abstract class ConfigurationClassUtils {
Expand All @@ -71,6 +73,7 @@ public abstract class ConfigurationClassUtils {
Import.class.getName(),
ImportResource.class.getName());

private static final MetadataReaderFactory defaultMetadataReaderFactory = new CachingMetadataReaderFactory();

/**
* Initialize a configuration class proxy for the specified class.
Expand Down Expand Up @@ -136,7 +139,7 @@ else if (beanDef instanceof AbstractBeanDefinition abstractBd && abstractBd.hasB
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
else if (config != null || isConfigurationCandidate(metadata)) {
else if (config != null || isConfigurationCandidate(metadata, metadataReaderFactory)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
Expand All @@ -160,6 +163,18 @@ else if (config != null || isConfigurationCandidate(metadata)) {
* configuration class processing; {@code false} otherwise
*/
static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
return isConfigurationCandidate(metadata, defaultMetadataReaderFactory);
}

/**
* Check the given metadata for a configuration class candidate
* (or nested component class declared within a configuration/component class).
* @param metadata the metadata of the annotated class
* @param metadataReaderFactory the current factory in use by the caller
* @return {@code true} if the given class is to be registered for
* configuration class processing; {@code false} otherwise
*/
static boolean isConfigurationCandidate(AnnotationMetadata metadata, MetadataReaderFactory metadataReaderFactory) {
// Do not consider an interface or an annotation...
if (metadata.isInterface()) {
return false;
Expand All @@ -173,19 +188,30 @@ static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
}

// Finally, let's look for @Bean methods...
return hasBeanMethods(metadata);
return hasBeanMethods(metadata, metadataReaderFactory);
}

static boolean hasBeanMethods(AnnotationMetadata metadata) {
static boolean hasBeanMethods(AnnotationMetadata metadata, MetadataReaderFactory metadataReaderFactory) {
try {
return metadata.hasAnnotatedMethods(Bean.class.getName());
AnnotationMetadata md = metadata;
while (true) {
if (md.hasAnnotatedMethods(Bean.class.getName())) {
return true;
}
if (md.hasSuperClass()) {
md = metadataReaderFactory.getMetadataReader(md.getSuperClassName()).getAnnotationMetadata();
}
else {
break;
}
}
}
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
}
return false;
}
return false;
}

/**
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -69,11 +69,13 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.assertj.core.api.Assertions.assertThatNoException;

/**
* @author Chris Beams
* @author Juergen Hoeller
* @author Sam Brannen
* @author Yanming Zhou
*/
class ConfigurationClassPostProcessorTests {

Expand Down Expand Up @@ -1125,6 +1127,13 @@ void testBeanDefinitionRegistryPostProcessorConfig() {
}


@Test
void testBeanNotDeclaredLocallyWithLiteMode() { // GH-30449
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(LiteConfiguration.class);
assertThatNoException().isThrownBy(() -> ctx.getBean("myTestBean"));
ctx.close();
}

// -------------------------------------------------------------------------

@Configuration
Expand Down Expand Up @@ -2038,4 +2047,16 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
}
}

static class LiteConfiguration extends BaseLiteConfiguration {

}

static class BaseLiteConfiguration {
@Bean
TestBean myTestBean() {
return new TestBean();
}

}

}

0 comments on commit 09218a3

Please sign in to comment.