使用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. day03-函数

    形参:位置参数:必须传 *args:动态参数,可以接收任意多个位置参数 默认值参数:可以传也可以不传 **kwargs:动态参数,可以接收多个关键字参数. 实参:按照位置传参,按照关键字传参. #顺序 ...

  2. ubuntu Python 升级

    安装时ubuntu提示: DEPRECATION: Python 3.4 support has been deprecated. pip 19.1 will be the last one supp ...

  3. Simple Random Sampling|representative sample|probability sampling|simple random sampling with replacement| simple random sampling without replacement|Random-Number Tables

    1.2 Simple Random Sampling Census, :全部信息 Sampling: 抽样方式: representative sample:有偏向,研究者选择自己觉得有代表性的sam ...

  4. 微信小程序的标签和html标签比较

    html 小程序 <div></div> <view></view> <h1><h2>....<h6> <p& ...

  5. 聊聊HTTPS和SSL/TLS协议 【基础入门】

    要说清楚 HTTPS 协议的实现原理,至少需要如下几个背景知识.1. 大致了解几个基本术语(HTTPS.SSL.TLS)的含义2. 大致了解 HTTP 和 TCP 的关系(尤其是“短连接”VS“长连接 ...

  6. EncryptUtils

    package me.zhengjie.core.utils; import org.springframework.util.DigestUtils; import javax.crypto.Cip ...

  7. 吴裕雄--天生自然 Hadoop大数据分布式处理:关闭CenterOS 7防火墙

    使用命令:systemctl status firewalld.service 查看防火墙状态 执行后可以看到绿色字样标注的“active(running)”,说明防火墙是开启状态 使用命令:syst ...

  8. python语法基础-基础-控制语句

    ###############    if条件控制语句    ############### # 以下实例 x 为 0-99 取一个数,y 为 0-199 取一个数,如果 x>y 则输出 x,如 ...

  9. AngularJS中格式化日期为指定格式字符串

    var date = $filter('date')(new Date(),'MM/dd/yyyy');

  10. 为Nginx启用目录浏览功能

    今天工作需要,要给客户提供一个patch的下载地址,于是想用nginx的目录浏览功能来做,需要让客户看到指定一个目录下的文件列表,然后让他自己来选择该下载那个文件: 我们都知道在apache下可以配置 ...