|
|
|
|
@ -16,15 +16,16 @@
@@ -16,15 +16,16 @@
|
|
|
|
|
|
|
|
|
|
package org.springframework.context.annotation; |
|
|
|
|
|
|
|
|
|
import static org.springframework.context.annotation.MetadataUtils.attributesFor; |
|
|
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.lang.annotation.Annotation; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.Arrays; |
|
|
|
|
import java.util.Collections; |
|
|
|
|
import java.util.Comparator; |
|
|
|
|
import java.util.HashMap; |
|
|
|
|
import java.util.HashSet; |
|
|
|
|
import java.util.Iterator; |
|
|
|
|
import java.util.LinkedHashSet; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.Map; |
|
|
|
|
import java.util.Set; |
|
|
|
|
import java.util.Stack; |
|
|
|
|
@ -51,8 +52,6 @@ import org.springframework.core.type.classreading.MetadataReaderFactory;
@@ -51,8 +52,6 @@ import org.springframework.core.type.classreading.MetadataReaderFactory;
|
|
|
|
|
import org.springframework.core.type.filter.AssignableTypeFilter; |
|
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
|
|
|
|
|
|
import static org.springframework.context.annotation.MetadataUtils.*; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Parses a {@link Configuration} class definition, populating a collection of |
|
|
|
|
* {@link ConfigurationClass} objects (parsing a single Configuration class may result in |
|
|
|
|
@ -221,10 +220,9 @@ class ConfigurationClassParser {
@@ -221,10 +220,9 @@ class ConfigurationClassParser {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// process any @Import annotations
|
|
|
|
|
List<AnnotationAttributes> imports = |
|
|
|
|
findAllAnnotationAttributes(Import.class, metadata.getClassName(), true); |
|
|
|
|
for (AnnotationAttributes importAnno : imports) { |
|
|
|
|
processImport(configClass, importAnno.getStringArray("value"), true); |
|
|
|
|
Set<String> imports = getImports(metadata.getClassName(), null, new HashSet<String>()); |
|
|
|
|
if (imports != null && !imports.isEmpty()) { |
|
|
|
|
processImport(configClass, imports.toArray(new String[imports.size()]), true); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// process any @ImportResource annotations
|
|
|
|
|
@ -274,45 +272,36 @@ class ConfigurationClassParser {
@@ -274,45 +272,36 @@ class ConfigurationClassParser {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Return a list of attribute maps for all declarations of the given annotation |
|
|
|
|
* on the given annotated class using the given MetadataReaderFactory to introspect |
|
|
|
|
* annotation metadata. Meta-annotations are ordered first in the list, and if the |
|
|
|
|
* target annotation is declared directly on the class, its map of attributes will be |
|
|
|
|
* ordered last in the list. |
|
|
|
|
* @param targetAnnotation the annotation to search for, both locally and as a meta-annotation |
|
|
|
|
* @param annotatedClassName the class to inspect |
|
|
|
|
* @param classValuesAsString whether class attributes should be returned as strings |
|
|
|
|
* Recursively collect all declared {@code @Import} values. Unlike most |
|
|
|
|
* meta-annotations it is valid to have several {@code @Import}s declared with |
|
|
|
|
* different values, the usual process or returning values from the first |
|
|
|
|
* meta-annotation on a class is not sufficient. |
|
|
|
|
* <p>For example, it is common for a {@code @Configuration} class to declare direct |
|
|
|
|
* {@code @Import}s in addition to meta-imports originating from an {@code @Enable} |
|
|
|
|
* annotation. |
|
|
|
|
* @param className the class name to search |
|
|
|
|
* @param imports the imports collected so far or {@code null} |
|
|
|
|
* @param visited used to track visited classes to prevent infinite recursion (must not be null) |
|
|
|
|
* @return a set of all {@link Import#value() import values} or {@code null} |
|
|
|
|
* @throws IOException if there is any problem reading metadata from the named class
|
|
|
|
|
*/ |
|
|
|
|
private List<AnnotationAttributes> findAllAnnotationAttributes( |
|
|
|
|
Class<? extends Annotation> targetAnnotation, String annotatedClassName, |
|
|
|
|
boolean classValuesAsString) throws IOException { |
|
|
|
|
|
|
|
|
|
List<AnnotationAttributes> allAttribs = new ArrayList<AnnotationAttributes>(); |
|
|
|
|
|
|
|
|
|
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(annotatedClassName); |
|
|
|
|
AnnotationMetadata metadata = reader.getAnnotationMetadata(); |
|
|
|
|
String targetAnnotationType = targetAnnotation.getName(); |
|
|
|
|
|
|
|
|
|
private Set<String> getImports(String className, Set<String> imports, |
|
|
|
|
Set<String> visited) throws IOException { |
|
|
|
|
if (visited.add(className)) { |
|
|
|
|
AnnotationMetadata metadata = metadataReaderFactory.getMetadataReader(className).getAnnotationMetadata(); |
|
|
|
|
for (String annotationType : metadata.getAnnotationTypes()) { |
|
|
|
|
if (annotationType.equals(targetAnnotationType)) { |
|
|
|
|
continue; |
|
|
|
|
imports = getImports(annotationType, imports, visited); |
|
|
|
|
} |
|
|
|
|
AnnotationMetadata metaAnnotations = |
|
|
|
|
this.metadataReaderFactory.getMetadataReader(annotationType).getAnnotationMetadata(); |
|
|
|
|
AnnotationAttributes targetAttribs = |
|
|
|
|
AnnotationAttributes.fromMap(metaAnnotations.getAnnotationAttributes(targetAnnotationType, classValuesAsString)); |
|
|
|
|
if (targetAttribs != null) { |
|
|
|
|
allAttribs.add(targetAttribs); |
|
|
|
|
Map<String, Object> attributes = metadata.getAnnotationAttributes(Import.class.getName(), true); |
|
|
|
|
if (attributes != null) { |
|
|
|
|
String[] value = (String[]) attributes.get("value"); |
|
|
|
|
if (value != null && value.length > 0) { |
|
|
|
|
imports = (imports == null ? new LinkedHashSet<String>() : imports); |
|
|
|
|
imports.addAll(Arrays.asList(value)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
AnnotationAttributes localAttribs = |
|
|
|
|
AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(targetAnnotationType, classValuesAsString)); |
|
|
|
|
if (localAttribs != null) { |
|
|
|
|
allAttribs.add(localAttribs); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return allAttribs; |
|
|
|
|
return imports; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void processImport(ConfigurationClass configClass, String[] classesToImport, boolean checkForCircularImports) throws IOException { |
|
|
|
|
@ -451,5 +440,4 @@ class ConfigurationClassParser {
@@ -451,5 +440,4 @@ class ConfigurationClassParser {
|
|
|
|
|
new Location(importStack.peek().getResource(), metadata)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|