前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Boot 源码解析,一步步分析启动原理

Spring Boot 源码解析,一步步分析启动原理

作者头像
南风
发布2020-01-15 15:49:12
6640
发布2020-01-15 15:49:12
举报
文章被收录于专栏:Java大联盟Java大联盟Java大联盟

Spring Boot 是一套 Java 开发框架,可以快速构建基于 Spring 生态的 Java Application,实现自动配置,作为 Java 领域最火的技术栈,我们有必要搞清楚 Spring Boot 的底层原理,今天楠哥就带大家一探究竟。

Spring Boot 核心配置

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

spring-boot-starter 是 Spring Boot 提供的场景启动器,通过 starter 导入不同场景下所需要的 jar 包,如 web、dao 等。

spring-boot-starter-{name} 是 Spring 官方提供的启动器,如 spring-boot-starter-parent,{name}-spring-boot-starter 是第三方提供的启动器,如 mybatis-spring-boot-starter。

spring-boot-starter-parent 是 Spring Boot 的父级启动器,Spring Boot 相当于一个大的组件集合,将 Spring 家族组件及第三方组件全部进行了集成,开发者只需要通过配置 spring-boot-starter 就可以将所需组件配置到项目中,直接使用,这就是开箱即用。

打开 spring-boot-starter-parent 源码,可以看到 resource 中配置了 Spring Boot 默认会读取的资源文件。

<resource>
  <filtering>true</filtering>
  <directory>${basedir}/src/main/resources</directory>
  <includes>
    <include>**/application*.yml</include>
    <include>**/application*.yaml</include>
    <include>**/application*.properties</include>
  </includes>
</resource>

所以 Spring Boot 默认加载的配置文件是 src/main/resources 路径下名为 application 的 yml、yaml、properties 文件。

同时 spring-boot-starter-parent 中又引入了 spring-boot-dependencies 依赖。

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-dependencies</artifactId>
  <version>2.2.2.RELEASE</version>
  <relativePath>../../spring-boot-dependencies</relativePath>
</parent>

打开源码,如下所示。

<properties>
  <activemq.version>5.15.11</activemq.version>
  <antlr2.version>2.7.7</antlr2.version>
  <appengine-sdk.version>1.9.77</appengine-sdk.version>
  <artemis.version>2.10.1</artemis.version>
  <aspectj.version>1.9.5</aspectj.version>
  ......
</properties>

可以看到 Spring Boot 2.2.2 版本自动集成的各种组件的版本,对应的 jar 依赖都会自动导入到当前工厂,starter 就这样帮助我们非常方便的引入了项目所需要的各种 jar 包。

Spring Boot 自动配置类

传统的 Spring 应用中,各个组件对象的管理全部交给 Spring IoC 容器,我们需要在 application.xml 中配置多个 bean,以完成组件对象的注入。

而在 Spring Boot 中,这些配置是自动注入的,并不需要开发者配置任何一个 bean,如何实现?定义一个自动配置的类,通过加载这个类来读取各种配置信息,用来替代 XML 的配置文件,这里用到两个核心注解 @Configuration 和 @Bean。

@Configuration 注解标明该类是一个配置类,@Bean 注解表示该方法返回的对象就是一个要交给 Spring IoC 容器管理的 bean 实例。

一个 @Bean 就相当于传统的 application.xml 中配置的一组 <bean/> 。

XML 配置方式

1、实体类。

@AllArgsConstructor
public class User {
    private Integer id;
    private String name;
}

2、配置文件。

<beans>  
    <bean id="user" class="com.southwind.entity.User">  
        <property name="id" value="1"></property>  
        <property name="name" value="张三"></property>   
    </bean>  
</beans>

3、获取 bean。

public class Test {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
        User user = (User) applicationContext.getBean("user");
        System.out.println(user);
    }
}

基于配置类的方式

1、创建配置类。

@Configuration
public class MyConfiguration {

    @Bean(name = "user")
    public User getUser(){
        return new User(1,"张三");
    }
}

2、获取 Bean。

public class Test {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfiguration.class);
        User user = (User) applicationContext.getBean("user");
        System.out.println(user);
    }
}

Spring Boot 源码解析

Spring Boot 自动装配主要完成两件事:

1、自动装置开发者自定义的业务组件(Handler、Service、Repository 等 bean)。

2、根据开发者的设置进行自动配置(比如集成 MyBatis,自动配置 DataSource、SqlSessionFactory 等 bean)。

Spring Boot 最大的特点就是可以完成自动配置,简单讲就是之前需要开发者手动配置的各种 bean,现在 Spring Boot 全部自动完成,并且是基于 JavaConfig 的形式,即用标注了 @Configuration 的类来替代 XML,Spring Boot 最核心的注解是 @SpringBootApplication。

@SpringBootApplication 注解

该注解实际由 3 个核心注解组成:

1、@SpringBootConfiguration

2、@EnableAutoConfiguration

3、@ComponentScan

@SpringBootConfiguration 实际上还是使用了 @Configuration,Spring 官方推荐使用 @Configuration 配置类的形式来替代 XML 的配置方式,启动类标注了 @Configuration 注解之后,也就成为了 IoC 的配置类。

@ComponentScan 这个注解的功能是自动扫描并加载符合条件的组件(比如开发者自定义的业务组件,@Component 和 @Repository等),可以通过 basePackages 属性来制定扫描的范围,如果不指定,默认从 @ComponentScan 所在类的 package 向下进行扫描。

@EnableAutoConfiguration 就是完成自动配置的,会根据类路径中引入的 jar 依赖为项目自动配置,比如添加了 spring-boot-starter-web 依赖,Spring Boot 就会自动添加 Spring MVC 相关 jar,并且会自动对 Spring MVC 进行配置(DispatcherServlet、ViewResolver )。

@EnableAutoConfiguration 是如何完成自动配置的呢?

核心注解是 @Import(EnableAutoConfigurationImportSelector.class),具体流程如下:

1、EnableAutoConfigurationImportSelector 中返回符合条件的 @Configuration 类信息。

2、@Import 通过加载 EnableAutoConfigurationImportSelector,将所有符合条件的 @Configuration 配置都加载到当前 Spring Boot 创建并使用的 IoC 容器中。

我们通过一个例子来搞清楚 @Import 的使用。

User

package org.southwind.entity;

@Data
public class User {
    @Value("1")
    private Integer id;
    @Value("张三")
    private String name;
}

MyImportSelector

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"org.southwind.entity.User"};
    }
}

MyImportConfig

@Import(MyImportSelector.class)
public class MyImportConfig {
}

Test

public class Test {
  public static void main(String[] args) {
    ApplicationContext context = new AnnotationConfigApplicationContext(MyImportConfig.class);
    System.out.println(context.getBean("org.southwind.entity.User"));
  }
}

运行结果如图所示。

可以得出结论,Spring Boot 自动配置的类都是通过 EnableAutoConfigurationImportSelector 获取的,那么问题来了,EnableAutoConfigurationImportSelector 是如何返回 Spring Boot 所需要的 @Configuration 类呢?

这里需要使用 SpringFactoriesLoader 来完成,SpringFactoriesLoader 属于 Spring 框架私有的一种扩展方案,其主要功能就是从指定的配置文件 META-INF/spring.factories 加载配置。

它在这里的工作是通过 @EnableAutoConfiguration 的完整类名 org.springframework.boot.autoconfigure.EnableAutoConfiguration 作为 Key,在 META-INF/spring.factories 查找对应的一组 @Configuration 类。

通过这种方式,让 Spring Boot 读取到所有符合条件的 @Configuration 配置类,并通过反射机制实例化 bean 并加载到 IoC 容器中,这样就实现了自动配置。

推荐阅读

1、一次性把JVM讲清楚,别再被面试官问住了

2、学会GC,直接吊打面试官

3、一文搞懂前后端分离

4、快速上手Spring Boot+Vue前后端分离

博主简介:楠哥,资深 Java 工程师,《Java 零基础实战》一书作者,今日头条认证大 V,GitChat 认证作者,B 站 UP 主(楠哥教你学 Java),微信号 nnsouthwind,致力于帮助万千 Java 学习者持续成长。

有收获,就点个在看

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-01-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java大联盟 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档