Spring boot自动装配原理
开局一张图。全是精华。
Spring Boot原创原理图
SpringInitializerApplication讲解
首先我们看我们的配置启动类SpringInitializerApplication中有一个@SpringBootApplication
打开@SpringBootApplication,@SpringBootApplication如下图:
里面有一个@EnableAutoConfiguration,打开@EnableAutoConfiguration
@EnableAutoConfiguration如图:
最主要的是两个注解@AutoConfigurationPackage和@Import(AutoConfigurationImportSelector)
@AutoConfigurationPackage注解讲解
先看看@AutoConfigurationPackage注解:
这个注解是自动配置包,主要是使用的@Import来给Spring容器中导入一个组件 ,这里导入的是Registrar.class。
来看下这个Registrar:
就是通过这个方法获取扫描的包路径,可以debug看看:
在这行代码上打了一个断点:
启动项目:
进入断点处,看看能否获取扫描的包路径:
已经获取到了包路径:
那那个metadata是什么呢:
可以看到是标注在@SpringBootApplication注解上的DemosbApplication,也就是我们的主配置类:
说白了就是将主配置类(即@SpringBootApplication标注的类)的所在包及子包里面所有组件扫描加载到Spring容器。所以包名一定要注意。
现在包扫描路径获取到了,那具体加载哪些组件呢,看看下面这个注解。
@Import({AutoConfigurationImportSelector.class})注解讲解
而这个注解也是一个派生注解,其中的关键功能由@Import提供,其导入AutoConfigurationImportSelector.class,打开AutoConfigurationImportSelector.class
AutoConfigurationImportSelector.class如下图:
最重要的是里面的selectimports方法,然后里面有一个SpringFactoriesLoader.loadFactoryNames()
他的作用是扫描所有具有META-INF/spring.factories的jar包。spring-boot-autoconfigure-x.x.x.x.jar里就有一个这样的spring.factories文件。
这个spring.factories文件也是一组一组的key=value的形式,其中一个key是EnableAutoConfiguration类的全类名,而它的value是一个xxxxAutoConfiguration的类名的列表,这些类名以逗号分隔,如下图所示:
但是我这里找到的所有自动配置类不都能生效,都有限制条件,常见的有以下:
@ConditionalOnBean:当容器里有指定的bean的条件下。
@ConditionalOnMissingBean:当容器里不存在指定bean的条件下。
@ConditionalOnClass:当类路径下有指定类的条件下。
@ConditionalOnMissingClass:当类路径下不存在指定类的条件下。
@ConditionalOnProperty:指定的属性是否有指定的值,比如@ConditionalOnProperties(prefix=”xxx.xxx”, value=”enable”, matchIfMissing=true),代表当xxx.xxx为enable时条件的布尔值为true,如果没有设置的情况下也为true。
以ServletWebServerFactoryAutoConfiguration配置类为例,解释一下全局配置文件中的属性如何生效,比如:server.port=8081,是如何生效的(当然不配置也会有默认值,这个默认值来自于org.apache.catalina.startup.Tomcat)。下面的@Conditionxxxx都是限制条件,当然不配置也有默认值。
在ServletWebServerFactoryAutoConfiguration类上,有一个@EnableConfigurationProperties注解:开启配置属性,@EnableConfigurationProperties简单来说就是使使用@ConfigurationProperties 注解的类生效。而它后面的参数是一个ServerProperties类,这就是习惯优于配置的最终落地点。
在这个类上,我们看到了一个非常熟悉的注解:@ConfigurationProperties,它的作用就是从配置文件中绑定属性到对应的bean上,说白了就是让你配置的时候有提示。
返回上一级ServletWebServerFactoryAutoConfiguration类:
而**@EnableConfigurationProperties**负责导入这个已经绑定了属性的bean到spring容器中
那么所有其他的和这个类相关的属性都可以在全局配置文件中定义,也就是说,真正“限制”我们可以在全局配置文件中配置哪些属性的类就是这些XxxxProperties类,它与配置文件中定义的prefix关键字开头的一组属性是唯一对应的。
例如:
总结
返回到最初,我们运行主启动类,执行SpringApplication.run(…)方法,其内部就会执行@Spring Boot Application中@EnableAutoConfiguration中@Import({AutoConfigurationImportSelector.class})里的AutoConfigurationImportSelector.class里的selectImports()方法,扫描所有spring factories,找到所有JavaConfig自动配置类的全限定名对应的class,然后将可生效的配置类配置的已绑定了属性的bean加载到Spring容器中。run方法还执行了@EnableAutoConfiguration中的@AutoConfigurationPackage中的@import({Registrar})中的Registrar里的getPackageName()得到主配置类的所在包名,最后把主配置类所在包以及子包里面所有组件加载如Spring容器。
参考文献:
Spring Boot面试杀手锏————自动配置原理,作者:圣斗士Morty
SpringBoot自动装配原理分析,作者:Dongguabai