写在最前
上篇文章 - 详解Spring的ImportSelector接口(1) //www.greatytc.com/p/aa99a303bc37中,我们最后留下了两个疑问。今天我们先说说第一个疑问 - ImportSelector是如何被Spring框架调用的呢?
ImportSelector是如何被Spring框架调用的呢?
ClassPathXmlApplicationContext
我们以ClassPathXmlApplicationContext为例子,看看Spring在启动过程中是如何调用到ImportSelector接口的。
如上图,我们初始化一个ClassPathXmlApplicationContext时需要指定一个xml文件作为应用上下文。该构造器中又调用了另一个构造器,我们跟进去看下:
从上面的代码中,我们可以看到在设置完configLocations后调用了refresh()方法。那么,refresh()方法又是干什么的呢?
AbstractApplicationContext的refresh()方法
refresh()定义在ConfigurableApplicationContext接口中,具体的实现在AbstractApplicationContext中,如下:
从上面的实现中,我们可以看到该方法做了很多准备、初始化、事件通知等工作。具体的我们就不一一看了,今天我们只关心其中的
invokeBeanFactoryPostProcessors
方法。
从上面的代码中我们可以看到,invokeBeanFactoryPostProcessors()方法把具体的调用方法委托给了
PostProcessorRegistrationDelegate
类。另外,从该方法的名字当中我们也可以看出,该方法主要的目的是:实例化,并调用BeanFactoryPostProcessor类的。BeanFactoryPostProcessor是一个接口,有很多的实现类,这里我们就暂且不管BeanFactoryPostProcessor的具体用处了。我们先进入PostProcessorRegistrationDelegate
一窥究竟。
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(xxx)方法
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
// 如果有BeanDefinitionRegistryPostProcessors 的话,就先调用它们
// 处理过的Beans
Set<String> processedBeans = new HashSet<String>();
// 是否是BeanDefinitionRegistry类型的BeanFactory. BeanDefinitionRegistry的作用是可以用来注册,删除,获取BeanDefinitions
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 普通类型的BeanFactoryPostProcessor集合
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
// BeanDefinitionRegistry类型的BeanFactoryPostProcessor集合(BeanDefinitionRegistryPostProcessor继承于BeanFactoryPostProcessor)
List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
new LinkedList<BeanDefinitionRegistryPostProcessor>();
// 对集合beanFactoryPostProcessors进行分类,如果是BeanDefinitionRegistry类型的BeanFactoryPostProcessor;则调用方法 - postProcessBeanDefinitionRegistry()。、、
// postProcessBeanDefinitionRegistry(BeanDefinitionRegistry)该方法的作用是在标准的BeanDefinitions初始化完成后可以修改容器上下文内部的beanDefinition。
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryPostProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
registryPostProcessors.add(registryPostProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
// 这里不要初始化FactoryBeans,我们需要保留这些普通的beans 不在这里初始化,目的是为了让bean factory post-processor去处理他们。
// 根据BeanDefinitionRegistryPostProcessors 实现的不同接口,拆分开来去调用他们。
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 首先,调用实现了优先级接口 - PriorityOrdered的BeanDefinitionRegistryPostProcessors
List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 排序
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
// 添加排序好的优先级PostProcessors到registryPostProcessors集合
registryPostProcessors.addAll(priorityOrderedPostProcessors);
// 调用排序好的优先级BeanDefinitionRegistryPostProcessors,postProcessBeanDefinitionRegistry方法会被调用,用来修改,获取,删除容器上下文中的bean定义。
invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// 调用实现了Ordered接口的BeanDefinitionRegistryPostProcessors ,大致逻辑同上PriorityOrdered的处理
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(beanFactory, orderedPostProcessors);
registryPostProcessors.addAll(orderedPostProcessors);
invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// 调用所有其它类型的BeanDefinitionRegistryPostProcessors
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);
registryPostProcessors.add(pp);
processedBeans.add(ppName);
pp.postProcessBeanDefinitionRegistry(registry);
reiterate = true;
}
}
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 调用所有的BeanDefinitionRegistryPostProcessor的postProcessBeanFactory 方法。
invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
// 调用容器中BeanFactoryPostProcessor类型的bean(不包含BeanDefinitionRegistryPostProcessor类型的beans)。
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
// 若beanFactory不是BeanDefinitionRegistry类型的,则直接调用容器中所有的BeanFactoryPostProcessor的postProcessBeanFactory 方法。
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 下面是BeanFactoryPostProcessor的具体调用过程,和上面的过程很相似,这里就不多说了。
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(beanFactory, orderedPostProcessors);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
上面的调用关系中,我们可以看出。在这个方法中有两种类型的PostPorcessor被调用处理了;而这两种PostProcessor的关系如下图:
BeanDefinitionRegistryPostProcessor继承于BeanFactoryPostProcessor。我们大致看看接口定义的方法:
postProcessBeanFactory用于在标准的初始化完成后修改容器上下文中的beanFactory。所有bean定义将被加载,但是它们将暂时不被实例化,这允许覆盖,甚至添加一些属性到延迟初始化的bean上。
postProcessBeanDefinitionRegistry方法在标准化初始化完成后可以修改容器内部的bean definition registry。所有的常规的bean定义都将被加载,但是没有bean被实例化。这允许我们在下一个处理阶段增加一些新的bean定义。
综合上面的逻辑,postProcessBeanDefinitionRegistry是在postProcessBeanFactory方法之前被调用的。
ConfigurationClassPostProcessor
上面说了这么多,目的是为了说明我们的主角 - ConfigurationClassPostProcessor。ConfigurationClassPostProcessor类实现了BeanDefinitionRegistryPostProcessor接口,同时还实现了一些其他的接口,如下图:
ConfigurationClassPostProcessor类实现了父类的postProcessBeanDefinitionRegistry和postProcessBeanFactory方法,如下图:
由上面的分析可知,postProcessBeanDefinitionRegistry方法的调用早于postProcessBeanFactory方法。所有我们先来看看postProcessBeanDefinitionRegistry方法的具体内容:
从注释中我们可以看到,这个方法的主要作用是进一步从配置中获取bean的定义,也就是被@Configuration注解修饰的配置类。该方法中又调用了processConfigBeanDefinitions()方法,该方法主要用于处理@Configuration注解。
在processConfigBeanDefinitions方法中又调用了ConfigurationClassParser类的parse方法用于解析@Configuration,如下图:
我们在进入到ConfigurationClassParser类的parse方法看看,如下:
看到这里,我们终于看见曙光了,终于看见DeferredImportSelector接口了。我们忽略方法中其它部分代码,直接进入到processDeferredImportSelectors()方法一窥究竟。
processDeferredImportSelectors方法中调用了processImports方法执行导入,跟进去看看,在processImports 方法中有很重要的一段代码,如下:
如上图中代码所示:
- 检查类型是否是ImportSelector,如果是则执行第2步。
- 如果同时实现了Aware接口和ImportSelector接口,则先调用Aware接口的实现方法;然后进入第三步。
- 调用selector的selectImpors方法,把要导入的类的元数据信息作为参数,根据具体的实现逻辑返回要导入的classes。
- 执行后续的代码...
说到这里,我们可以看到ImportSelector接口的实现方法selectImports终于被调用成功了。
总结
- ImportSelector的导入实现是通过BeanFactoryPostProcessor接口的子接口BeanDefinitionRegistryPostProcessor来实现的。
- ImportSelector接口的处理是伴随着@Configuration注解的处理一起处理的。
- ImportSelector接口可以实现自定义条件选择性导入classes。
- ImportSelector接口的字接口DeferredImportSelector在所有@Configuration处理完成后才被处理的。
- 处理ImportSelector接口时,bean定义已经被加载,但是bean还没有被实例化。
- Spring Bootn的自动配置功能就是通过DeferredImportSelector接口的实现类EnableAutoConfigurationImportSelector做到的。