SpringBoot应用启动原理

一、SpringBoot应用启动原理

1.SpringBoot应用启动流程

  1. 初始化
    a. 保存主配置类
    b. 判断是否是web应用
    c.保存ApplicationContextInitializer容器初始化器
    d.保存ApplicationListener容器监听器
initialize(sources);
private void initialize(Object[] sources) {
    //保存主配置类
    if (sources != null && sources.length > 0) {
        this.sources.addAll(Arrays.asList(sources));
    }
    //判断当前是否一个web应用
    this.webEnvironment = deduceWebEnvironment();
    //从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer;然后保存起来
    setInitializers((Collection) getSpringFactoriesInstances(
        ApplicationContextInitializer.class));
    //从类路径下找到ETA-INF/spring.factories配置的所有ApplicationListener
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    //从多个配置类中找到有main方法的主配置类
    this.mainApplicationClass = deduceMainApplicationClass();
}
  1. 执行run()方法
    a.获取并开启SpringApplicationRunListener应用启动监听器
    b.封装命令行参数
    c.准备应用启动环境
    d.打印banner图
    e.创建ApplicationContext–即创建IOC容器
    f.准备容器上下文环境
    g.刷新容器–容器初始化(配置类,组件,自动配置)
    h.回调所有的SpringApplicationRunListener应用启动监听器的finished()方法
    i.返回IOC容器对象
public ConfigurableApplicationContext run(String... args) {
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   ConfigurableApplicationContext context = null;//定义IOC容器
   FailureAnalyzers analyzers = null;
   configureHeadlessProperty();
    
   //获取SpringApplicationRunListeners;从类路径下META-INF/spring.factories
   SpringApplicationRunListeners listeners = getRunListeners(args);
   //回调所有的获取SpringApplicationRunListener.starting()方法
   listeners.starting();
   
   try {
       //封装命令行参数
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
      
      //准备环境
      //环境准备完成后会回调SpringApplicationRunListener.environmentPrepared();
      //表示环境准备完成
      ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
      
      //打印banner图  		
      Banner printedBanner = printBanner(environment);
       
      //创建ApplicationContext;决定创建web的ioc还是普通的ioc
      context = createApplicationContext();
       
      analyzers = new FailureAnalyzers(context);
      
       //准备上下文环境;将environment保存到ioc中;而且applyInitializers();
       //applyInitializers():回调初始化时保存的所有的ApplicationContextInitializer的initialize方法
       //回调所有的SpringApplicationRunListener的contextPrepared();
       //prepareContext运行完成以后回调所有的SpringApplicationRunListener的contextLoaded()
       prepareContext(context, environment, listeners, applicationArguments,printedBanner);
       
      //刷新容器;ioc容器初始化(如果是web应用还会创建嵌入式的Tomcat)
      //扫描,创建,加载所有组件的地方;(配置类,组件,自动配置)
      refreshContext(context);
      
      //从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调
      //ApplicationRunner先回调,CommandLineRunner再回调
      afterRefresh(context, applicationArguments);
      
       //所有的SpringApplicationRunListener回调finished方法
      listeners.finished(context, null);
      
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass)
               .logStarted(getApplicationLog(), stopWatch);
      }
       //整个SpringBoot应用启动完成以后返回启动的ioc容器;
      return context;
   }
   catch (Throwable ex) {
      handleRunFailure(context, listeners, analyzers, ex);
      throw new IllegalStateException(ex);
   }
}

二、自定义Start

1.自定义Start

问题引入:
​ 1、这个场景需要使用到的依赖是什么?
​ 2、如何编写自动配置

2.自动配置类主要结构:(常用注解)

@Configuration  //指定这个类是一个配置类
@ConditionalOnXXX  //在指定条件成立的情况下自动配置类生效
@AutoConfigureAfter  //指定自动配置类的顺序
@Bean  //给容器中添加组件
@ConfigurationPropertie//在相关xxxProperties类上加此注解来绑定指定前缀的配置
@EnableConfigurationProperties //让xxxProperties生效加入到容器中

自动配置类要能加载
将需要启动就加载的自动配置类,配置在META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\

3.模式

  • 启动器只用来做依赖导入
  • 专门来写一个自动配置模块
  • 启动器依赖自动配置模块,这样别人只需要引入启动器(starter)即可完成自动配置

命名风格:自定义启动器名-spring-boot-starter(例:mybatis-spring-boot-starter)

代码实例:

  1. 启动器模块pom—依赖自动配置模块
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.atguigu.starter</groupId>
    <artifactId>atguigu-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--启动器-->
    <dependencies>

        <!--引入自动配置模块-->
        <dependency>
            <groupId>com.atguigu.starter</groupId>
            <artifactId>atguigu-spring-boot-starter-autoconfigurer</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>
  1. 自动配置模块pom—只引入基本的依赖即可
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.atguigu.starter</groupId>
   <artifactId>atguigu-spring-boot-starter-autoconfigurer</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>atguigu-spring-boot-starter-autoconfigurer</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.10.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>

      <!--引入spring-boot-starter;所有starter的基本配置-->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
      </dependency>

   </dependencies>



</project>

  1. XXXProperties配置绑定类—用@ConfigurationProperties注解绑定指定的前缀
package com.atguigu.starter;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "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;
    }
}

  1. 服务提供类 —用来测试
package com.atguigu.starter;

public class HelloService {

    HelloProperties helloProperties;

    public HelloProperties getHelloProperties() {
        return helloProperties;
    }

    public void setHelloProperties(HelloProperties helloProperties) {
        this.helloProperties = helloProperties;
    }

    public String sayHellAtguigu(String name){
        return helloProperties.getPrefix()+"-" +name + helloProperties.getSuffix();
    }
}

  1. 自动配置类
    @Configuration:标识这是一个配置类
    @ConditionalOnWebApplication:类似@ConditionalOnXXX的注解可以指定配置类生效的条件
    @EnableConfigurationProperties(HelloProperties.class):使该配置绑定类生效并加载到容器中
package com.atguigu.starter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConditionalOnWebApplication //web应用才生效
@EnableConfigurationProperties(HelloProperties.class)
public class HelloServiceAutoConfiguration {

    @Autowired
    HelloProperties helloProperties;
    @Bean
    public HelloService helloService(){
        HelloService service = new HelloService();
        service.setHelloProperties(helloProperties);
        return service;
    }
}

  1. 自动加载自动配置类

自动加载自动配置类还有一个关键的操作,就是把自定义的自动配置类配置到META-INF/spring.factories文件中:

注:EnableAutoConfiguration下都配置是创建容器时加载到容器的自动配置类
spring.factories文件中,\表示换行,多个类名用,分隔

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
在此处配置自定义的全类名

更多SpringBoot整合示例

https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值