Spring Boot
为什么要用Spring Boot?与传统Spring框架的区别?
传统的Spring框架开发有几个痛点:
- 复杂的配置,大量的配置写在XML中,开发时需要了解太多的概念
- 混乱的依赖管理,所有的包都需要自己来导入,有可能每个包依赖的子包的版本不一样,调用方法时可能出现异常
- 项目部署时需要考虑tomcat的版本
- 混乱的依赖管理,所有的包都需要自己来导入,有可能每个包依赖的子包的版本不一样,调用方法时可能出现异常
在使用SpringBoot后这些问题都得到了解决,SpringBoot可以快速上手,不需要了解太多配置概念,也不需要大量XML配置,通过使用SpringBoot的版本管理可以避免包依赖的混乱,SpringBoot官方已经对包的相互依赖做了大量的测试,保证不会出现异常,并且SpringBoot内置了tomcat,部署时可以直接通过Java命令运行应用。
Spring Boot的自动配置原理
SpringBoot项目启动类都会添加@SpringBootApplication
注解,而这个注解的其中一个二级注解是@EnableAutoConfiguration
注解。而@EnableAutoConfiguration
注解通过@Import
注解,以ImportSelector
接口的方法来导入classpath下的META-INF/spring.factories
文件,这些文件中会指定需要加载的一些类名称。
这些类一般都加了@Configuration
注解,并且完成了对某框架(例如Redis、SpringMVC)的默认配置,当这些类符合条件时,就会被实例化,其中的配置生效,那么自动配置自然生效了。
满足怎样的条件配置才会生效?
一般提供默认配置的类都会添加@ConditionalOnXxx
这样的注解,例如:@ConditionalOnClass
,@ConditionalOnProperties
等。@ConditionalOnClass
表示只有classpath中存在某些指定的类时,条件满足,此时该配置类才会生效。例如Redis的默认配置其实早就有了,但是只有你引入redis的starter依赖,引入了条件特定的类,才满足了条件,触发自动配置。
那如果我需要覆盖这些默认配置呢?
有两种方式可以覆盖默认配置:
- SpringBoot提供默认配置时,会在提供的Bean上加注解@ConditionalOnMissingBean,意思是如果这个Bean不存在时条件满足,那么我们只要配置了相同的Bean,那么SpringBoot提供的默认配置就会失效
- SpringBoot提供默认配置时,一些关键属性会通过读取application.yml或者application.properties文件来获取,因此我们可以通过覆盖任意一个文件中的属性来覆盖默认配置。
SpringBoot项目的启动流程
SpringBoot项目启动第一步就是创建SpringApplication的实例,并且调用SpringApplication.run()这个方法。
创建SpringApplication实例主要完成三件事情:
- 记录当前启动类字节码
- 判断当前项目类型,普通Servlet、响应式WebFlux、NONE
- 加载/META-INF/spring.factories文件,初始化ApplicationContextInitializer和ApplicationListener实例
而后的run()方法则会创建spring容器,流程如下:
- 准备监听器,监听Spring启动的各个过程
- 创建并配置环境参数Environment
- 创建ApplicationContext
prepareContext()
:初始化ApplicationContext,准备运行环境refreshContext(context)
:准备Bean工厂,调用一个BeanDefinition和BeanFactory的后处理器,初始化各种Bean,初始化tomcatafterRefresh()
:拓展功能,目前为空- 发布容器初始化完毕的事件
怎么开发一个启动器项目?
首先添加一个starter项目,用户管理具体功能实现包的版本,再添加一个自动配置项目,实现自己要封装的功能,添加一个自动配置类,在配置类中将相应的功能注册成Bean,在Resources中添加META-INF/spring.factories,添加自动配置类所在的全路径
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\