面试官——能说下 SpringBoot 启动原理吗?

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

转载声明:转载请注明出处,本技术博客是本人原创文章

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 面试官——能说下 SpringBoot 启动原理吗?

点击上方 **好好学java **,选择 **星标 **公众号

重磅资讯、干货,第一时间送达

今日推荐:

 个人原创100W+访问量博客:点击前往,查看更多

SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说,如果不大懂SpringBoot内部启动原理,以后难免会吃亏。所以这次博主就跟你们一起一步步揭开SpringBoot的神秘面纱,让它不在神秘。

那么接下,我们就通过SpringBoot源码分析,讲述启动原理

我们开发任何一个Spring Boot项目,都会用到如下的启动类


@SpringBootApplication
publicclassApplication {
publicstaticvoid main(String[] args) {
SpringApplication.run(Application.class, args);
     }
 }

从上面代码可以看出,Annotation定义(@SpringBootApplication)和类定义(SpringApplication.run)最为耀眼,所以要揭开SpringBoot的神秘面纱,我们要从这两位开始就可以了。

一、SpringBootApplication背后的秘密

@SpringBootApplication注解是Spring Boot的核心注解,它其实是一个组合注解:


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public@interfaceSpringBootApplication {
 ...
 }

@Configuration
@EnableAutoConfiguration
@ComponentScan
publicclassApplication {
publicstaticvoid main(String[] args) {
SpringApplication.run(Application.class, args);
     }
 }

每次写这3个比较累,所以写一个@SpringBootApplication方便点。接下来分别介绍这3个Annotation。

1、@Configuration

(1)表达形式层面

基于XML配置的方式是这样:


 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
default-lazy-init="true">
<!--bean定义-->
 </beans>

而基于JavaConfig的配置方式是这样:


@Configuration
publicclassMockConfiguration{
//bean定义
 }

任何一个标注了@Configuration的Java类定义都是一个JavaConfig配置类。

(2)注册bean定义层面

基于XML的配置形式是这样:


 <bean id="mockService"class="..MockServiceImpl">
     ...
 </bean>

而基于JavaConfig的配置形式是这样的:


@Configuration
publicclassMockConfiguration{
@Bean
publicMockService mockService(){
returnnewMockServiceImpl();
     }
 }

任何一个标注了@Bean的方法,其返回值将作为一个bean定义注册到Spring的IoC容器,方法名将默认成该bean定义的id。

(3)表达依赖注入关系层面

为了表达bean与bean之间的依赖关系,在XML形式中一般是这样:


 <bean id="mockService"class="..MockServiceImpl">
     <propery name ="dependencyService"ref="dependencyService" />
 </bean>
 <bean id="dependencyService"class="DependencyServiceImpl"></bean>

而基于JavaConfig的配置形式是这样的:


@Configuration
publicclassMockConfiguration{
@Bean
publicMockService mockService(){
returnnewMockServiceImpl(dependencyService());
     }
@Bean
publicDependencyService dependencyService(){
returnnewDependencyServiceImpl();
     }
 }

如果一个bean的定义依赖其他bean,则直接调用对应的JavaConfig类中依赖bean的创建方法就可以了。

@Configuration:提到@Configuration就要提到他的搭档@Bean。使用这两个注解就可以创建一个简单的spring配置类,可以用来替代相应的xml配置文件。


 <beans>
     <bean id = "car"class="com.test.Car">
         <property name="wheel"ref = "wheel"></property>
     </bean>
     <bean id = "wheel"class="com.test.Wheel"></bean>
 </beans>

相当于:


@Configuration
publicclassConf {
@Bean
publicCar car() {
Car car = newCar();
         car.setWheel(wheel());
return car;
     }
@Bean
publicWheel wheel() {
returnnewWheel();
     }
 }

@Configuration的注解类标识这个类可以使用Spring IoC容器作为bean定义的来源。

@Bean注解告诉Spring,一个带有@Bean的注解方法将返回一个对象,该对象应该被注册为在Spring应用程序上下文中的bean。

2、@ComponentScan

3、@EnableAutoConfiguration

@EnableAutoConfiguration作为一个复合Annotation,其自身定义关键信息如下:


@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public@interfaceEnableAutoConfiguration {
     ...
 }

自动配置幕后英雄:SpringFactoriesLoader详解

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


publicabstractclassSpringFactoriesLoader {
//...
publicstatic <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) {
         ...
     }
publicstaticList<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
         ....
     }
 }

配合@EnableAutoConfiguration使用的话,它更多是提供一种配置查找的功能支持,即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration作为查找的Key,获取对应的一组@Configuration类。

二、深入探索SpringApplication执行流程

去除事件通知点后,整个流程如下:

本文以调试一个实际的SpringBoot启动程序为例,参考流程中主要类类图,来分析其启动逻辑和自动化配置原理。

总览

启动

SpringBoot启动类

首先进入run方法

run方法中去创建了一个SpringApplication实例,在该构造方法内,我们可以发现其调用了一个初始化的initialize方法

这里主要是为SpringApplication对象赋一些初值。构造函数执行完毕后,我们回到run方法

该方法中实现了如下几个关键步骤:

主要看其继承的两个方向:

自动化配置

之前的启动结构图中,我们注意到无论是应用初始化还是具体的执行过程,都调用了SpringBoot自动配置模块。

SpringBoot自动配置模块

工厂接口与其若干实现类接口名称

下图有助于我们形象理解自动配置流程。

SpringBoot自动化配置关键组件关系图

之前我们提到了EnableAutoConfiguration注解,其类图如下:

进入org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration中,主要看一下类头:

这里是截取的mybatis-spring-boot-starter的源码中pom.xml文件中所有依赖:

作者:平凡希

cnblogs.com/xiaoxi/p/7999885.html

推荐文章



原创电子书历时整整一年总结的 Java 面试 + Java 后端技术学习指南,这是本人这几年及校招的总结,各种高频面试题已经全部进行总结,按照章节复习即可,已经拿到了大厂offer。
原创思维导图扫码或者微信搜 程序员的技术圈子 回复 面试 领取原创电子书和思维导图。

原文地址:https://sihai.blog.csdn.net/article/details/110211613

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

转载声明:转载请注明出处,本技术博客是本人原创文章

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 面试官——能说下 SpringBoot 启动原理吗?


 上一篇
Spring Cloud Alibaba到底坑不坑?反正是解放了部分使用的繁琐! Spring Cloud Alibaba到底坑不坑?反正是解放了部分使用的繁琐!
随着Spring Cloud Alibaba相关组件逐渐的成熟,学习它已经是java开发人员的大势所趋。 因为Spring Cloud 不少功能组件的停更,环境搭建繁杂,而Spring Cloud Alibaba将Dubbo融入Spring
2021-04-04
下一篇 
为什么一个还没毕业的大学生能够把 IO 讲的这么好? 为什么一个还没毕业的大学生能够把 IO 讲的这么好?
点击上方 **好好学java **,选择 **星标 **公众号 重磅资讯、干货,第一时间送达 今日推荐: 个人原创100W+访问量博客:点击前往,查看更多 Java IO 是一个庞大的知识体系,很多人学着学着就会学懵了,包括我在内也是如此,
2021-04-04