1.灵感来源
最近在仔细研究SpringBoot,通过学习了解了SpringBoot自动配置的过程,可以完美解答:为什么通过Spring Initializr 引入对应的场景(例如:springboot-starter-web),然后写好业务项目就可以跑起来?以Tomcat为例,如果需要修改端口号,只需要在application.properties里面修改server.port=XXXX就可以生效?下面将以springboot-starter-web场景为例,从源码的层面回答以上问题。
2.流程
a:导入start-web:导入web开发场景
打开pom文件按住Ctrl点击 spring-boot-starter-web发现它导入了web开发场景所需要的所以依赖:json、tomcat、web、webmvc等。
每一个场景都有一个spring-boot-starter核心启动类,点击核心启动类我们能看到以下的依赖:spring-boot-autoconfigure等
spring-boot-autoconfigure里面包括了所有场景的所有配置
所以只要包下所有的类都生效,那么就可以回答第一个问题了,以为这些配置类给我们做了整合操作,但是springboot默认只扫描主类所在的包以及它的子包,那么上面的类并不能被springboot扫描到,组件也不能放进容器,事实并不是这样,我们接着往下看。
b:主程序里面有 @SpringBootApplication注解
我们来看主程序的@SpringBootApplication注解点击去看会发现它是一个复合注解
@SpringBootConfiguration 这个注解是用来声明我是一个配置类 @EnableAutoConfiguration 这个注解就是用来解决springboot扫描不到 spring-boot-autoconfigure的问题 @Import({AutoConfigurationImportSelector.class})用来向容器批量导入组件,而且这些配置类是从 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports来的
也就是说springboot启动的时候会将上面的配置类导入进来,虽然它只能导入主类的包及其子包但是主程序通过@EnableAutoConfiguration注解自动的包这些配置类导入进来。虽然导入了这么多配置类但是不一定全都生效,以AopAutoConfiguration为例:只有存在Advice配置才生效,每一个配置类都有自己的条件注解@ConditionalOnXXX只有条件成立配置才生效。这样就回答了第一个问题。
@ComponentScan
这个是用来扫描指定的组合包的
第二个问题的答案,以tomcat配置为例,打开org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,会发现@EnableConfigurationProperties({ServerProperties.class})这个注解的作用是把配置文件的前缀的属性值封装到ServerProperties中,点开就能查看前缀值:如图。
c:编写业务,过程不需要关系ssm是怎么整合的(主要是底层已经整合好了,而且已经生效了)
总结:
springboot项目在启动的时候是通过 @EnableAutoConfiguration注解来批量导入配置类的而且这些配置类是从 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports来的
这些类的导入帮我们完成了框架整合。
配置文件之所以可以修改属性值是因为配置类中@EnableConfigurationProperties({ServerProperties.class})注解将配置文件的特定前缀值与类中的相同的属性名进行绑定。