提交 9a271ce6 编写于 作者: C Chris Beams

Introduce ImportSelector interface

Allows @Enable* a layer of indirection for deciding which @Configuration
class(es) to @Import.

The @Import annotation may now accept @Configuration class literals
and/or ImportSelector class literals.
上级 cdb01cbd
...@@ -27,6 +27,7 @@ import java.util.Map; ...@@ -27,6 +27,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Stack; import java.util.Stack;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.parsing.Location; import org.springframework.beans.factory.parsing.Location;
import org.springframework.beans.factory.parsing.Problem; import org.springframework.beans.factory.parsing.Problem;
import org.springframework.beans.factory.parsing.ProblemReporter; import org.springframework.beans.factory.parsing.ProblemReporter;
...@@ -37,6 +38,7 @@ import org.springframework.core.type.MethodMetadata; ...@@ -37,6 +38,7 @@ import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.StandardAnnotationMetadata; import org.springframework.core.type.StandardAnnotationMetadata;
import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
...@@ -142,7 +144,7 @@ class ConfigurationClassParser { ...@@ -142,7 +144,7 @@ class ConfigurationClassParser {
List<Map<String, Object>> allImportAttribs = List<Map<String, Object>> allImportAttribs =
AnnotationUtils.findAllAnnotationAttributes(Import.class, metadata.getClassName(), true); AnnotationUtils.findAllAnnotationAttributes(Import.class, metadata.getClassName(), true);
for (Map<String, Object> importAttribs : allImportAttribs) { for (Map<String, Object> importAttribs : allImportAttribs) {
processImport(configClass, (String[]) importAttribs.get("value")); processImport(configClass, (String[]) importAttribs.get("value"), true);
} }
if (metadata.isAnnotated(ImportResource.class.getName())) { if (metadata.isAnnotated(ImportResource.class.getName())) {
...@@ -162,16 +164,29 @@ class ConfigurationClassParser { ...@@ -162,16 +164,29 @@ class ConfigurationClassParser {
} }
} }
private void processImport(ConfigurationClass configClass, String[] classesToImport) throws IOException { private void processImport(ConfigurationClass configClass, String[] classesToImport, boolean checkForCircularImports) throws IOException {
if (this.importStack.contains(configClass)) { if (checkForCircularImports && this.importStack.contains(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack, configClass.getMetadata())); this.problemReporter.error(new CircularImportProblem(configClass, this.importStack, configClass.getMetadata()));
} }
else { else {
this.importStack.push(configClass); this.importStack.push(configClass);
for (String classToImport : classesToImport) { AnnotationMetadata importingClassMetadata = configClass.getMetadata();
this.importStack.registerImport(configClass.getMetadata().getClassName(), classToImport); for (String candidate : classesToImport) {
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(classToImport); MetadataReader reader = this.metadataReaderFactory.getMetadataReader(candidate);
processConfigurationClass(new ConfigurationClass(reader, null)); if (new AssignableTypeFilter(ImportSelector.class).match(reader, metadataReaderFactory)) {
// the candidate class is an ImportSelector -> delegate to it to determine imports
try {
ImportSelector selector = BeanUtils.instantiateClass(Class.forName(candidate), ImportSelector.class);
processImport(configClass, selector.selectImports(importingClassMetadata), false);
} catch (ClassNotFoundException ex) {
throw new IllegalStateException(ex);
}
}
else {
// the candidate class not an ImportSelector -> process it as a @Configuration class
this.importStack.registerImport(importingClassMetadata.getClassName(), candidate);
processConfigurationClass(new ConfigurationClass(reader, null));
}
} }
this.importStack.pop(); this.importStack.pop();
} }
......
/*
* Copyright 2002-2011 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import org.springframework.core.type.AnnotationMetadata;
/**
* Interface to be implemented by types that determine
* which @{@link Configuration} class(es) should be imported based on
* a given selection criteria, usually an annotation attribute.
*
* @author Chris Beams
* @since 3.1
* @see Import
*/
public interface ImportSelector {
/**
* Select and return the names of which class(es) should be imported.
* @param importingClassMetadata the AnnotationMetodata of the
* importing @{@link Configuration} class.
*/
String[] selectImports(AnnotationMetadata importingClassMetadata);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册