Springboot自动配置原理
Springboot强大到几乎让我们只需编写我们自己的业务逻辑,神不知鬼不觉的帮我们做了那么多事情。我们的分析还是从主程序(MainApplication)开始,核心就是@SpringBootApplication注解。
分析@SpringBootApplication
点进@SpringBootApplication注解我们会发现@SpringBootApplication实际就相当于@SpringBootConfiguration+@EnableAutoConfiguration+@ComponentScan
所以,分析@SpringBootApplication注解就相当于分析这三个。
分析@SpringBootConfiguration
点进@SpringBootConfiguration注解我们发现,它其实就是一个@Configuration
@Configuration:代表当前是一个配置类,它还是相当于标注在主程序类上。
分析@ComponentScan
包扫描,指定扫描哪些,在这里不同的是,Springboot有两个自定义的扫描器,大家有兴趣的可以深入了解下。
以上这两个注解貌似都还没有完成我们想要的任务。所以剩下的任务想必也就放在了第三个注解@EnableAutoConfiguration上了。
分析@EnableAutoConfiguration
老规矩,点进@EnableAutoConfiguration我们会发现它也是个合成注解,由@AutoConfigurationPackage+@Import({AutoConfigurationImportSelector.class})组成。
所以分析@EnableAutoConfiguration到头来是分析它里面的这两个注解。
- @AutoConfigurationPackage
翻译过来就是自动配置包,继续进入它的源码看看它究竟做了什么事情,点进之后发现它实际就是@Import()。
@Import的作用就是给容器中注册一个组件。源码是给容器中注册Registrar组件。这个组件的作用又是啥,继续跟踪源码:
可以看到源码中有两个方法,关注下打了断点的这个方法,参数其一AnnotationMetadata metadata就是拿到注解的元信息,这个方法的作用就是利用Registrar给容器中导入一系列组件,将指定的一个包下的所有组件导入进来,在此处也就是主程序MainApplication 所在包下,如图:
new AutoConfigurationPackages.PackageImports(metadata).getPackageNames() 此处也就等于你主程序MainApplication所在的包全名
- @Import({AutoConfigurationImportSelector.class})
利用AutoConfigurationImportSelector.class给容器中批量导入组件,这个理解清楚之后,我们的分析就OK了,具体导入了什么,我们继续跟踪源码,进入AutoConfigurationImportSelector.class:
看到第64行(此处是64行),方法名为selectImports,这个方法返回的String[]数组中有哪些东西,我们就导入哪些。
分析源码得知,最终的String[]数组里的东西还是来源于getAutoConfigurationEntry(annotationMetadata),利用getAutoConfigurationEntry(annotationMetadata)给容器中批量导入一些组件。我们继续跟着源码定位到此方法处,打个断点,DeBug以下
第86行先获取所有候选的配置,然后经过移除重复的,再排除一些东西等等操作,最终得到的configurations就是我们要导入到容器中的组件。
那它又是怎样得到这些组件的呢?继续跟踪源码,进入此方法
一路追踪源码我们得知,它是利用工厂加载 Map<String, List> loadSpringFactories(@Nullable ClassLoader classLoader)得到所有的组件
那么问题又来了,它是从哪加载得到所有的组件的。由上面方法的源码得知,从META-INF/spring.factories位置来加载一个文件,默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件,在我们引入的jar包中有的就有META-INF/spring.factories文件,有的就没有。最核心的是spring-boot-autoconfigure-2.3.4.RELEASE.jar
打开spring.factories,里面有个配置项org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
从22行到148行,总共148-22+1=127个的自动配置类,我们可以发现,实际上这些自动配置类是在文件中写死的,每当spring-boot一启动就要给容器中加载这些所有的配置类。但实际上,我们springboot容器中真的会全部注册进来这些组件吗?答案是:不一定的!还要按需开启自动配置项!虽然我们127个场景的所有自动配置启动的时候默认全部加载。
实则还需按照条件装配规则(@Conditional),最终会按需配置。此处就省略了。
若有错误,小伙伴们可以提醒一下,谢谢大家的观看!