@@ -90,40 +90,37 @@ class ConfigurationClassParser {
90
90
91
91
private static final Comparator <DeferredImportSelectorHolder > DEFERRED_IMPORT_COMPARATOR =
92
92
new Comparator <ConfigurationClassParser .DeferredImportSelectorHolder >() {
93
- @ Override
94
- public int compare (DeferredImportSelectorHolder o1 ,
95
- DeferredImportSelectorHolder o2 ) {
96
- return AnnotationAwareOrderComparator .INSTANCE .compare (
97
- o1 .getImportSelector (), o2 .getImportSelector ());
98
- }
99
- };
93
+ @ Override
94
+ public int compare (DeferredImportSelectorHolder o1 , DeferredImportSelectorHolder o2 ) {
95
+ return AnnotationAwareOrderComparator .INSTANCE .compare (o1 .getImportSelector (), o2 .getImportSelector ());
96
+ }
97
+ };
98
+
100
99
101
100
private final MetadataReaderFactory metadataReaderFactory ;
102
101
103
102
private final ProblemReporter problemReporter ;
104
103
105
- private final ImportStack importStack = new ImportStack ();
106
-
107
- private final Set <String > knownSuperclasses = new LinkedHashSet <String >();
108
-
109
- private final Set <ConfigurationClass > configurationClasses =
110
- new LinkedHashSet <ConfigurationClass >();
111
-
112
- private final Stack <PropertySource <?>> propertySources =
113
- new Stack <PropertySource <?>>();
114
-
115
104
private final Environment environment ;
116
105
117
106
private final ResourceLoader resourceLoader ;
118
107
119
108
private final BeanDefinitionRegistry registry ;
120
109
110
+ private final BeanNameGenerator beanNameGenerator ;
111
+
121
112
private final ComponentScanAnnotationParser componentScanParser ;
122
113
123
- private final BeanNameGenerator beanNameGenerator ;
114
+ private final Set <ConfigurationClass > configurationClasses = new LinkedHashSet <ConfigurationClass >();
115
+
116
+ private final Map <String , ConfigurationClass > knownSuperclasses = new HashMap <String , ConfigurationClass >();
117
+
118
+ private final Stack <PropertySource <?>> propertySources = new Stack <PropertySource <?>>();
119
+
120
+ private final ImportStack importStack = new ImportStack ();
121
+
122
+ private final List <DeferredImportSelectorHolder > deferredImportSelectors = new LinkedList <DeferredImportSelectorHolder >();
124
123
125
- private final List <DeferredImportSelectorHolder > deferredImportSelectors =
126
- new LinkedList <DeferredImportSelectorHolder >();
127
124
128
125
/**
129
126
* Create a new {@link ConfigurationClassParser} instance that will be used
@@ -143,6 +140,7 @@ public ConfigurationClassParser(MetadataReaderFactory metadataReaderFactory,
143
140
resourceLoader , environment , componentScanBeanNameGenerator , registry );
144
141
}
145
142
143
+
146
144
public void parse (Set <BeanDefinitionHolder > configCandidates ) {
147
145
for (BeanDefinitionHolder holder : configCandidates ) {
148
146
BeanDefinition bd = holder .getBeanDefinition ();
@@ -177,35 +175,39 @@ public void parse(String className, String beanName) throws IOException {
177
175
* @param clazz the Class to parse
178
176
* @param beanName must not be null (as of Spring 3.1.1)
179
177
*/
180
- protected void parse (Class <?> clazz , String beanName ) throws IOException {
178
+ public void parse (Class <?> clazz , String beanName ) throws IOException {
181
179
processConfigurationClass (new ConfigurationClass (clazz , beanName ));
182
180
}
183
181
184
- protected void processConfigurationClass (ConfigurationClass configClass ) throws IOException {
185
- AnnotationMetadata metadata = configClass .getMetadata ();
186
182
187
- if ( ConditionalAnnotationHelper . shouldSkip ( configClass , this . registry ,
188
- this .environment , this .beanNameGenerator )) {
183
+ protected void processConfigurationClass ( ConfigurationClass configClass ) throws IOException {
184
+ if ( ConditionalAnnotationHelper . shouldSkip ( configClass , this . registry , this .environment , this .beanNameGenerator )) {
189
185
return ;
190
186
}
191
187
192
- // recursively process the configuration class and its superclass hierarchy
193
- do {
194
- metadata = doProcessConfigurationClass (configClass , metadata );
195
- }
196
- while (metadata != null );
197
-
198
188
if (this .configurationClasses .contains (configClass ) && configClass .getBeanName () != null ) {
199
189
// Explicit bean definition found, probably replacing an import.
200
190
// Let's remove the old one and go with the new one.
201
191
this .configurationClasses .remove (configClass );
192
+ for (Iterator <ConfigurationClass > it = this .knownSuperclasses .values ().iterator (); it .hasNext ();) {
193
+ if (configClass .equals (it .next ())) {
194
+ it .remove ();
195
+ }
196
+ }
202
197
}
203
198
199
+ // Recursively process the configuration class and its superclass hierarchy.
200
+ AnnotationMetadata metadata = configClass .getMetadata ();
201
+ do {
202
+ metadata = doProcessConfigurationClass (configClass , metadata );
203
+ }
204
+ while (metadata != null );
205
+
204
206
this .configurationClasses .add (configClass );
205
207
}
206
208
207
209
/**
208
- * @return annotation metadata of superclass, null if none found or previously processed
210
+ * @return annotation metadata of superclass, {@code null} if none found or previously processed
209
211
*/
210
212
protected AnnotationMetadata doProcessConfigurationClass (
211
213
ConfigurationClass configClass , AnnotationMetadata metadata ) throws IOException {
@@ -219,7 +221,7 @@ protected AnnotationMetadata doProcessConfigurationClass(
219
221
processPropertySource (propertySource );
220
222
}
221
223
222
- // process any @ComponentScan annotions
224
+ // process any @ComponentScan annotations
223
225
AnnotationAttributes componentScan = attributesFor (metadata , ComponentScan .class );
224
226
if (componentScan != null ) {
225
227
// the config class is annotated with @ComponentScan -> perform the scan immediately
@@ -235,7 +237,6 @@ protected AnnotationMetadata doProcessConfigurationClass(
235
237
}
236
238
237
239
// process any @Import annotations
238
-
239
240
Set <Object > imports = new LinkedHashSet <Object >();
240
241
Set <Object > visited = new LinkedHashSet <Object >();
241
242
collectImports (metadata , imports , visited );
@@ -262,7 +263,8 @@ protected AnnotationMetadata doProcessConfigurationClass(
262
263
// process superclass, if any
263
264
if (metadata .hasSuperClass ()) {
264
265
String superclass = metadata .getSuperClassName ();
265
- if (this .knownSuperclasses .add (superclass )) {
266
+ if (!this .knownSuperclasses .containsKey (superclass )) {
267
+ this .knownSuperclasses .put (superclass , configClass );
266
268
// superclass found, return its annotation metadata and recurse
267
269
if (metadata instanceof StandardAnnotationMetadata ) {
268
270
Class <?> clazz = ((StandardAnnotationMetadata ) metadata ).getIntrospectedClass ();
@@ -416,7 +418,7 @@ private void processDeferredImportSelectors() {
416
418
throw new BeanDefinitionStoreException ("Failed to load bean class: " , ex );
417
419
}
418
420
}
419
- deferredImportSelectors .clear ();
421
+ this . deferredImportSelectors .clear ();
420
422
}
421
423
422
424
private void processImport (ConfigurationClass configClass , Collection <?> classesToImport , boolean checkForCircularImports ) throws IOException {
@@ -435,9 +437,9 @@ private void processImport(ConfigurationClass configClass, Collection<?> classes
435
437
ImportSelector selector = BeanUtils .instantiateClass (candidateClass , ImportSelector .class );
436
438
invokeAwareMethods (selector );
437
439
if (selector instanceof DeferredImportSelector ) {
438
- this .deferredImportSelectors .add (new DeferredImportSelectorHolder (
439
- configClass , ( DeferredImportSelector ) selector ));
440
- } else {
440
+ this .deferredImportSelectors .add (new DeferredImportSelectorHolder (configClass , ( DeferredImportSelector ) selector ));
441
+ }
442
+ else {
441
443
processImport (configClass , Arrays .asList (selector .selectImports (importingClassMetadata )), false );
442
444
}
443
445
}
@@ -516,7 +518,7 @@ public Stack<PropertySource<?>> getPropertySources() {
516
518
return this .propertySources ;
517
519
}
518
520
519
- public ImportRegistry getImportRegistry () {
521
+ ImportRegistry getImportRegistry () {
520
522
return this .importStack ;
521
523
}
522
524
@@ -582,38 +584,39 @@ public String toString() {
582
584
}
583
585
584
586
585
- /**
586
- * {@link Problem} registered upon detection of a circular {@link Import}.
587
- */
588
- private static class CircularImportProblem extends Problem {
589
-
590
- public CircularImportProblem (ConfigurationClass attemptedImport , Stack <ConfigurationClass > importStack , AnnotationMetadata metadata ) {
591
- super (String .format ("A circular @Import has been detected: " +
592
- "Illegal attempt by @Configuration class '%s' to import class '%s' as '%s' is " +
593
- "already present in the current import stack [%s]" , importStack .peek ().getSimpleName (),
594
- attemptedImport .getSimpleName (), attemptedImport .getSimpleName (), importStack ),
595
- new Location (importStack .peek ().getResource (), metadata ));
596
- }
597
- }
598
-
599
-
600
587
private static class DeferredImportSelectorHolder {
601
588
602
- private ConfigurationClass configurationClass ;
589
+ private final ConfigurationClass configurationClass ;
603
590
604
- private DeferredImportSelector importSelector ;
591
+ private final DeferredImportSelector importSelector ;
605
592
606
593
public DeferredImportSelectorHolder (ConfigurationClass configurationClass , DeferredImportSelector importSelector ) {
607
594
this .configurationClass = configurationClass ;
608
595
this .importSelector = importSelector ;
609
596
}
610
597
611
598
public ConfigurationClass getConfigurationClass () {
612
- return configurationClass ;
599
+ return this . configurationClass ;
613
600
}
614
601
615
602
public DeferredImportSelector getImportSelector () {
616
- return importSelector ;
603
+ return this . importSelector ;
617
604
}
618
605
}
606
+
607
+
608
+ /**
609
+ * {@link Problem} registered upon detection of a circular {@link Import}.
610
+ */
611
+ private static class CircularImportProblem extends Problem {
612
+
613
+ public CircularImportProblem (ConfigurationClass attemptedImport , Stack <ConfigurationClass > importStack , AnnotationMetadata metadata ) {
614
+ super (String .format ("A circular @Import has been detected: " +
615
+ "Illegal attempt by @Configuration class '%s' to import class '%s' as '%s' is " +
616
+ "already present in the current import stack [%s]" , importStack .peek ().getSimpleName (),
617
+ attemptedImport .getSimpleName (), attemptedImport .getSimpleName (), importStack ),
618
+ new Location (importStack .peek ().getResource (), metadata ));
619
+ }
620
+ }
621
+
619
622
}
0 commit comments