SpringBoot入门(十二)原理解析
发布日期:2022-03-04 11:48:27 浏览次数:1 分类:技术文章

本文共 9546 字,大约阅读时间需要 31 分钟。

目录


第十二章 原理解析

12.1 Profile功能

   为了方便多环境适配,springboot简化了profile功能,简化了环境的切换导致需要修改配置文件

12.1.1 application-profile功能

  • 默认配置文件application.yaml,任何时候都会加载
  • 指定环境配置文件application-{env}.yaml
  • 激活指定环境
    • 配置文件激活
    • 命令行激活:java -jar xxx.jar --spring.profiles.active=prod --person.name=haha
      • 修改配置文件的任意值,命令行优先
  • 默认配置与环境配置同时生效
  • 同名配置项,profile配置优先

server.port=8080 #同名配置#在配置文件中指定激活的环境,默认配置文件和指定环境的配置文件都会生效,但是同名属性会覆盖spring.profiles.active=prod

12.1.2 @Profile条件装配功能

   当加上了@Profile注解,可以使某个环境的条件下这个组件才生效:

public interface Person {   String getName();   Integer getAge();}
@Profile(value = {"prod","default"}) //prod、default环境下生效@Component@ConfigurationProperties("person")//读取配置文件中person开头的值@Datapublic class Boss implements Person {
private String name;
private Integer age;}
@Profile("test")@Component@ConfigurationProperties("person")@Datapublic class Worker implements Person {
private String name;
private Integer age;}

   除了标在类上,也可以标在方法上:

@Configurationpublic class MyConfig {
@Profile("prod")
@Bean
public Color red(){
return new Color();
}
@Profile("test")
@Bean
public Color green(){
return new Color();
}}

12.1.3 profile分组

spring.profiles.active=myprod#生产环境组spring.profiles.group.myprod[0]=ppdspring.profiles.group.myprod[1]=prod#测试环境组spring.profiles.group.mytest[0]=test

12.2 外部化配置

   比如把数据库的登录信息等不是固定写死在配置文件中,而实抽取出现写在一个外部配置文件中

12.2.1 外部配置源

   常用:Java属性文件YAML文件环境变量命令行参数

        比如获取环境变量的值:

@RestControllerpublic class HelloController {
@Value("${MAVEN_HOME}")
private String msg;
@GetMapping("/msg")
public String getMsg(){
return msg+"==>"+osName;
}}

         获取系统的环境变量和属性:

@SpringBootApplicationpublic class Boot09FeaturesProfileApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(Boot09FeaturesProfileApplication.class, args);
ConfigurableEnvironment environment = run.getEnvironment();
Map  systemEnvironment = environment.getSystemEnvironment();
Map  systemProperties = environment.getSystemProperties();
System.out.println(systemEnvironment);
System.out.println(systemProperties);
}}

12.2.2 配置文件查找位置

   application.propertiesapplication.yaml文件读取位置:

  • classpath 根路径

  • classpath 根路径下config目录

  • jar包当前目录

  • jar包当前目录的config目录

  • /config子目录的直接子目录

12.2.3 配置文件加载顺序

  1. 当前jar包内部的application.properties和application.yml

  2. 当前jar包内部的application-{profile}.properties和application-{profile}.yml

  3. 引用的外部jar包的application.properties和application.yml

  4. 引用的外部jar包的application-{profile}.properties和application-{profile}.yml

12.2.4 关键

   指定环境优先,外部优先,后面的可以覆盖前面的的同名配置项

12.3 自定义starter

12.3.1 starter启动原理

  • starter-pom引入autoconfigurer包

12.3.2 自定义starter

  • atguigu-hello-spring-boot-starter(启动器)

  • atguigu-hello-spring-boot-starter-autoconfigure(自动配置包)

        pom.xml文件:

   
   
    
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0

org.springframework.boot
spring-boot-starter-parent
2.4.0
 

com.atguigu
atguigu-hello-spring-boot-starter-autoconfigure
0.0.1-SNAPSHOT
atguigu-hello-spring-boot-starter-autoconfigure
Demo project for Spring Boot

1.8



org.springframework.boot
spring-boot-starter

   在配置文件中自动注入需要的类:

/** * 默认不要放在容器中 */public class HelloService {
@Autowired
HelloProperties helloProperties;
public String sayHello(String userName){
return helloProperties.getPrefix() + ":"+userName+"》"+helloProperties.getSuffix();
}}
@ConfigurationProperties("atguigu.hello")public class HelloProperties {
private String prefix;
private String suffix;
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}}
@Configuration@EnableConfigurationProperties(HelloProperties.class)  //默认HelloProperties放在容器中public class HelloServiceAutoConfiguration{
@ConditionalOnMissingBean(HelloService.class)
@Bean
public HelloService helloService(){
HelloService helloService = new HelloService();
return helloService;
}}

        在类路径下创建一个META-INF文件夹,这个文件夹下有一个文件spring.factories:

# Auto Configure# 指定项目一启动要加载哪个包哪个自动配置类org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.atguigu.hello.auto.HelloServiceAutoConfiguration

   此时可以在其他项目中引入这个自定义的starter场景:

    
     
com.atguigu
atguigu-hello-spring-boot-starter
1.0-SNAPSHOT
#在配置文件中定义属性atguigu.hello开头atguigu.hello.prefix=ATGUIGUatguigu.hello.suffix=88888

12.4 SpringBoot原理

   SpringBoot原理【Spring注解】、SpringMVC原理、自动配置原理、SpringBoot原理

12.4.1 SpringBoot启动过程

  • 创建SpringApplication
    • 保存一些信息
    • 利用工具类ClassUtils判定当前应用的类型,一般就是Servlet类型
    • bootstrappers初始启动引导器(List<Bootstrapper>):去spring.factories文件中找 org.springframework.boot.Bootstrapper

    • 初始化器ApplicationContextInitializer去spring.factories找ApplicationContextInitializer
      • List<ApplicationContextInitializer<?>> initializers
    • 应用监听器ApplicationListener去spring.factories找ApplicationListener
      • List<ApplicationListener<?>> listeners
  • 运行SpringApplication
    • StopWatch:监控整个项目的启停
    • 记录应用的启动时间
    • createBootstrapContext():创建引导上下文(Context环境)
      • 获取到所有之前的bootstrappers挨个执行intitialize()来完成对引导启动器上下文环境设置
    • 让当前应用进入headless模式,java.awt.headless
    • 获取所有RunListener(运行监听器)【为了方便所有Listener进行事件感知】
      • getSpringFactoriesInstances去spring.factories找SpringApplicationRunListener
    • 遍历SpringApplicationRunListener调用starting方法
      • 相当于事件通知机制,项目正在starting
    • 保存命令行参数,ApplicationArguments
    • 准备环境prepareEnvironment()

      • 返回或者创建基础环境信息对象,StandardServletEnvironment
      • 配置环境信息对象

        • 读取所有的配置源的配置属性值

      • 绑定环境信息
      • 监听器调用listener.environmentPrepared(),通知所有的监听器当前环境准备完成
    • 创建IOC容器,createApplicationContext()
      • 根据项目类型创建容器,一般为Servlet

      • 当前Servlet类型会创建AnnotationConfigServletWebServerApplicationContext
    • 准备ApplicationContext IOC容器的基本信息,prepareContext()
      • 保存环境信息
      • IOC容器的后置处理流程

      • 应用初始化器applyInitializers

        • 遍历所有的ApplicationContextInitializer,调用initialize来对ioc容器进行初始化扩展功能(可以自定义initialize)
        • 遍历所有的listener调用contextPrepared,EventPublishRunListenr通知所有的监听器contextPrepared
      • ​​​​​​​所有的监听器调用contextLoaded,通知所有的监听器contextLoaded
    • 刷新IOC容器,refreshContext
      • 创建容器中的所有组件(Spring注解)
    • 容器刷新完成后工作,afterRefresh

    • 所有监听器调用listeners.started(context),通知所有的监听器started
    • 调用所有runners,callRunners()

      • 获取容器中的ApplicationRunner
      • 获取容器中的CommandLineRunner
      • 合并所有runner并且按照@Order进行排序
      • 遍历所有的runner,调用 run 方法
    • 如果以上有异常

      • 调用Listener的failed
    • 如果没有异常,调用所有监听器的running方法,listeners.running(context),通知所有的监听器running
    • running如果有问题,继续通知failed,调用所有Listener的failed,通知所有的监听器 failed

12.4.2 Application Events and Listeners

  • ApplicationContextInitializer

  • ApplicationListener

  • SpringApplicationRunListener

   可以自动义组件:在启动过程中某些时机增添自己需要的功能

public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("MyApplicationContextInitializer ....initialize.... ");
}}
public class MyApplicationListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("MyApplicationListener.....onApplicationEvent...");
}}
public class MySpringApplicationRunListener implements SpringApplicationRunListener {
private SpringApplication application;
public MySpringApplicationRunListener(SpringApplication application, String[] args){
this.application = application;
}
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
System.out.println("MySpringApplicationRunListener....starting....");
}
@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
System.out.println("MySpringApplicationRunListener....environmentPrepared....");
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("MySpringApplicationRunListener....contextPrepared....");
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.out.println("MySpringApplicationRunListener....contextLoaded....");
}
@Override
public void started(ConfigurableApplicationContext context) {
System.out.println("MySpringApplicationRunListener....started....");
}
@Override
public void running(ConfigurableApplicationContext context) {
System.out.println("MySpringApplicationRunListener....running....");
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
System.out.println("MySpringApplicationRunListener....failed....");
}}

12.4.3 ApplicationRunner 与 CommandLineRunner

   runner接口:

@FunctionalInterfacepublic interface ApplicationRunner {
/**
 * Callback used to run the bean.
 * @param args incoming application arguments
 * @throws Exception on error
 */
void run(ApplicationArguments args) throws Exception;}
@FunctionalInterfacepublic interface CommandLineRunner {
/**
 * Callback used to run the bean.
 * @param args incoming main method arguments
 * @throws Exception on error
 */
void run(String... args) throws Exception;}

   可以自定义组件:

@Order(1)@Componentpublic class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("MyApplicationRunner...run...");
}}
/** * 应用启动做一个一次性事情 */@Order(2)@Componentpublic class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("MyCommandLineRunner....run....");
}}

PS:根据尚硅谷视频整理,如有侵权,联系删除

转载地址:https://blog.csdn.net/xxyneymar/article/details/122818042 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:SpringBoot入门(十一)指标监控
下一篇:豆瓣前250个电影的相关分析

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.36.148.197]2022年07月30日 01时59分50秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

最新文章

韶关学院计算机专插本专业怎么样,2020年韶关学院专插本各专业计划人数和报考人数情况分析... 2020-01-10 11:49:25
西北工业太学计算机科学与技术周世钢,周世钢_西北工业大学研究生导师信息... 2020-01-10 11:49:25
电子计算机管理应用,电子计算机在企业管理中的应用研究分析原稿(全文完整版)... 2020-01-10 11:49:25
计算机组成原理八位全加器,8位全加器-课程设计 2020-01-10 11:49:25
计算机考研能换专业吗,我本科学的是计算机专业,现在想考研,但是想换一个适合自己的专业,和教育方面有关的专业,请问有什么好专业能选择的么?... 2020-01-10 11:49:25
从S3获取数据在html表示,javascript – 显示从s3获取的图像 2020-01-10 11:49:25
Android手机按键不灵,手机按键不灵怎么办 手机按键修改教程【详细步骤】 2020-01-10 11:49:25
刷php程序,PHP刷CSDN博客脚本 2022-03-15
通信原理及matlab仿真实验指导书,通信原理实验指导书——2015.pdf 2022-03-15
修复win10的更新服务器,win10升级服务器异常怎么解决_win10升级服务器发生异常修复方法... 2022-03-15
ajax session更新,ajax请求session超时时解决办法 2020-01-10 11:49:23
微信免密支付服务器忙,微信免密支付 查询用户授权记录,调起商家预授权 都返回系统繁忙... 2020-01-10 11:49:23
对使用数据源显示信息的web服务器控件,使用数据源控件绑定到数据 2020-01-10 11:49:23
ubuntu系统服务器维护,Ubuntu Server系列各项服务的安装和维护 Apache部分 2020-01-10 11:49:23
软件测试跟踪需求矩阵,测试管理之从需求到跟踪操作实务 2020-01-10 11:49:21
计算机跨专业保研数学,保研生跨专业很容易吗 2020-01-10 11:49:22
大连中考计算机分值,2019大连中考总分多少分及各科目分值设置 2020-01-10 11:49:22
为什么王者荣耀总是服务器中断,王者荣耀有史以来游戏时间最长的对局!服务器多次崩溃!破纪录!... 2020-01-10 11:49:22
css 加载 500错误,express中加载css和js时候出现500错误 2020-01-10 11:49:22
mysql where排除,MySQL'WHERE'子句排除子查询中的结果 2020-01-10 11:49:20