使用IDEA快速创建一个springboot项目

创建Spring Initializr,然后一直下一步下一步直至完成

选择web,表示创建web项目

运行原理分析

我们先来看看pom.xml文件

核心依赖的父项目如下:

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

进入spring-boot-starter-parent,可以看到管理SpringBoot应用里面所有依赖版本的地方和配置加载的地方。

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>//管理SpringBoot应用里面所有依赖版本的地方
<version>2.2..RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>

在进入spring-boot-dependencies,就可以看到所依赖的所有版本了,由于太过,这里只截取部分。

所以,以后我们导入依赖默认是不需要写版本;但是如果导入的包没有在依赖中管理着就需要手动配置版本了。

springboot自动配置原理分析

主程序

//@SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用
@SpringBootApplication
public class Springboot01Application {
public static void main(String[] args) {
SpringApplication.run(Springboot01Application.class, args);
}
}
@SpringBootApplication意义:SpringBoot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动SpringBoot应用;
进入@SpringBootApplication会发现有三个重要的注解
  • @SpringBootConfiguration:SpringBoot的配置类 ;标注在某个类上 , 表示这是一个SpringBoot的配置类;
  • @EnableAutoConfiguration:开启自动配置功能
  • @ComponentScan:自动扫描并加载符合条件的组件或者bean , 将这个bean定义加载到IOC容器中 ;

下面我们依次看一下这三个注解

@SpringBootConfiguration

进入@SpringBootConfiguration后,会看到@Configuration这个注解。

@Configuration:配置类上来标注这个注解,说明这是一个配置类 ,配置类,即:配置文件

在进入@Configuration后,会看到@Component注解,这个注解大家都很熟悉了吧,说明容器中的一个组件,也就是说启动类本身也是Spring中的一个组件而已,负责启动应用而已

返回来我们再看@ComponentScan

@ComponentScan

@ComponentScan在Spring中非常重要,它对应XML配置中的元素。功能就是自动扫描并加载符合条件的组件或者bean,将这个bean定义加载到IOC容器中 ;

接下来在看最重要的一个@EnableAutoConfiguration

@EnableAutoConfiguration

@EnableAutoConfiguration的作用是:开启自动配置功能,无须我们在自己配置,自动就告诉SpringBoot开启自动配置功能,这样自动配置才能生效;

进入@EnableAutoConfiguration后会发下有两个注解,@AutoConfigurationPackage和@Import(AutoConfigurationImportSelector.class)

@AutoConfigurationPackage //自动配置包
@Import(AutoConfigurationImportSelector.class) //导入哪些组件的选择器
public @interface EnableAutoConfiguration {
... ...
}

进入@AutoConfigurationPackage(自动配置包),有一个@Import(AutoConfigurationPackages.Registrar.class)。

@Import注解大家都知道,是Spring底层注解, 给容器中导入一个组件。

Registrar.class 将主配置类【即@SpringBootApplication标注的类】的所在包及包下面所有子包里面的所有组件扫描到Spring容器 ;

@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage { }

接下返回@EnableAutoConfiguration看下@Import(AutoConfigurationImportSelector.class)(给容器导入组件)。

AutoConfigurationImportSelector:自动配置导入选择器。

我们来思考下,它会导入哪些组件的选择器呢?进入这个类,我们来看源码

在类中找到这样一个方法

// 获得候选的配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
   //这里的getSpringFactoriesLoaderFactoryClass()方法
//返回的就是我们最开始看的启动自动导入配置文件的注解类;EnableAutoConfiguration
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}

getSpringFactoriesLoaderFactoryClass()

这个方法又调用了 SpringFactoriesLoader 类的静态方法!我们进入SpringFactoriesLoader类loadFactoryNames() 方法

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
     //这里它又调用了 loadSpringFactories 方法
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}

我们继续点击查看 loadSpringFactories 方法

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    //获得classLoader , 我们返回可以看到这里得到的就是EnableAutoConfiguration标注的类本身
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
        //去获取一个资源 "META-INF/spring.factories"
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
        //将读取到的资源遍历,封装成为一个Properties
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}

我们进入FACTORIES_RESOURCE_LOCATION

看到了这个路径:META-INF/spring.factories
FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"
接下来我们就找一下这个配置文件
找到spring-boot-autoconfigure-2.2.1.RELEASE.jar - META-INF - spring.factories文件

这些都是自动配置根源

进入我们熟悉的WebMvcAutoConfiguration,都是JavaConfig配置类,而且都注入了一些Bean

总结

springboot所有自动配置都是在启动的时候扫描并加载:spring.factories所有的自动配置类都在这里面,但不一定生效,要判断条件是否成立,只要导入对应的start,就有对应的启动器了,有了启动器,我们自动装配就会生效,然后就配置成功。

结论

1、SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值
2、将这些值作为自动配置类导入容器 , 自动配置类就生效 , 帮我们进行自动配置工作;
3、以前我们需要自己配置的东西 , 自动配置类都帮我们解决了
4、整个J2EE的整体解决方案和自动配置都在springboot-autoconfigure的jar包中;
5、它将所有需要导入的组件以全类名的方式返回 , 这些组件就会被添加到容器中 ;
6、容器中存在非常多xxxAutoConfiguration的文件(@Bean), 就是给容器中导入这个场景需要的所有组件 ,并自动配置 ,@Configuration,javaConfig;
7、有了自动配置类 , 免去了我们手动编写配置注入功能组件等的工作;

流程图:https://www.processon.com/view/link/5de763fee4b00e6d9017b5e5

run()方法

@SpringBootApplication
public class Springboot01Application {
public static void main(String[] args) {
//该方法返回一个ConfigurableApplicationContext对象
//参数一:应用入口的类 参数类:命令行参数
SpringApplication.run(Springboot01Application.class, args);
}
}

run()做了四件事:

  1. 推断应用的类型是普通的项目还是Web项目
  2. 查找并加载所有可用初始化器,设置到initializers属性中
  3. 找出所有的应用程序监听器,设置到listeners属性中
  4. 推断并设置main方法的定义类,找到运行的主类

springboot创建,自动装配原理分析,run方法启动的更多相关文章

  1. 【springboot】自动装配原理

    摘自:https://mp.weixin.qq.com/s/ZxY_AiJ1m3z1kH6juh2XHw 前言 Spring翻译为中文是"春天",的确,在某段时间内,它给Java开 ...

  2. SpringBoot启动流程分析(五):SpringBoot自动装配原理实现

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  3. Spring Boot 自动装配原理

    Spring Boot 自动装配原理 Spring Boot 在启动之前还有一系列的准备工作,比如:推断 web 应用类型,设置初始化器,设置监听器,启动各种监听器,准备环境,创建 applicati ...

  4. springboot自动装配原理回顾、配置文件分析

    配置文件 spring boot官方文档 官方外部配置文件说明参考文档 自动配置原理分析 1. SpringBoot启动的时候加载主配置类,开启了自动配置功能@EnableAutoConfigurat ...

  5. SpringBoot:带你认认真真梳理一遍自动装配原理

    前言 Spring翻译为中文是“春天”,的确,在某段时间内,它给Java开发人员带来过春天,但是随着我们项目规模的扩大,Spring需要配置的地方就越来越多,夸张点说,“配置两小时,Coding五分钟 ...

  6. SpringBoot:认认真真梳理一遍自动装配原理

    前言 Spring翻译为中文是“春天”,的确,在某段时间内,它给Java开发人员带来过春天,但是随着我们项目规模的扩大,Spring需要配置的地方就越来越多,夸张点说,“配置两小时,Coding五分钟 ...

  7. SpringBoot自动装配原理解析

    本文包含:SpringBoot的自动配置原理及如何自定义SpringBootStar等 我们知道,在使用SpringBoot的时候,我们只需要如下方式即可直接启动一个Web程序: @SpringBoo ...

  8. SpringBoot | 2.1 SpringBoot自动装配原理

    @ 目录 前言 1. 引入配置文件与配置绑定 @ImportResource @ConfigurationProperties 1.1 @ConfigurationProperties + @Enab ...

  9. springboot自动装配原理

    最近开始学习spring源码,看各种文章的时候看到了springboot自动装配实现原理.用自己的话简单概括下. 首先打开一个基本的springboot项目,点进去@SpringBootApplica ...

随机推荐

  1. nginx限制IP访问网站

    需求:网站只允许指定IP访问,其他访问一律拒绝server { listen 80; server_name a.com; index index.html index.htm index.php; ...

  2. xianduanshu

    https://www.cnblogs.com/xenny/p/9739600.html ***************https://blog.csdn.net/shiqi_614/article/ ...

  3. Cantor表(模拟)

    链接:https://ac.nowcoder.com/acm/contest/1069/I来源:牛客网 题目描述 现代数学的著名证明之一是Georg Cantor证明了有理数是可枚举的.他是用下面这一 ...

  4. 【DSP】TMS320F28335的GPIO

    --> 关于TMS320F28335的GPIO的基础操作 TI的c2000系列DSP大多数的外设信号与通用输入/输出 (GPIO) 信号复用. 这使得用户能够在外设信号或者功能不使用时将一个引脚 ...

  5. ionic3 设置状态栏背景颜色

    this.statusBar.styleDefault(); this.statusBar.overlaysWebView(true); this.statusBar.backgroundColorB ...

  6. VS2010 保护视力 背景色设置

    vs2010——工具——选项---环境——字体和颜色——纯文本——项背景色——自定义 色调:88 饱和度:92 亮度:209

  7. Linux 设置开机启动项的几种方法

    方法一:编辑rc.loacl脚本 Ubuntu开机之后会执行/etc/rc.local文件中的脚本. 所以我们可以直接在/etc/rc.local中添加启动脚本. $ vim /etc/rc.loca ...

  8. 在服务器搭建git服务器

    服务端操作 安装Git及创建用户组.用户 123 yum install gitgroupadd gitadduser git -g git 禁止用户git登录 修改/etc/passwd文件: 找到 ...

  9. python之操作数据库

    一.操作mysql 首先,python3操作mysql.需要安装第三方模块pymysql,在python2中则使用的是pysqldb.这里使用pymysql. 直接使用pip install pymy ...

  10. numpy中的ndarray与pandas中的series、dataframe的转换

    一个ndarray是一个多维同类数据容器.每一个数组有一个dtype属性,用来描述数组的数据类型. Series是一种一维数组型对象,包含了一个值序列,并且包含了数据标签----索引(index). ...