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
的 三个组成注解之一
那么我们也知道, spring boot就是靠着 EnableAutoConfiguration 这个注解, 实现了 自动载入应用程序所需要的所有的默认配置, 那么 @Entity
跟它有什么关系么?
我们可以查看EnableAutoConfiguration的源码,如下:
image.png其中有一个@AutoConfigurationPackage
还有一个@Import
注解,我们先看@AutoConfigurationPackage
会发现它这里也有一个@Import
注解,既然多处都出现了它,那么它的作用肯定是很重要的,源码如下
在注释中说的很明白了,简单点来说就是 用来导入配置类或者一些需要前置加载的类.根据类的类型不同, 通过不同的方式导入目标类.
既然明白了@Import
的作用,那么就知道了重点肯定是@Import(AutoConfigurationPackages.Registrar.class) 中的AutoConfigurationPackages
,其部分源码如下
根据源码的注释, 我们知道了答案, @Entity
注解由@AutoConfigurationPackage
扫描并加载. 换句话来说, 就是这个class,它保存了自动装配的路径以方便后续的引用, 那么现在我们跟随代码来看看它是怎么运行的.
最开始肯定是SpringApplication.run(DemoApplication.class, args)
的run方法拿到context,拿到后会执行refreshContext方法.
在refresh
中我们主要关注invokeBeanFactoryPostProcessors(beanFactory)
,这个方法是实例化并调用所有注册的BeanFactoryPostProcessor bean.
接下列会进一步的生成BeanDefinitions
image.pngprocessConfigBeanDefinitions源码中比较重要的就是如下的do方法:
image.png其中第三行的 parser.parse 会完成对AutoConfigurationImportSelector的处理,也就是把各个包下的spring.factory里的自动装配相关的class都选出来
image.png可以看到生成的 configClasses 一共有71个, 而我们的启动类只是其中之一. 且有一个属性是专门用来保存Registrar的。比如我们的启动类对应的 ConfigurationClass 就有上面所说的 AutoConfigurationPackages Registrar, 如下.
image.png接下来就会加载这些Registrar
image.pngloadBeanDefinitionsFromRegistrars 源码如下:
image.png以及后续的注册等步骤:
register 源码 image.png那么最终调用的就是AutoConfigurationPackages.register
这个方法,进入的是else逻辑,注册一个新的Definition
而这里的packageName就是我们的 启动类所在的路径.
那么注册了, 怎么拿到呢? 有register方法肯定就有get, 在 AutoConfigurationPackages
有一个 get方法,该方法的作用就是返回上面提到的路径, 源码如下
那么回到最开始的问题,以 JPA 为例, 当获取到包路径后,就可以开始扫描注册了.
org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration#getPackagesToScan
网友评论