Skip to content

Commit

Permalink
ConfigurationClassUtils should check bean methods in super classes
Browse files Browse the repository at this point in the history
  • Loading branch information
quaff committed May 11, 2023
1 parent 993a69d commit bc146f1
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 7 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

0 comments on commit bc146f1

Please sign in to comment.