详解Spring的ImportSelector接口(1)

接口的说明

从Spring 3.1开始,Spring中便有了ImportSelector接口,该接口是spring-context包中。如下:

详解Spring的ImportSelector接口(1)_第1张图片
ImportSelector

从 spring源码的注释中我们可以看到关于该接口的作用说明:
翻译:该接口通常被子类实现,用以判断被@Configuration注解修饰的类是否应该被导入;而判断的条件通常是基于注解的一些属性。

从注释中我们可以看出,我们可以通过实现该接口,用于选择性的导入一些被@Configuration注解修饰的类。

接口的子类

详解Spring的ImportSelector接口(1)_第2张图片
ImportSelector的子类

从上图的层级结构中,我们知道。ImportSelector接口有很多实现类,同时也存在一个子接口。那么,我们看看这个子接口 - DeferredImportSelector。顾名思义,从名字中我们可以看出这是一个可以延迟选择性导入类的接口。同样,我们看下Spring官方的说明文档:

详解Spring的ImportSelector接口(1)_第3张图片
DeferredImportSelector

该接口是spring 4.0版本开始出现的,要比它的父接口 - ImportSelector晚了几个版本。从文档中我们得知,这是一个变种的ImportSelector接口,它在所有被@Configuration注解修饰的类处理完成后才运行。DeferredImportSelector用在处理@Conditional相关的导入时特别有用。

下面我们看一个ImportSelector的具体实现:EnableConfigurationPropertiesImportSelector

class EnableConfigurationPropertiesImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata metadata) {
              // 获取EnableConfigurationProperties注解的所有的属性值
        MultiValueMap attributes = metadata.getAllAnnotationAttributes(
                EnableConfigurationProperties.class.getName(), false);
             // 获取attributes中主键value的第一个值。
        Object[] type = attributes == null ? null
                : (Object[]) attributes.getFirst("value");
              // 根据条件,返回需要导入的类。
        if (type == null || type.length == 0) {
            return new String[] {
                    ConfigurationPropertiesBindingPostProcessorRegistrar.class
                            .getName() };
        }
        return new String[] { ConfigurationPropertiesBeanRegistrar.class.getName(),
                ConfigurationPropertiesBindingPostProcessorRegistrar.class.getName() };
    }
}

该类来自于SpringBoot的一个实现,用于绑定外部配置文件中的属性到Configuration类中。从上面的类,我们可以看到,要实现ImportSelector 接口,还是比较简单的。我们只需要实现它的selectImports方法即可。方法中的返回值可以根据我们自己的条件返回。

疑问

  1. ImportSelector是如何被Spring框架调用的呢?
  2. selectImports()的返回值又是如何被Spring框架使用的呢?

你可能感兴趣的:(详解Spring的ImportSelector接口(1))