DeferredImportSelector是ImportSelector既然一个子接口是相似的,那么功能是相似的,都是向的spring容器中注入bean,只不过注入bean时机不同。
DeferredImportSelector与ImportSelector的区别:
- ImportSelector:顺便处理一下分析配置类。ImportSelector类。
- DeferredImportSelector:在分析配置类时,只需将其添加到容器中,直到所有配置类分析完成后才能处理DeferredImportSelector。
DeferredImportSelector的使用
自定义DeferredImportSelector当然要实现DeferredImportSelector接口,同时getImportGroup()返回的是一个Group的Class因此,我们还需要定制一个类来实现它DeferredImportSelector.Group当然,接口也不能实现,端倪从源码中可见。
package com.morris.spring.entity.imports; import com.morris.spring.entity.User; import org.springframework.context.annotation.DeferredImportSelector; import org.springframework.core.type.AnnotationMetadata; import java.util.ArrayList; import java.util.List; public class DeferredImportSelectorBean implements DeferredImportSelector {
@Override public Class<? extends Group> getImportGroup() {
return DeferredImportSelectorBeanGroup.class; } @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{
User.class.getName()};
}
private static class DeferredImportSelectorBeanGroup implements DeferredImportSelector.Group {
private final List<Entry> instanceImports = new ArrayList<>();
@Override
public void process(AnnotationMetadata metadata, DeferredImportSelector selector) {
for (String importClassName : selector.selectImports(metadata)) {
this.instanceImports.add(new Entry(metadata, importClassName));
}
}
@Override
public Iterable<Entry> selectImports() {
return instanceImports;
}
}
}
使用@Import注解将DeferredImportSelectorBean导入到Spring容器中:
package com.morris.spring.demo.annotation;
import com.morris.spring.entity.User;
import com.morris.spring.entity.imports.DeferredImportSelectorBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;
@Import(DeferredImportSelectorBean.class)
public class DeferredImportSelectorBeanDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(DeferredImportSelectorBeanDemo.class);
User user = applicationContext.getBean(User.class);
System.out.println(user);
System.out.println(applicationContext.containsBean("deferredImportSelectorBean"));
}
}
运行结果如下:
User(username=null, age=0)
false
源码分析
DeferredImportSelector的实例化
org.springframework.context.annotation.ConfigurationClassParser#processImports
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
boolean checkForCircularImports) {
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
if (candidate.isAssignable(ImportSelector.class)) {
// 处理ImportSelector
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass(); // 加载ImportSelector
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry); // 反射实例化ImportSelector
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
if (selector instanceof DeferredImportSelector) {
// 特殊处理DeferredImportSelector
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else {
// 调用selectImports方法
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
// 又递归,实际上会进入下面的else
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
}
... ...
收集DeferredImportSelector
DeferredImportSelectorHandler#handle方法只是负责DeferredImportSelector的收集,加入到deferredImportSelectors容器中。 org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorHandler#handle
private class DeferredImportSelectorHandler {
@Nullable
private List<DeferredImportSelectorHolder> deferredImportSelectors = new ArrayList<>();
/** * Handle the specified {@link DeferredImportSelector}. If deferred import * selectors are being collected, this registers this instance to the list. If * they are being processed, the {@link DeferredImportSelector} is also processed * immediately according to its {@link DeferredImportSelector.Group}. * @param configClass the source configuration class * @param importSelector the selector to handle */
public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
if (this.deferredImportSelectors == null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
handler.register(holder);
handler.processGroupImports();
}
else {
// 这里只是加入到list中
this.deferredImportSelectors.add(holder);
}
}
... ...
DeferredImportSelector的调用
ConfigurationClassParser#parse主要负责对所有的配置类进行解析,解析完成最后会完成DeferredImportSelector的调用。 org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)
public void parse(Set<BeanDefinitionHolder> configCandidates) {
// 开始遍历所有的BD,解析其中的各种注解
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
// 有注解的BD具体的实现类为AnnotatedBeanDefinition
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
// DeferredImportSelector的处理
this.deferredImportSelectorHandler.process();
}
org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorHandler#process
public void process() {
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
try {
if (deferredImports != null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
// 对DeferredImportSelector进行排序,DeferredImportSelector可以实现order,@Order,@Priority等
deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
// 将group注册到groupings
// 将配置类注册到configurationClasses
deferredImports.forEach(handler::register);
handler.processGroupImports();
}
}
finally {
this.deferredImportSelectors = new ArrayList<>();
}
}
org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGroupingHandler#register
private class DeferredImportSelectorGroupingHandler {
private final Map<Object, DeferredImportSelectorGrouping> groupings = new LinkedHashMap<>();
private final Map<AnnotationMetadata, ConfigurationClass> configurationClasses = new HashMap<>();
public void register(DeferredImportSelectorHolder deferredImport) {
Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup();
// Map.computeIfAbsent,key存在就返回value,key不存在就根据function计算后插入map中,并返回value
DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent(
(group != null ? group : deferredImport),
key -> new DeferredImportSelectorGrouping(createGroup(group)));
grouping.add(deferredImport);
this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getConfigurationClass());
}
org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGroupingHandler#processGroupImports
public void processGroupImports() {
for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
Predicate<String> exclusionFilter = grouping.getCandidateFilter();
// grouping.getImports()会完成group的两个方法的调用
grouping.getImports().forEach(entry -> {
ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
try {
// 将grouping.getImports()返回的类当成import普通的bean来处理
processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),
Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
exclusionFilter, false);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configurationClass.getMetadata().getClassName() + "]", ex);
}
});
}
}
org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGrouping#getImports
public Iterable<Group.Entry> getImports() {
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
// 先调用Group的process方法
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
// 再调用Group的selectImports方法
return this.group.selectImports();
}