随着Spring不断的发展,涉及的领域越来越多,需要的配置文件也越来越多。配置日益繁琐(配置地狱)
SpringBoot正是在这样的背景下被抽象出来的开发框架。
与Spring联系
spring发展到一定程度后,人们根据实际生产应用情况,选取其中实用功能和设计精华,重构出一些轻量级的框架;之后为了提高开发效率,嫌弃原先的各类配置过于麻烦,于是开始提倡“约定大于配置”,进而衍生出一些一站式的解决方案。
- Springboot基于spring开发而来,Spirng Boot 本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于 Spring 框架的应用程序。也就是说,它并不是用来替代 Spring 的解决方案,而是和 Spring 框架紧密结合用于提升 Spring 开发者体验的工具。
- Spring Boot 以约定大于配置的核心思想,默认帮我们进行了很多设置,多数 Spring Boot 应用只需要很少的 Spring 配置。
- 同时它集成了大量常用的第三方库配置(例如 Redis、MongoDB、Jpa、RabbitMQ、Quartz 等等),Spring Boot 应用中这些第三方库几乎可以零配置的开箱即用。即SpringBoot整合了所有框架,是一个大杂烩
springcloud是依赖于springboot而构建的一套微服务治理框架
Spring Boot主要优点:
为所有Spring开发者更快的入门
- 开箱即用,提供各种默认配置来简化项目配置
- 内嵌式容器简化Web项目(即内嵌了web服务器,默认是Tomcat)
- 没有冗余代码生成和XML配置的要求
简化开发最重要的即是自动装配,这也是SpringBoot最重要,最需要掌握。
Bean的生命周期
- Bean 容器找到配置文件中 Spring Bean 的定义。
- Bean 容器利用 Java Reflection API 创建一个 Bean 的实例。
- 如果涉及到一些属性值 利用 set()方法设置一些属性值。
- 如果 Bean 实现了
BeanNameAware
接口,调用setBeanName
()方法,传入 Bean 的名字。 - 如果 Bean 实现了
BeanClassLoaderAware
接口,调用setBeanClassLoader()
方法,传入 ClassLoader对象的实例。 - 如果 Bean 实现了 BeanFactoryAware 接口,调用 setBeanFactory()方法,传入 BeanFactory对象的实例。
- 与上面的类似,如果实现了其他 *.Aware接口,就调用相应的方法。
- 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessBeforeInitialization() 方法
- 如果 Bean 实现了InitializingBean接口,执行afterPropertiesSet()方法。
- 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
- 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessAfterInitialization() 方法
- 当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。
- 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。
图示:
1:实例化 Bean:对于 BeanFactory 容器,当客户向容器请求一个尚未初始化的 Bean 时,或初始化 Bean 的时候需要注入另一个尚未初始化的依赖时,容器就会调用 createBean 进行实例化。对于 ApplicationContext 容器,当容器启动结束后,通过获取 BeanDefinition 对象中的信息,实例化所有的 Bean;
2:设置对象属性(依赖注入):实例化后的对象被封装在 BeanWrapper 对象中,紧接着 Spring 根据 BeanDefinition 中的信息以及通过 BeanWrapper 提供的设置属性的接口完成依赖注入;
3:处理 Aware 接口:Spring 会检测该对象是否实现了 xxxAware 接口,并将相关的 xxxAware 实例注入给 Bean:
3.1:如果这个 Bean 已经实现了 BeanNameAware 接口,会调用它实现的 setBeanName(String BeanId) 方法,此处传递的就是 Spring 配置文件中 Bean 的 id 值;
3.2:如果这个 Bean 已经实现了 BeanFactoryAware 接口,会调用它实现的 setBeanFactory() 方法,传递的是 Spring 工厂自身;
3.3如果这个 Bean 已经实现了 ApplicationContextAware 接口,会调用 setApplicationContext(ApplicationContext) 方法,传入 Spring 上下文;
4:BeanPostProcessor:如果想对 Bean 进行一些自定义的处理,那么可以让 Bean 实现了 BeanPostProcessor 接口,那将会调用 postProcessBeforeInitialization(Object obj, String s) 方法;
5:InitializingBean 与 init-method:如果 Bean 在 Spring 配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法;
6:如果这个 Bean 实现了 BeanPostProcessor 接口,将会调用 postProcessAfterInitialization(Object obj, String s) 方法;由于这个方法是在 Bean 初始化结束时调用的,因而可以被应用于内存或缓存技术;
以上几个步骤完成后,Bean 就已经被正确创建了,之后就可以使用这个 Bean 了。
7:DisposableBean:当 Bean 不再需要时,会经过清理阶段,如果 Bean 实现了 DisposableBean 这个接口,会调用其实现的 destroy() 方法;
8:destroy-method:最后,如果这个 Bean 的 Spring 配置中配置了 destroy-method 属性,会自动调用其配置的销毁方法。
框架中的设计模式
- bean的单例作用域时使用到了单例模式,而原型模式使用到了原型模式(原型即创建新的对象,但是新对象跟旧对象的属性差不多,原型采用clone()实现快速复制一个,比直接new,然后set效率更高)
- 观察者模式:如ApplicationListener 监听指定动作的触发
- 策略模式:spring aop使用动态代理时,被代理对象实现了接口就使用jdl动态代理,未实现接口使用cglib,这便是策略模式
自动装配原理
- SpringBoot 定义了一套接口规范,这套规范规定:SpringBoot 在启动时会扫描外部引用 jar 包中的
META-INF/spring.factories
。将文件中配置的类型信息加载到 Spring 容器,并执行类中定义的各种操作。- 没有 Spring Boot 的情况下,如果我们需要引入第三方依赖,需要手动配置,非常麻烦。但是,Spring Boot 中,我们直接引入一个 starter 即可。
自定义Starter
- 创建一个模块。引入 Spring Boot 相关依赖
- 创建bean配置
- 一般都会配合
@ConditionalOnXXX
定义,防止自动装配的bean和用户自定义的bean冲突
- 一般都会配合
- 在resources下创建
META-INF/spring.factories
文件 - 最后在其他springboot项目里引入该模块作依赖,并注入我们配置的bean,发现能直接使用该bean,并且该bean是我们定义的配置
SpirngBoot2.0版本兼容问题
- Spring Boot 2.0 支持最低的 JDK 版本是jdk8。
- springboot2.0无法运行在低于tomcat8的版本上,因为 Spring Boot 2.0 使用的是 Spring Framework 5,Spring Framework 5 使用的是 Servlet 3.1,而 Tomcat 7 最高支持到 Servlet 3.0,所以 Spring Boot 2.0必须最低tomcat8