- 什么是springboot ?
- SpringBoot的特点
Spring Boot、Spring MVC 和 Spring 有什么区别?- Springboot自动配置的原理
- SpringBoot原理
- 什么是嵌入式服务器?我们为什么要使用嵌入式服务器呢?
SpringBoot1 和Spring Boot 2差别- SpringBoot启动流程
- 组装SpringApplication
- 执行SpringApplication的run方法
- 获取SpringApplicationRunListeners
- prepareEnvironment(目前profile功能已经被maven取代了)
- createApplicationContext:创建spring的容器
- prepareContext:准备容器,在准备刷新容器前准备好容器
- refreshContext(context):真正的刷新spring容器
什么是springboot ?
SpringBoot是用来简化Spring应用开发,约定大于配置,去繁从简,通过run就能创建一个独立的、产品级别的应用
- 用来简化Spring应用开发的初始化搭建以及开发过程,使用特定的方式来进行配置
(properties或者yml文件)
- 创建独立的Spring应用程序,main方法执行
- 内嵌tomcat无需部署war文件
- 简化maven配置,自动配置Spring添加对应功能starter自动化配置
SpringBoot的特点
- 快速创建独立运行的Spring项目与主流框架集成
- 使用嵌入式的servlet容器,应用无需打包成war包
- starters自动依赖与版本控制
- 大量自动化配置,简化开发,也可以修改默认值
- 准生产环境的运行应用监控
-
Spring Boot、Spring MVC 和 Spring 有什么区别? Spring 框架就像一个家族,有众多的产品例如boot、secutity、jpa等等,但是他们的基础都是Spring的IOC和AOP,IOC提供了依赖注入的容器,AOP解决了面向横切面的编程,然后在此两者的基础上实现了其他延伸产品的功能
- SpringMVC是一个基于servlet的MVC框架,主要解决WEB开发问题。通过运用像DispatcherServelet、ModelAndView和ViewResolver等一些简单的概念,开发Web应用将会变得非常简单。
- 因为Spring的配置非常复杂,各种xml,处理起来比较繁琐,Spring Boot实现了自动配置,降低了项目搭建的复杂度。
Spring Boot只是承载者,辅助你简化项目搭建过程的。如果承载的是WEB项目,使用Spring MVC作为MVC框架,那么工作流程和你上面描述的是完全一样的,因为这部分工作是Spring MVC做的而不是Spring Boot。
对使用者来说,换用Spring Boot以后,项目初始化方法变了,配置文件变了,另外就是不需要单独安装Tomcat这类容器服务器了,maven打出jar包直接跑起来就是个网站,但你最核心的业务逻辑实现与业务流程实现没有任何变化。
所以,用最简练的语言概括就是:
Spring 是一个“引擎”;
Spring MVC 是基于Spring的一个 MVC 框架;
Spring Boot 是基于Spring4的条件注册的一套快速开发整合包。
因此他们的关系大概就是这样:
spring mvc < spring
Springboot自动配置的原理
在Spring程序main方法中,添加@SpringBootApplication或者@EnableAutoConfiguration。会自动去maven中读取每个starter中spring.factories文件,该文件里配置了所有需要被创建Spring容器中的bean
1)SpringBoot启动会加载大量的自动配置类
2)我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;
3)我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)
4)给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值;
SpringBoot原理
1.依赖管理,SpringBoot做了大量的stater,这样我们需要开发什么功能,就导入什么场景启动器依赖即可
2.自动配置,SpringBoot基于Spring代码配置提供了很多常用组件和框架配置类
3.内嵌Tomcat容器,直接java -jar运行
什么是嵌入式服务器?我们为什么要使用嵌入式服务器呢?
传统的虚拟机部署使用到的步骤如下:
第一步: 安装 Java
第二部: 安装 Web 或者是应用程序的服务器(Tomat/Weblogic 等等)
第三部: 部署应用程序 war 包
如果我们想简化这些步骤,应该如何做?让服务器成为应用程序的一部分?
你只需要一个安装了 Java 的虚拟机,就可以直接在上面部署应用程序了,非常的快捷方便
SpringBoot简化了这些步骤,创建一个可以部署的应用程序的时候,把服务器(例如,tomcat)嵌入到可部署的服务器中。
SpringBoot1 和Spring Boot 2差别
SpringBoot 2. 更改:
1. Java 8是最低版本
2. Tomcat 8.5版是最低的
3. Hibernate 5.2版是最低的
4. Gradle版本*3.4是最低的
SpringBoot启动流程
组装SpringApplication
1.resourceLoader:设置resourceload
2.设置primarySources:可以把启动类加载进入spring容器
3.webApplicationType:判断当前application应该运行在什么环境下
4.mainApplicationClass:找出main方法启动的class
执行SpringApplication的run方法
获取SpringApplicationRunListeners
1.从META-INF/spring.factories获取SpringApplicationRunListener的集合,并依次调用的SpringApplicationRunListener的starting方法—-即最终调用ApplicationListener的onApplicationEvent方法,发布springboot启动事件
prepareEnvironment(目前profile功能已经被maven取代了)
1.ConfigurableEnvironment:代表两种意义:一种是profiles,用来描述哪些bean definitions是可用的;一种是properties,用来描述系统的配置,其来源可能是配置文件、JVM属性文件、操作系统环境变量等等
2.getOrCreateEnvironment():根据webApplicationType创建不同的Environment
3.configureEnvironment(XX):通过configurePropertySources(environment, args)设置properties,通过configureProfiles(environment, args)设置profiles
4.listeners.environmentPrepared(environment);发布environmentPrepared事件,即调用ApplicationListener的onApplicationEvent事件
- bindToSpringApplication:即把当前的environment和当前的springApplication绑定
6.ConfigurationPropertySources.attach(environment):将ConfigurationPropertySource放入environment的propertysource中的第一个createApplicationContext:创建spring的容器
1.根据不同的webApplicationType设置不同的contextClass(容器的class类型),然后生成不同的容器实例对象
2.生成容器实例的时候,对于Kotlin类使用’primary’构造函数实例化一个类,如果不是就使用默认构造函数,根据得到构造函数生成实例对象,如果构造函数不是公共的,我们尝试去改变并访问prepareContext:准备容器,在准备刷新容器前准备好容器
1.context.setEnvironment(environment):设置spring容器的environment
2.postProcessApplicationContext(context):设置beanNameGenerator和resourceLoader
3.applyInitializers(context):调用ApplicationContextInitializer的initialize来初始化context,其中还检测各个ApplicationContextInitializer是否接受该类型的容器
4.listeners.contextPrepared(context);即调用SpringApplicationRunListener的contextPrepared方法,但目前是个空实现。
5.分别注册springApplicationArguments和springBootBanner这两个bean
6.getAllSources就是获取我们的primarySources和sources
7.load(context, sources.toArray(new Object[0])):首先创建BeanDefinitionLoader,设置该loader的sources,annotatedReader,xmlReader,scanner,以及添加scanner的ExcludeFilter(即过滤springboot的启动类),若用户启动的时候设置了beanNameGenerator,resourceLoader,environment的话就替代我们自身设置的属性。同时根据source的类型选择不同的load方法,这边我们是load(class),最终判断是否是component注解,是的话就通过annotatedReader将启动类注册成bean
8.listeners.contextLoaded(context):首先判断ApplicationListener是否属于ApplicationContextAware,如果是的话就将spring容器赋值给该listener,然后将该ApplicationListener赋值给spring容器,然后调用ApplicationListener的onApplicationEvent方法refreshContext(context):真正的刷新spring容器
一.refresh(context):
1.prepareRefresh():设置些初始的操作比如,开启激活,启动日期,初始化propertySource。
2.获取beanFactory
3.prepareBeanFactory(beanFactory):设置beanFactory的classloader,BeanExpressionResolver,PropertyEditorRegistrar,ApplicationContextAwareProcessor和忽略xxxxAware,注册依赖,还有ApplicationListenerDetector
ApplicationContextAwareProcessor:只是将applicationContext传递给ApplicationContextAwareProcessor,方便后面的xxxAware调用
忽略xxxxAware:忽略这些Aware接口实现类中与接口set方法中入参类型相同的属性的的自动注入这样就保证了关键的类是由spring容器自己产生的而不是我们注入的,自动注入不是指的@AutoWire 而是指的是beans的default-autowire=”byType” 或在bean的autowire=”byType” ,这样spring 回去ioc容器寻找类型相似的类型给其注入,如果实现了spring 的xxaware接口,就不会自动注入记载filterPropertyDescriptorsForDependencyCheck删除与入参类型相同的属性
注册依赖:即指定一些类自动注入的实例是spring指定的实例对象
ApplicationListenerDetector:检测实现了ApplicationListener的实现类,因为有些实现类,无法通过getBeanNamesForType获取到。
4.postProcessBeanFactory(beanFactory):继续设置ignoreDependencyInterface(ServletContextAware)还有annotatedClasses,basePackages如果存在就设置。
5.invokeBeanFactoryPostProcessors(beanFactory):从beanFactoryPostProcessors获取BeanFactoryPostProcessor,然后先执行BeanDefinitionRegistryPostProcessor类型的postProcessBeanDefinitionRegistry,继续从beanFactory获取BeanDefinitionRegistryPostProcessor类型的bean然后执行postProcessBeanDefinitionRegistry,执行的过程按照PriorityOrdered,Ordered,普通的类型进行执行,然后优先执行registryProcessors的postProcessBeanFactory在执行regularPostProcessors的postProcessBeanFactory,再从BeanFactory获取PriorityOrdered,Ordered,普通的类型三种类型的BeanFactoryPostProcessor,并按照顺序执行。总结:从之前加入的beanFactoryPostProcessor先执行postProcessBeanDefinitionRegistry(假如是BeanDefinitionRegistryPostProcessor)然后在执行postProcessBeanFactory方法,然后从beanFactory获取BeanFactoryPostProcessor 然后执行postProcessBeanFactory,执行过程中都要按照PriorityOrdered,Ordered,普通的类型三种类型的顺序执行。
6.registerBeanPostProcessors:从beanFactory获取BeanPostProcessor分别按照PriorityOrdered,Ordered,普通的类型注册BeanPostProcessor
7.BeanPostProcessor和BeanFactoryPostProcessor:前者是对bean初始化前后进行设置,后者可以对beanFactory进行修改 或者,可以对beanDefinition进行修改或者增加或者初始化渴望提前初始化的bean
8.initMessageSource():一般是我们用来初始化我们国际化文件的
9.initApplicationEventMulticaster():设置applicationEventMulticaster,spring发布各种事件就依靠他,这个和springboot发布事件使用相同的类
10.onRefresh():初始化其他的子容器类中的bean,同时创建spring的内置tomcat,这在后期Springboot内嵌式tomcat中详细阐述
11.registerListeners():添加用户设置applicationListeners,然后从beanFactory获取ApplicationListener,然后发布需要earlyApplicationEvents事件
12.finishBeanFactoryInitialization(beanFactory):实例化非懒加载的剩余bean
13.finishRefresh:清理资源缓存,初始化lifecycle,调用lifecycle的onrefresh,发布ContextRefreshedEvent的事件,激活JMX,启动tomcat
二.context.registerShutdownHook():注册一个线程,该线程主要指向doclose方法,doClose方法的逻辑就是:从applicationContexts集合中删除当前容器,MBeanServer卸载MBean,发布容器关闭事件,调用了实现了lifecycleProcessor接口的bean,destroyBeans,closeBeanFactory,onClose:关闭内置tomcat,active设置为falseafterRefresh(context, applicationArguments):目前是空的实现
listeners.started(context):发布started事件
callRunners(context, applicationArguments)
1.从spring容器中获取ApplicationRunner和CommandLineRunner对象,然后按照顺序排序,循环调用他们的run方法handleRunFailure(context, ex, exceptionReporters, listeners)
1.处理不同的异常状态,然后调用listeners.failed(context, exception),并关闭spring容器listeners.running(context):发布running事件