使用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应用geoip模块,实现不同地区访问不同页面的需求(实践版)

    https://www.52os.net/articles/configure-nginx-using-geoip-allow-whitelist.html       搞了几天没有搞定,这篇文章一下 ...

  2. 量化投资_TB交易开拓者A函数和Q函数详解

    //////////////////A函数详解/////////////// //A函数主要在端口上进行下单操作//////////////// A_AccountID说明 返回当前公式应用的交易帐户 ...

  3. HDU-4614 Vases and Flowers(线段树区间更新+二分查找)

    http://acm.hdu.edu.cn/showproblem.php?pid=4614 Time Limit: 4000/2000 MS (Java/Others)    Memory Limi ...

  4. docker里修改时间

    在docker容器里,你会发现,你根本无法通过命令修改时间.这时我们就可以通过/etc/localtime这个配置文件修改时间了.但这个配置文件是一个二进制的文件,里面根本就是一堆乱码.所以我只好拷贝 ...

  5. LGOJ4450 双亲数

    Description link \[\sum \limits_{i = 1}^A \sum \limits_{j = 1}^B [ \gcd(i, j) = d] \] 要\(O(\sqrt n)\ ...

  6. 代码审计中的CSRF

    0x00 背景 CSRF漏洞中文名为“跨站请求伪造”,英文别名为“one-click-attack”.从字面上我们就可以看出,这是一种劫持其他用户进行非法请求的攻击方式,主要用于越权操作,与XSS相比 ...

  7. Ubuntu navicat试用到期及乱码问题

    对于Ubuntu18.04,navicat试用过期,我这采用的是删掉记录,使其重新试用 网上有的说删掉/home/.navicat64/system.reg,有的又加上删除.update-timest ...

  8. springboot yml 文件配置oracle,提示账号密码错误

    最近使用Spring boot,本来一直连接的是mysql数据库,一直没问题.昨天在更换了oracle数据库后,一直提示账号密码不正确,登录被拒绝.检查多次,检查账号密码一切正常,但就是连接不上ora ...

  9. Redis Client 官方下载地址

    下载地址:https://github.com/caoxinyu/RedisClient 界面 归途(LM)

  10. python开发时小问题之端口占用

    昨天开发时遇到个小问题: 在使用pycharm编写tornado代码时: 直接用这种方式开启了服务,当我想修改代码时发现端口已经被占用代码提交不上去 所以现在该关闭进程: 步骤一: 打开CMD 步骤二 ...