栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot自动装配的时候为什么没有走selectImports方法?

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot自动装配的时候为什么没有走selectImports方法?

SpringBoot自动装配的时候为什么没有走selectimports方法?

  本文首先需要大家对SpringBoot的自动装配比较清楚,如果不清楚的可以移步我之前介绍的自动装配的相关视频和文章。

一、疑惑点

  我们之前在分析SpringBoot自动装配源码的时候讲过在 @EnableAutoConfiguration注解上通过 @import注解导入了一个 importSelector接口的实现类 AutoConfigurationimportSelector。按照之前对 @import 注解的理解,应该会执行重写的 selectimports 方法,但调试的时候,执行的流程好像和我们期待的不一样哦,没有走 selectimports方法。

  通过Debug模式,端点定位我们能够发现进入到了getAutoConfigurationEntry方法中。

  但是没有进入selectimports方法。

  这是什么原因呢?他不是实现了importSelector接口吗?怎么和我们之前理解的不一样呢?这就需要我们再来细说下@import注解了。

二、@import

  我们前面介绍过@import注解可以根据添加的不同类型做出不同的操作

导入类型注入方式
实现了importSelector接口不注入该类型的对象,调用selectimports方法,将返回的数据注入到容器中
实现了importBeanDefinitionRegistrar接口不注入该类型的对象,调用registerBeanDefinitions方法,通过注册器注入
普通类型直接注入该类型的对象

  而在自动装配中导入的AutoConfigurationimportSelector这个类型有点特殊。具体看下类图结构

  那这个DeferredimportSelector这个接口的作用是什么呢?字面含义是延迟导入的意思。具体怎么实现的后面再说,我们先来说下他的作用。

三、DeferredimportSelector接口

  DeferredimportSelector接口本身也有importSelector接口的功能,如果我们仅仅是实现了DeferredimportSelector接口,重写了selectimports方法,那么selectimports方法还是会被执行的,来看代码。

public class MyDeferredimportSelector implements DeferredimportSelector {

    @Override
    public String[] selectimports(Annotationmetadata importingClassmetadata) {
        System.out.println("selectimports方法执行了---->");
        return new String[0];
    }


}

对应的配置启动类

@Configuration
@import(MyDeferredimportSelector.class)
public class JavaConfig {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
    }
}

启动效果:

但是如果我们重写了DeferredimportSelector中的Group接口,并重写了getimportGroup,那么容器在启动的时候就不会执行selectimports方法了,而是执行getimportGroup方法。进而执行Group中重写的方法。

public class MyDeferredimportSelector implements DeferredimportSelector {

    @Override
    public String[] selectimports(Annotationmetadata importingClassmetadata) {
        System.out.println("selectimports方法执行了---->");
        return new String[0];
    }

    @Override
    public Class getimportGroup() {
        System.out.println("getimportGroup");
        return MyDeferredimportSelectorGroup.class;
    }

    public static class MyDeferredimportSelectorGroup implements Group{
        private final List imports = new ArrayList<>();
        @Override
        public void process(Annotationmetadata metadata, DeferredimportSelector selector) {
            System.out.println("MyDeferredimportSelectorGroup.Group");
        }

        @Override
        public Iterable selectimports() {
            System.out.println("Group中的:selectimports方法");
            return imports;
        }
    }
}

执行效果:

通过上面的效果解释了为什么在SpringBoot自动装配的时候没有走selectimports方法。那么DeferredimportSelector接口的作用是什么呢?为什么要这么设计呢?我们接下来继续分析

四、DeferredimportSelector的作用

  通过前面的类图结构我们知道DeferredimportSelector是importSelector接口的一个扩展。

importSelector实例的selectimports方法的执行时机,是在@Configguration注解中的其他逻辑被处理之前,所谓的其他逻辑,包括对@importResource、@Bean这些注解的处理(注意,这里只是对@Bean修饰的方法的处理,并不是立即调用@Bean修饰的方法,这个区别很重要!)

DeferredimportSelector实例的selectimports方法的执行时机,是在@Configguration注解中的其他逻辑被处理完毕之后,所谓的其他逻辑,包括对@importResource、@Bean这些注解的处理.

上面的结论我们可以直接在源码中看到对应的答案。首先定位到ConfigurationClassParser中的parse方法。

上面代码有两个非常重要的分支,我们在下面逐一的介绍

1.parse方法

我们先看parse方法,也就是解析注解类的方法。进入

看到调用的是processConfigurationClass,翻译过来就比较好理解了,处理配置类

再进入到循环的方法中。

继续往下看

逻辑处理还是非常清楚的。然后我们需要回到上面的处理@import注解的方法中。在这个方法中我们可以看到@import注解的实现逻辑

也就是前面给大家回顾的@import注解的作用

然后来看下导入的类型是importSelector接口的逻辑。

上面的代码重点解决了importSelector接口的不同类型的实现。

对应的实例存储了起来

2.process方法

  好了上面的代码分析清楚了,然后我们再回到process方法中来看下DeferredimportSelectorHandler是如何处理的。

进入process方法

先看register方法

然后再看processGroupimports方法。

进去后我们需要进入getimports方法中。

然后我们进入到process方法中,可以看到自动装配的方法被执行了!

到这儿是不是帮助大家解决了自动装配为什么没有走 AutoConfigurationimportSelector中的 selectimports 方法了!!!

同时也介绍清楚了importSelector与DeferredimportSelector的区别,就是selectimports方法执行时机有差别,这个差别期间,spring容器对此Configguration类做了些其他的逻辑:包括对@importResource、@Bean这些注解的处理

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/708277.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号