11/*
2- * Copyright 2002-2023 the original author or authors.
2+ * Copyright 2002-2025 the original author or authors.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
8181 * any number of ConfigurationClass objects because one Configuration class may import
8282 * another using the {@link Import} annotation).
8383 *
84- * <p>This class helps separate the concern of parsing the structure of a Configuration
85- * class from the concern of registering BeanDefinition objects based on the content of
86- * that model (with the exception of {@code @ComponentScan} annotations which need to be
87- * registered immediately).
84+ * <p>This class helps separate the concern of parsing the structure of a Configuration class
85+ * from the concern of registering BeanDefinition objects based on the content of that model
86+ * (except {@code @ComponentScan} annotations which need to be registered immediately).
8887 *
8988 * <p>This ASM-based implementation avoids reflection and eager class loading in order to
9089 * interoperate effectively with lazy class loading in a Spring ApplicationContext.
@@ -161,14 +160,22 @@ public void parse(Set<BeanDefinitionHolder> configCandidates) {
161160 for (BeanDefinitionHolder holder : configCandidates ) {
162161 BeanDefinition bd = holder .getBeanDefinition ();
163162 try {
163+ ConfigurationClass configClass ;
164164 if (bd instanceof AnnotatedBeanDefinition annotatedBeanDef ) {
165- parse (annotatedBeanDef .getMetadata (), holder .getBeanName ());
165+ configClass = parse (annotatedBeanDef .getMetadata (), holder .getBeanName ());
166166 }
167167 else if (bd instanceof AbstractBeanDefinition abstractBeanDef && abstractBeanDef .hasBeanClass ()) {
168- parse (abstractBeanDef .getBeanClass (), holder .getBeanName ());
168+ configClass = parse (abstractBeanDef .getBeanClass (), holder .getBeanName ());
169169 }
170170 else {
171- parse (bd .getBeanClassName (), holder .getBeanName ());
171+ configClass = parse (bd .getBeanClassName (), holder .getBeanName ());
172+ }
173+
174+ // Downgrade to lite (no enhancement) in case of no instance-level @Bean methods.
175+ if (!configClass .hasNonStaticBeanMethods () && ConfigurationClassUtils .CONFIGURATION_CLASS_FULL .equals (
176+ bd .getAttribute (ConfigurationClassUtils .CONFIGURATION_CLASS_ATTRIBUTE ))) {
177+ bd .setAttribute (ConfigurationClassUtils .CONFIGURATION_CLASS_ATTRIBUTE ,
178+ ConfigurationClassUtils .CONFIGURATION_CLASS_LITE );
172179 }
173180 }
174181 catch (BeanDefinitionStoreException ex ) {
@@ -183,31 +190,37 @@ else if (bd instanceof AbstractBeanDefinition abstractBeanDef && abstractBeanDef
183190 this .deferredImportSelectorHandler .process ();
184191 }
185192
186- protected final void parse (@ Nullable String className , String beanName ) throws IOException {
187- Assert . notNull ( className , "No bean class name for configuration class bean definition" );
188- MetadataReader reader = this . metadataReaderFactory . getMetadataReader ( className );
189- processConfigurationClass ( new ConfigurationClass ( reader , beanName ), DEFAULT_EXCLUSION_FILTER ) ;
193+ final ConfigurationClass parse (AnnotationMetadata metadata , String beanName ) {
194+ ConfigurationClass configClass = new ConfigurationClass ( metadata , beanName );
195+ processConfigurationClass ( configClass , DEFAULT_EXCLUSION_FILTER );
196+ return configClass ;
190197 }
191198
192- protected final void parse (Class <?> clazz , String beanName ) throws IOException {
193- processConfigurationClass (new ConfigurationClass (clazz , beanName ), DEFAULT_EXCLUSION_FILTER );
199+ final ConfigurationClass parse (Class <?> clazz , String beanName ) {
200+ ConfigurationClass configClass = new ConfigurationClass (clazz , beanName );
201+ processConfigurationClass (configClass , DEFAULT_EXCLUSION_FILTER );
202+ return configClass ;
194203 }
195204
196- protected final void parse (AnnotationMetadata metadata , String beanName ) throws IOException {
197- processConfigurationClass (new ConfigurationClass (metadata , beanName ), DEFAULT_EXCLUSION_FILTER );
205+ final ConfigurationClass parse (@ Nullable String className , String beanName ) throws IOException {
206+ Assert .notNull (className , "No bean class name for configuration class bean definition" );
207+ MetadataReader reader = this .metadataReaderFactory .getMetadataReader (className );
208+ ConfigurationClass configClass = new ConfigurationClass (reader , beanName );
209+ processConfigurationClass (configClass , DEFAULT_EXCLUSION_FILTER );
210+ return configClass ;
198211 }
199212
200213 /**
201214 * Validate each {@link ConfigurationClass} object.
202215 * @see ConfigurationClass#validate
203216 */
204- public void validate () {
217+ void validate () {
205218 for (ConfigurationClass configClass : this .configurationClasses .keySet ()) {
206219 configClass .validate (this .problemReporter );
207220 }
208221 }
209222
210- public Set <ConfigurationClass > getConfigurationClasses () {
223+ Set <ConfigurationClass > getConfigurationClasses () {
211224 return this .configurationClasses .keySet ();
212225 }
213226
@@ -216,7 +229,7 @@ List<PropertySourceDescriptor> getPropertySourceDescriptors() {
216229 Collections .emptyList ());
217230 }
218231
219- protected void processConfigurationClass (ConfigurationClass configClass , Predicate <String > filter ) throws IOException {
232+ protected void processConfigurationClass (ConfigurationClass configClass , Predicate <String > filter ) {
220233 if (this .conditionEvaluator .shouldSkip (configClass .getMetadata (), ConfigurationPhase .PARSE_CONFIGURATION )) {
221234 return ;
222235 }
@@ -448,7 +461,7 @@ private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass)
448461
449462
450463 /**
451- * Returns {@code @Import} class , considering all meta-annotations.
464+ * Returns {@code @Import} classes , considering all meta-annotations.
452465 */
453466 private Set <SourceClass > getImports (SourceClass sourceClass ) throws IOException {
454467 Set <SourceClass > imports = new LinkedHashSet <>();
@@ -636,7 +649,7 @@ private static class ImportStack extends ArrayDeque<ConfigurationClass> implemen
636649
637650 private final MultiValueMap <String , AnnotationMetadata > imports = new LinkedMultiValueMap <>();
638651
639- public void registerImport (AnnotationMetadata importingClass , String importedClass ) {
652+ void registerImport (AnnotationMetadata importingClass , String importedClass ) {
640653 this .imports .add (importedClass , importingClass );
641654 }
642655
@@ -691,7 +704,7 @@ private class DeferredImportSelectorHandler {
691704 * @param configClass the source configuration class
692705 * @param importSelector the selector to handle
693706 */
694- public void handle (ConfigurationClass configClass , DeferredImportSelector importSelector ) {
707+ void handle (ConfigurationClass configClass , DeferredImportSelector importSelector ) {
695708 DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder (configClass , importSelector );
696709 if (this .deferredImportSelectors == null ) {
697710 DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler ();
@@ -703,7 +716,7 @@ public void handle(ConfigurationClass configClass, DeferredImportSelector import
703716 }
704717 }
705718
706- public void process () {
719+ void process () {
707720 List <DeferredImportSelectorHolder > deferredImports = this .deferredImportSelectors ;
708721 this .deferredImportSelectors = null ;
709722 try {
@@ -727,7 +740,7 @@ private class DeferredImportSelectorGroupingHandler {
727740
728741 private final Map <AnnotationMetadata , ConfigurationClass > configurationClasses = new HashMap <>();
729742
730- public void register (DeferredImportSelectorHolder deferredImport ) {
743+ void register (DeferredImportSelectorHolder deferredImport ) {
731744 Class <? extends Group > group = deferredImport .getImportSelector ().getImportGroup ();
732745 DeferredImportSelectorGrouping grouping = this .groupings .computeIfAbsent (
733746 (group != null ? group : deferredImport ),
@@ -737,7 +750,7 @@ public void register(DeferredImportSelectorHolder deferredImport) {
737750 deferredImport .getConfigurationClass ());
738751 }
739752
740- public void processGroupImports () {
753+ void processGroupImports () {
741754 for (DeferredImportSelectorGrouping grouping : this .groupings .values ()) {
742755 Predicate <String > exclusionFilter = grouping .getCandidateFilter ();
743756 grouping .getImports ().forEach (entry -> {
@@ -775,16 +788,16 @@ private static class DeferredImportSelectorHolder {
775788
776789 private final DeferredImportSelector importSelector ;
777790
778- public DeferredImportSelectorHolder (ConfigurationClass configClass , DeferredImportSelector selector ) {
791+ DeferredImportSelectorHolder (ConfigurationClass configClass , DeferredImportSelector selector ) {
779792 this .configurationClass = configClass ;
780793 this .importSelector = selector ;
781794 }
782795
783- public ConfigurationClass getConfigurationClass () {
796+ ConfigurationClass getConfigurationClass () {
784797 return this .configurationClass ;
785798 }
786799
787- public DeferredImportSelector getImportSelector () {
800+ DeferredImportSelector getImportSelector () {
788801 return this .importSelector ;
789802 }
790803 }
@@ -800,23 +813,23 @@ private static class DeferredImportSelectorGrouping {
800813 this .group = group ;
801814 }
802815
803- public void add (DeferredImportSelectorHolder deferredImport ) {
816+ void add (DeferredImportSelectorHolder deferredImport ) {
804817 this .deferredImports .add (deferredImport );
805818 }
806819
807820 /**
808821 * Return the imports defined by the group.
809822 * @return each import with its associated configuration class
810823 */
811- public Iterable <Group .Entry > getImports () {
824+ Iterable <Group .Entry > getImports () {
812825 for (DeferredImportSelectorHolder deferredImport : this .deferredImports ) {
813826 this .group .process (deferredImport .getConfigurationClass ().getMetadata (),
814827 deferredImport .getImportSelector ());
815828 }
816829 return this .group .selectImports ();
817830 }
818831
819- public Predicate <String > getCandidateFilter () {
832+ Predicate <String > getCandidateFilter () {
820833 Predicate <String > mergedFilter = DEFAULT_EXCLUSION_FILTER ;
821834 for (DeferredImportSelectorHolder deferredImport : this .deferredImports ) {
822835 Predicate <String > selectorFilter = deferredImport .getImportSelector ().getExclusionFilter ();
0 commit comments