微服务框架之SpringBoot分析

1.启动流程


1.1new SpringApplication()框架初始化

  • 配置resourceLoader
  • 配置primarySources
  • 配置webApplicationType(推断环境类型:servlet,None,reactive反应式编程)
  • 配置ApplicationContextInitializer(实现该接口的类通常会设置一些环境有关的属性变量,有三种配置实现类的方式
  • 实现类会在refresh方法刷新上下文前,准备上下文时调用,且通过order注解进行排序

ps:推荐)spring.factories中key=xxx,application.properties中key=xxx,SpringApplication类初始化后设置进去

  • 底层实现1:SpringFactoriesLoader读取指定jar包配置文件下(类似:META-INF/spring.factories)的key=value对,然后通过反射进行加载类,再根据order排序。
  • 底层实现2:DelegatingApplicationContextInitializer(order=0,会直接加载property进行调用)框架内部的实现类,先从application.properties加载对应的类,再调用加载的类调用初始化,而且默认的order值为0最先进行加载该实现类。
  • 底层实现3:实现类直接加入list中,硬编码方式(初始化属性已经加载完了,然后进行addInitializers,还没有run)。
  • 配置ApplicationListener(除了三种常规方式实现ApplicationListener接口并且设置泛型对应具体的事件类型,还有一种实现SmartApplicationListener接口可以自己定义事件类型匹配方式
  • 原理:通过监听器对应的事件类型和传入的事件类型进行匹配,进行获取到对应的监听器进行执行;
  • 事件发送顺序:starting--environmentPrepared--contextInitialized--prepared--started--ready--执行完成最终启动完毕
  • 调用监听器:通过 EventPublishingRunListener 类 组装事件/广播器/监听器 来方便进行调用,每个事件都会进行匹配对应的监听器,匹配成功后调用监听器的onApplicationEvent方法 执行。

ps:监听器模式三大件,监听器、事件、主题/广播(multicaster),把这三者组合起来称为EventPublishingRunListener 。通常情况是把监听器模式作为一个服务,需要一个EventRunListener 类将广播器和监听器以及事件都组合起来方便调用。

  • 配置mainApplicationClass(如果当前类包含main方法就说明是主类,通过打印栈信息判断)

1.2SpringApplication().run框架启动

  • 计时器开始计时
  • 设置java.awt.handless
  • 发送ApplicationStartingEvent
  • 设置ApplicationArguments
  • 配置环境(加载配置的属性属性)
  • 四种Banner:默认banner、文字banner(设置spring.banner.location)、图片banner(设置spring.banner.image.location)、(txt和png都不存在的时候设置了才会执行)兜底banner(springApplictaion.setBanner)
  • 设置关闭Banner的两种:(1.properties文件设置spring.main.banner-mode=off、2.启动类设置Banner.Mode.OFF)
  • Banner获取原理:先判断是否禁止打印banner,获取imageBanner,获取textBanner(默认为banner.txt),判断如果不为空就返回获取到的banner,如果banner为空在判断兜底banner是否为空,不为空返回兜底banner,如果为空就只能返回默认的banner
  • banner输出:将banners集合遍历调用打印;
  • 上下文配置
  • 配置失败记录器
  • 准备上下文prepareContext
  • 刷新上下文refreshContext(实际调用spring里的refresh方法)

ps:在refresh方法里的onRefresh方法创建WebServerFactory(从容器获取)在基于此创建WebServer,在finishRefresh方法里启动WebServer并且发布事件。

  • 计时器停止计时
  • 发送ApplicationStartedEvent
  • 回调runners(在SpringBoot启动结束后立马执行对应的程序,启动加载器,实现CommandLineRunner接口;实现ApplicationRunner接口;加Component注解即可)

ps:通过order值指定顺序,如果order值相同ApplicationRunner实现先执行

  • 原理:先加入ApplicationRunner实现类再加入CommandLineRunner实现类,并根据order值排序,在迭代调用run方法
  • 发送ApplicationReadyEvent

1.3属性配置

属性设置

  • 通过SpringApplication编码方式设置属性(springApplication.setDefaultProperties());
  • 通过properties/yml文件设置,并使用@ImportSource("classpath:xxx.yml")注解导入spring配置文件
  • 通过命令行参数设置;

 

  • 通过properties/yml文件设置,并使用@PropertySource("classpath:xxx.yml")注解引入外部配置文件
  • 需要配合@ConfigurationProperties或者@Value("${xxx}")注解,因为只是把对应的文件加载进来而已

 

  • 通过properties/yml文件设置,并使用@ConfigurationProperties注解读取配置文件配置的属性(该类还要加上@Component注解);
  • 原理:通过自动装配@EnableConfigurationProperties注解里面包含@Import注解,以及在Bean初始化根据注册的ConfigurationPropertiesBindingPostProcessor类来进行初始化时的处理,具体为@ConfigurationProperties注解信息和类信息获取属性并进行设置值;
  • 是在初始化的时候进行赋值的

 

  • 通过properties/yml文件设置,并使用@Value("${xxx}")注解绑定配置文件;
  • 原理:不是通过set方法进行赋值;是在属性注入的时候进行赋值的

 

  • 通过实现Aware接口,会在bean初始化前后进行回调方法时进行设置bean的属性

ps:自定义实现Aware,定义一个接口继承Aware并且定义setXxx方法,写一个BeanPostProcessor实现类,将Xxx类注入容器,写一个类实现MyAware接口;​​​​​​​​​​​​​​​​​​​​​

属性加载与获取

  • 创建environment然后逐步将属性全部加载进propertySources里的propertySource里,基于此来进行获取加载到的属性。

属性环境切换

  • profile指定特定环境的属性配置;application-{profile}.properties(如果不指定默认为application.properties)
  • (命令行里配置spring.profiles.dafault=application-xxx文件,也可配置spring.profiles.active=dev/prod/test)
  • 使用yml配置的话使用方法是不相同的,支持多文档块配置;

配置文件加载顺序--优先级从高到低:

  • file:../config/  不会加载到jar包
  • file:../ 不会加载到jar包 
  • classpath:/config/
  • classpath:/
  • 这四个文件不同的属性会形成互补,相同属性优先级高的进行替换;
  • 通过打包方式启动,需要加上spring.config.location=xxx才可;

外部配置加载顺序--优先级从高到低:

  • 1.命令行参数  java jar xxxx.jar --server.port=8087
  • ~2.来自java:comp/env的JNDI属性
  • ~3.Java系统属性(System.getProperties())
  • ~4.操作系统环境变量
  • ~5.RandomValuePropertySource配置的random.*属性值
  • 6.jar包外部的application-{profile}.properties(优先)或application.yml(带spring.profile)配置文件
  • 7.jar包内部的application-{profile}.properties(优先)或application.yml(带spring.profile)配置文件
  • 8.jar包外部的application.properties(优先)或application.yml(不带spring.profile)配置文件
  • 9.jar包内部的application.properties(优先)或application.yml(不带spring.profile)配置文件
  • 10.@Configuration注解类上的@PropertySource(引入外部配置文件)
  • 11.通过SpringApplication.setDefaultProperties指定的默认属性

1.4自动装配

  • spring.factories里设置自己的配置实现以供环境变量加载进去,然后就可以自动注入到容器中去。

原理:

  • 通过EnableAutoConfiguration注解实现,里面包含Import注解,它会导入AutoConfigurationImportSelector类。
  • 注入过程会过滤不必要的类,@Conditional注解会在某个条件满足的情况下会进行创建Bean;

ps:@Conditional(MyCondition.class)会在该类的matches匹配的情况下才会创建Bean

  • 最后才会将要注册到容器的类返回;

你可能感兴趣的:(Spring,Boot)