diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java index 515c78c91a3..ad6e2fab124 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java @@ -81,6 +81,7 @@ import org.springframework.util.ClassUtils; * @author Chris Beams * @author Juergen Hoeller * @author Phillip Webb + * @author Sam Brannen * @since 3.0 */ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, @@ -376,21 +377,30 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo for (String beanName : beanFactory.getBeanDefinitionNames()) { BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName); Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE); + AnnotationMetadata annotationMetadata = null; MethodMetadata methodMetadata = null; if (beanDef instanceof AnnotatedBeanDefinition) { - methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata(); + AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDef; + annotationMetadata = annotatedBeanDefinition.getMetadata(); + methodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata(); } if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) { // Configuration class (full or lite) or a configuration-derived @Bean method - // -> resolve bean class at this point... + // -> eagerly resolve bean class at this point, unless it's a 'lite' configuration + // or component class without @Bean methods. AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef; if (!abd.hasBeanClass()) { - try { - abd.resolveBeanClass(this.beanClassLoader); - } - catch (Throwable ex) { - throw new IllegalStateException( - "Cannot load configuration class: " + beanDef.getBeanClassName(), ex); + boolean liteConfigurationCandidateWithoutBeanMethods = + (ConfigurationClassUtils.CONFIGURATION_CLASS_LITE.equals(configClassAttr) && + annotationMetadata != null && !ConfigurationClassUtils.hasBeanMethods(annotationMetadata)); + if (!liteConfigurationCandidateWithoutBeanMethods) { + try { + abd.resolveBeanClass(this.beanClassLoader); + } + catch (Throwable ex) { + throw new IllegalStateException( + "Cannot load configuration class: " + beanDef.getBeanClassName(), ex); + } } } } diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java index 3758084c319..da377b13fd3 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -46,6 +46,7 @@ import org.springframework.stereotype.Component; * * @author Chris Beams * @author Juergen Hoeller + * @author Sam Brannen * @since 3.1 */ abstract class ConfigurationClassUtils { @@ -162,6 +163,10 @@ abstract class ConfigurationClassUtils { } // Finally, let's look for @Bean methods... + return hasBeanMethods(metadata); + } + + static boolean hasBeanMethods(AnnotationMetadata metadata) { try { return metadata.hasAnnotatedMethods(Bean.class.getName()); }