美文网首页Spring Boot方案springboot
Spring boot 扫描注册第三方类的流程及原理

Spring boot 扫描注册第三方类的流程及原理

作者: 程序员札记 | 来源:发表于2021-10-19 14:08 被阅读0次

    Springboot中,对于那些写在starter中的类,我们只需要把这些 starter的 依赖配置在pom文件中, 当spring boot启动的时候, 这些类就会自动的被 spring boot扫描然后将他们注册为bean 交给spring boot 去管理, 这些都是我们使用spring boot的一些比较基本的常识,

    当你写了一个自己的starter, 但是你的starter 的包路径可能和app的包路径不同,比如你的app 是com.sample, 你的starter的包路径是 com.test, 那么从spring 的角度来讲, com.test是不可能被扫描到的,除非你定义了spring.factory ,但是spring.factory也只能加载spring 认识的这些类。 如果有个类是用了@Entity, 我也想让他被扫描到该怎么办?
    一个简单的做法就是在这个类上加入@AutoConfigurationPackage。 当你再一个类上加入这个annotation 时,实际上就把这个类以及以下加入到了扫描的类里。 你可以在不同package 类下加这个annotation,那么就可以自动把这个package 下的类加入到spring boot 的扫描路径。

    @AutoConfigurationPackage一个最广泛的应用就是它是EnableAutoConfiguration 的一部分。我们以此为例子来看看@AutoConfigurationPackage是如何工作的。

    既然说到了 @Entity, 我们就用它来举例子. 在spring boot的文档中(https://spring.io/guides/gs/accessing-data-jpa/) 有这么一句话

    it will be used when scanning for code @Entity classes. It is generally recommended that you place EnableAutoConfiguration (if you’re not using @SpringBootApplication) in a root package so that all sub-packages and classes can be searched.

    其中就有一个关键词, EnableAutoConfiguration 这个我们应该很熟悉了,它是spring boot最必不可少的注解 @SpringBootApplication 的 三个组成注解之一

    image.png

    那么我们也知道, spring boot就是靠着 EnableAutoConfiguration 这个注解, 实现了 自动载入应用程序所需要的所有的默认配置, 那么 @Entity 跟它有什么关系么?

    我们可以查看EnableAutoConfiguration的源码,如下:

    image.png

    其中有一个@AutoConfigurationPackage还有一个@Import注解,我们先看@AutoConfigurationPackage

    image.png

    会发现它这里也有一个@Import注解,既然多处都出现了它,那么它的作用肯定是很重要的,源码如下

    image.png

    在注释中说的很明白了,简单点来说就是 用来导入配置类或者一些需要前置加载的类.根据类的类型不同, 通过不同的方式导入目标类.

    既然明白了@Import的作用,那么就知道了重点肯定是@Import(AutoConfigurationPackages.Registrar.class) 中的AutoConfigurationPackages,其部分源码如下

    image.png

    根据源码的注释, 我们知道了答案, @Entity注解由@AutoConfigurationPackage扫描并加载. 换句话来说, 就是这个class,它保存了自动装配的路径以方便后续的引用, 那么现在我们跟随代码来看看它是怎么运行的.

    最开始肯定是SpringApplication.run(DemoApplication.class, args)的run方法拿到context,拿到后会执行refreshContext方法.

    image.png

    refresh中我们主要关注invokeBeanFactoryPostProcessors(beanFactory),这个方法是实例化并调用所有注册的BeanFactoryPostProcessor bean.

    image.png

    接下列会进一步的生成BeanDefinitions

    image.png

    processConfigBeanDefinitions源码中比较重要的就是如下的do方法:

    image.png

    其中第三行的 parser.parse 会完成对AutoConfigurationImportSelector的处理,也就是把各个包下的spring.factory里的自动装配相关的class都选出来

    image.png

    可以看到生成的 configClasses 一共有71个, 而我们的启动类只是其中之一. 且有一个属性是专门用来保存Registrar的。比如我们的启动类对应的 ConfigurationClass 就有上面所说的 AutoConfigurationPackages Registrar, 如下.

    image.png

    接下来就会加载这些Registrar

    image.png

    loadBeanDefinitionsFromRegistrars 源码如下:

    image.png

    以及后续的注册等步骤:

    register 源码 image.png

    那么最终调用的就是AutoConfigurationPackages.register这个方法,进入的是else逻辑,注册一个新的Definition

    debug 截图

    而这里的packageName就是我们的 启动类所在的路径.

    那么注册了, 怎么拿到呢? 有register方法肯定就有get, 在 AutoConfigurationPackages 有一个 get方法,该方法的作用就是返回上面提到的路径, 源码如下

    image.png

    那么回到最开始的问题,以 JPA 为例, 当获取到包路径后,就可以开始扫描注册了.


    org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration#getPackagesToScan

    相关文章

      网友评论

        本文标题:Spring boot 扫描注册第三方类的流程及原理

        本文链接:https://www.haomeiwen.com/subject/dprvoltx.html