上一节我们已经运行了SpringBoot的HelloWorld,很简单,不用像Spring那么多配置,我们分析一下
分析
我们看一下pom.xml
1.父项目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
这是一个父项目,这里是spring-boot-starter-parent 所有spring-boot-starter的父项目,我们用Ctrl+鼠标左键 点击spring-boot-starter-parent,发现进入了spring-boot-starter-parent-1.5.9.RELEASE.pom,我们看到spring-boot-starter-parent还依赖一个父项目spring-boot-dependencies
我们往下看,我们再次Ctrl+鼠标左键点进去spring-boot-dependencies,则打开spring-boot-dependencies-1.5.9.RELEASE.pom
我们看到下面properties部分,定义了每一个依赖的版本,后面还有很多
其实它才是真正的SpringBoot应用所有依赖管理,所以也可以把它称为“SpringBoot的版本管理中心”,所以以后我们写SpringBoot程序是不需要导入依赖版本的(没有在这个spring-boot-dependencies中管理的则需要写版本号声明)
2. 启动器
我们接着看我们的pom.xml,发现导入了依赖spring-boot-starter-web
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
这个依赖没有版本号,我们发现与上面的父项目都是一样的前缀spring-boot-starter(SpringBoot的场景启动器)
我们再次Ctrl+鼠标左键点进去spring-boot-starter-web
我们看到它的父项目是spring-boot-starters
我们看下面,导入了一些依赖
原来它帮我们导入了web项目所需要的依赖的组件,也就是场景启动器帮我导入了web项目所需要的依赖组件,但各个组件的版本依赖父项目spring-boot-starter-parent 中的版本管理
这种类似starters(场景启动器)的做法在SpringBoot中还有很多,例如我们访问SpringBoot的官网手册
https://docs.spring.io/spring-boot/docs/1.5.9.RELEASE/reference/htmlsingle/
我们搜索starters,我们看到还有类似的很多starters
也就是SpringBoot将所有的功能场景都抽取出来,做成每个starters(场景启动器),我们用的时候就导入相应的starters就可以了,相关的依赖就会导入进来,版本由SpringBoot自动控制。
我们接着看一下main方法
@SpringBootApplication这个注解的意思是:标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法,来启动SpringBoot应用
我们依然Ctrl+鼠标左键点@SpringBootApplication进去,我们发现是一个组合注解,我们点击右上角的“Download Sources”因为我们没有下载SpringBootApplication源码, 所以要点击下载源码,下载完成后就是SpringBootApplication.java
下载完成后,代码有颜色提示
我们一个一个的看一下
@SpringBootConfiguration : 标注在某个类上表示这是一个SpringBoot的配置类,而用同样的方法Ctrl + 鼠标左键点进去,我们看到底层就是@Configuration注解,与Spring的是一样的,
@Configuration :标注在某个类上表示这是一个配置类,与配置文件类似,以前开发Spring的应用需要编写很多的配置文件,很多很麻烦,我们把配置文件都替换成配置类,用注解式声明配置类,用同样的方法Ctrl + 鼠标左键点进去
我们看到其实它就是一个容器中的组件
我们看SpringBootApplication.java中的第二个注解
@EnableAutoConfiguration:开启自动配置功能
我们想想我们的工程没有配置包扫描也可以扫描、SpringMVC也启动起来了、应用也可以运行,这是怎么做到的呢?就是自动配置功能,也就是以前我们需要手动配置的,现在都是SpringBoot帮助我们自动配置了。
用同样的方法Ctrl + 鼠标左键点进去,
我们看到
@AutoConfigurationPackage:自动配置包
我们用同样的方法Ctrl + 鼠标左键点进去
我们看到它里面是
@Import(AutoConfigurationPackages.Registrar.class),而@Import就是Spring的底层注解,作用是给容器中导入一个组件,导入的组件由AutoConfigurationPackages.Registrar.class类来指定,怎么导入的呢?
我们用同样的方法Ctrl + 鼠标左键点AutoConfigurationPackages.Registrar.class进去
registerBeanDefinitions 这个方法就是注册一些Bean定义信息,通过注解标注到metadata元信息,然后getPackageName获取包名
我们在register方法上打一个断点,Debug调试一下,看它拿到的是什么包名
我们看到元信息中的SpringBootApplication是注解名,HelloWorldMainApplication是注解标注到的方法名
我们在getPackageName上右键-->Evaluate Expression...,我们计算一下包名
我们看到计算完的包名就是com.david
所以@AutoConfigurationPackage本身的含义就是将我们的主配置类HelloWorldMainApplication所在的包下面的所有的组件(包括子包下面的组件)都扫描进去
我们接着看,在@AutoConfigurationPackage注解下面还有一个注解@Import(EnableAutoConfigurationImportSelector.class):
这个就是导入组件EnableAutoConfigurationImportSelector.class,这个组件就是EnableAutoConfigurationImportSelector.class
开启自动配置导包选择器,它就是导入哪些组件的选择器
我们用同样的方法Ctrl + 鼠标左键点进去,它里面只有一个方法isEnabled
我们看它的父类AutoConfigurationImportSelector,里面有一个selectImports方法,这个方法就是告诉Spring容器到底要导入哪些组件,我们这些组件都是以String[]数组的形式返回组件的全类名,也就是将所有要导入的组件以全类名的方式返回,这些组件会被导入到容器中
我们Debug的方式运行一下,看看到底导入了哪些组件?
在public String[] selectImports(AnnotationMetadata annotationMetadata) 上设置一个断点
点击调试
运行到该处,我们可以看到元信息
按F8单步运行,直到我们看到List<String> 的对象configurations,我们看到后面都在用该对象,并且最后返回该对象的数组形式
说明它就是要返回的组件名称列表
我们再执行一次F8,让它运行到configurations,我们看到有96个组件,所以它的作用是给容器导入非常多的自动配置类(xxxAutoConfiguration),这些自动配置类的作用就是给容器中导入这个场景所需要的组件,并配置好这些组件
所以就不用手动编写配置了
那么自动配置类是怎么扫描到这些包的呢?
是在getCandidateConfigurations 获取候选的配置文件,我们Ctrl + 鼠标左键点进去
里面用到了SpringFactoriesLoader.loadFactoryNames方法,该方法传两个参数
第一个参数的值,点击进去,它就是EnableAutoConfiguration.class;
第二个参数是一个getBeanClassLoader 类加载器,我们点击进入SpringFactoriesLoader.loadFactoryNames,看一下它的作用,它用classLoader类加载器获取一个资源
然后将该资源当成一个Properties配置文件
然后从Properties中拿出factoryClassName
总结一下其实就是从"META-INF/spring.factories"中获取EnableAutoConfiguration指定的值
我们看一下导入的jar包中的这个路径的文件
我们看到这的配置就是我们导入的自动配置类
其实也就是SpringBoot启动的时候就是从"META-INF/spring.factories"中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效了,就帮我们进行自动配置工作了
我们随便看一下,我们现在是web应用,我们看一下
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration
我们点进去,这里就是WebMvc的自动配置,@Bean就是给容器中添加一个组件,后面会详细介绍
这是给容器中添加一些filter组件
往下看,这是给容器中添加一些视图解析器
也就是我们以前自己手动的一些配置都被这些自动配置类所替换了
我们看到这就是SpringBoot用AutoConfigure对所有的大整合
都在这 spring-boot-autoconfigure-1.5.9.RELEASE.jar