SpringBoot核心就是两大块:
第一个,就是自动化配置:
SpringBoot提供了一套通用的配置机制,让我们配置文件里配的这些属性直接全部的能够通过简化的方式,通过这些默认值的方式,然后在运行期把他对应到我么要装配的这些类上去,说起来还是很抽象,我们一会通过一个具体的实例来看,
第二个就是定义了很多spring-boot-starter,比如说Web的starter,WebMVC的starter,JDBC的starter,mybatis的starter。各种starter。这个starter是什么呢?就是把对应的这个框架这个技术跟SpringBoot,Spring体系中间粘起来,如果我们说Spring就是一个框架,划分好这种格子,骨架全都有了,中间没有填具体的内容,那SpringBoot它里面的这些starter,官方就有一两百个,这些starter就相当于已经帮我们把要往格子里填的那些其他的框架其他的组件中间糊了一层胶水,这个starter就是那层胶水,这样的话,你就不需要做任何其他的操作,直接可以把对应的第三方的那个框架,那个组件插在Spring体系里面去。
在SpringBoot里我们配置配置文件默认的情况下可以用application.yaml或者application.properties这样的配置文件,这两个文件是一样的。作为他的入口点,而且这两个文件的名字是定死的。 在这两种文件里都是文本的,一个是有层次结构有缩进的,一个就像我们正常使用的properties,全是key=value的方式。那么我们所有的配置,前面的key都是a.b.c.d这种方式来配的,同意让他们按照前缀来进行区分和分组,比如说我们常用的spring.web,这个前缀表示是SpringWeb模块使用的配置,那他在后面配的各种参数就会最终提供给SpringWeb这个starter用。把SpringWeb相关的这些组件拉起来,把参数塞进去,
所以我们具体来看一下我们通过application.yaml或者properties配置了各种参数,再在SpringBoot加载启动的时候通过我们的各种配置类和自动配置的这些类(Configuration)加载上来,再通过这些Configuration配置最终把我们的Spring容器里的Bean生成创建出来,然后把他初始化好,通过这个链条就把SpringBoot整个拉起来了。
在我们的properties和yaml文件里面主要是用前缀来区分不同的参数配置,相同的前缀组成了一组配置。
一组配置都是提供给具体的某个组件的,或者我们叫某个starter。
所有装配的单元都是以starter为单位的,每个starter就相当于是在Spring框架里面我们往中间的某个格子里插过去的。在Spring整个体系相当于一大面墙,墙上插进去一个组件,或者集成进去的一个框架。
说到这里就不得不提SpringBoot里我们有一个很重要的一个原则,就叫约定大于配置。SpringBoot通过约定大于配置帮我们天然的已经定义好了很多规则,很多的默认的行为,默认的参数,这样的话就使得我们,比如说我们想new出来一个最简单的这样一个应用程序,Web应用程序还是CS应用程序,这样一个demo几乎可以说是少量的代码,甚至零代码零配置都可以run起来。这种特点我们一般有一个名词,叫开箱即用。就相当于你去买个东西买回来以后,包装一拆就能用。不需要你自己再去做任何的组装。
举个例子,JVM里面有1000多个参数,但是咱们正常使用的时候,如果常规下开发测试的时候,不需要条约的时候,你可以不使用任何的参数,直接用java,后面类名字就可以把我们一个java程序直接给run起来。这1000多个参数一个都没有配,为什么呢,他都默认给了你默认值。给了你一些相关的这种参数的组合。当你需要额外的去定制,额外的去调优它,根据你的一些软硬件条件,系统运行的一些特点、访问量等去调他的时候,你才需要去精确的调校相关的参数。这种思想我们现在用得越来越多了,就是先给大家一个通用的版本,里面的东西是按照各种配方搭配好的,可以满足绝大部分的需求,如果你有额外的需求在另说。在上面做一些相关的定制就好了。
具体说来在SpringBoot里我们常见的有如下的一些重要的默认约定:
说了那么多,那么SpringBoot这两大核心原理:自动装配,自动配置和starter机制这种拟合的脚手架,到底是什么原理。怎么run起来的,怎么起作用的。这就是我们接下来讲的重点。
这里有一个自动化配置的简化的一个模型:
首先我们每个SpringBoot程序都需要有一个入口,这个入口里面需要有一个入口函数,就是我们静态的main方法。这里面我们可用SpringApplication,这是SpringBoot自带的。.run当前这个类,在这个类上我们可以用@EnableAutoConfiguration。
有了这样一个入口,接下来我们可以定义一个我们需要配置的比如一个WebConfiguration这样一个类。大家需要注意的是,这个类作为一个配置类,我们就需要在它上面加一个注解,@Configuration表示它是用来做配置的类。然后在它上面需要加两个注解。一个是跟刚才一样@Configuration表示他是一个配置的类,另外一个注解也非常重要,就是@Import(WebConfiguration.class),表明这个AutoConfiguration类是用来自动的装配WebConfiguration这个类的。然后接下来我们也可以在当前的应用程序里,在resources/META-INF下面,创建一个文件,spring.factories,在里面把我们这个WebAutoConfiguration,自动配置的这个类给注进去,前面的key是EnableAutoConfiguration:这个类的权限类名称。然后他的值就是我们刚才写的这个WebAutoConfiguration。
当SpringBoot他扫描所有的jar包里,只要在里面找到了META-INF下面有spring.factories文件,就会把里面这些AutoConfiguration的这样一些类全部拉出来,然后按需要进行配置。
当我们很多情况下啥也不配,都会取默认值。如果在配置文件里指定一些配置值,就会把默认值覆盖。甚至我们可以做一些在配置里,前缀有这些匹配的驱动的部分,当我们配置了这样一些前缀的属性在配置文件里,他才会真正的去初始化这样的一些组件。这就是所谓的各种条件化装配。
此外SpringBoot在他自己启动的时候也会加载大量的默认可以自动化配置这样的一些组件。都在spring.factories文件中。
@SpringBootApplication
SpringBoot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就会运行这个类的main方法来启动SpringBoot项目。
@SpringBootApplication上面组合了其他的注解:
@SpringBootConfiguration。
这块就是SpringBoot自己需要去做刚才那些自定义的一些加载,需要去做装配的东西。
@EnableAutoConfiguration。
自动的配置,如果我们有很多自定义的、自动配置的东西,通过他来拉。
@AutoConfigurationPackage。
有些包要去扫描,要去把他下面的很多文件需要自动配置的东西扫描,然后进行配置。
@Import(AutoConfigurationImportSelector.class)。
前面我们看到SpringBoot里面可能要加载的有非常非常多的AutoConfiguration相关的类,这些类里面哪些是需要加载的,哪些是不需要加载的,怎么来从中选择一些我们需要的,这个注解就会帮我们做这一系列的事情。最终就会把那些我们现在SpringBoot项目需要的那些依赖需要的那些组件,需要的那些AutoConfiguration转配进来。把他们拉起来。再用我们的各种参数来组装他们,最终就变成了我们Spring容器里的装配好,配置好了这些Bean,然后我们就可以使用了。
加载所有META-INF/spring.factories中存在的配置类(类似SpringMVC中加载所有converter)。
所谓的条件化自动配置,为什么会有这个东西?大家想一想,我们配置了那么多那么多东西,他们如果相互之间运行期冲突了怎么办?比如说我们引入了两个数据库连接池,每一个数据库连接池,它的自动化装配这块都想用自己来创建一个数据库连接池。但是我们一般情况下一个应用系统只有一个数据库,这时候有两个,Spring进行各种自动化的配置这种注入的时候可能就报错了,不允许有两个,怎么办呢?这个时候我们就需要这些所谓的条件化的自动化配置。帮我们根据一些条件来判断,我们是要创建装配这个类的一个实例变成一个Bean放在我们的Spring容器里。还是我们这次初始化就不干了,当发生冲突的时候只有有的这种配置做出让步,才能把这次冲突消灭于无形。
所以Conditional这一系列的条件化的自动配置,就让我们把整个Spring容器里的所有的Bean他们相互之间的关系、装配这个过程变得非常的灵活,虽然我们代码写好了,注解也写好了,但是根据我们运行时的一些状态,启动的一些顺序等等。包括我们的环境都不同,就可以让我们最终拉起来的这些Bean,他们是不同的。
此外我们还可以通过自定义的方式,我们再去额外的定义一些Conditional,定义一些我们需要的条件,匹配某个具体的一个条件。一个方式。比如一个系统的恒变量等等。总之这块你想要多灵活你就可以把它做到多灵活。通过这种运行时的灵活的配置,我们就使得一套程序可以适应不同的环境,产生不同的作用。