springboot原理初识

本文深入探讨了SpringBoot的启动过程和自动配置机制。从`pom.xml`的父依赖管理到`spring-boot-starter`启动器的作用,再到`@SpringBootApplication`注解的解析,揭示了SpringBoot如何通过`@EnableAutoConfiguration`和`@ComponentScan`实现自动配置。文章详细分析了`SpringApplication.run()`方法的流程,解释了如何从`META-INF/spring.factories`加载自动配置类。总结了SpringBoot简化配置、自动导入组件的核心思想。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一,原理初探

         pom.xml

父依赖

启动器spring-boot-starter

二.主启动类

@ComponentScan

@SpringBootConfiguration

@EnableAutoConfiguration

起关键作用的两个注解

三.SpringApplication

         run

SpringApplication

run方法流程分析


一,原理初探

pom.xml

父依赖

其中它主要是依赖一个父项目,主要是管理项目的资源过滤及插件!

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

点进去,发现还有一个父依赖

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

这里才是真正管理SpringBoot应用里面所有依赖版本的地方,SpringBoot的版本控制中心;

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

启动器spring-boot-starter

可参考基本启动器44种

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
  • 启动器:简单来说就是springboot的使用场景
  • 例如spring-boot-starter-web,他会帮助我们自动导入web环境所有的依赖
  • springboot会将所有的功能场景,变成一个个的启动器
  • 需要什么功能,就只需要找到对应的启动器即可。"strater-???"

SpringBoot将所有的功能场景都抽取出来,做成一个个的starter (启动器),只需要在项目中引入这些starter即可,所有相关的依赖都会导入进来 , 我们要用什么功能就导入什么样的场景启动器即可 ;我们未来也可以自己自定义 starter;

二.主启动类

//@SpringBootApplication:标注这个类是springboot的应用 :启动类下的所有资源被导入
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        //run:将springboot应用启动
        SpringApplication.run(DemoApplication.class, args);
    }
}

@SpringBootApplication注解作用:标注在某个类上说明这个类是SpringBoot的主配置类 , SpringBoot就应该运行这个类的main方法来启动SpringBoot应用;

@SpringBootApplication注解还有以下七个注解

@Target

@Documented

@Retention

@Inherited

@SpringBootConfiguration

@EnableAutoConfiguration

@ComponentScan

@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}
)}
)

@ComponentScan

这个注解在Spring中很重要 ,它对应XML配置中的元素。

作用:自动扫描并加载符合条件的组件或者bean , 将这个bean定义加载到IOC容器中

@SpringBootConfiguration

作用:SpringBoot的配置类 ,标注在某个类上 , 表示这是一个SpringBoot的配置类;

我们继续进去这个注解查看

// 点进去得到下面的 @Component
@Configuration
public @interface SpringBootConfiguration {}

@Component
public @interface Configuration {}

这里的 @Configuration,说明这是一个配置类 ,配置类就是对应Spring的xml 配置文件;

里面的 @Component 这就说明,启动类本身也是Spring中的一个组件而已,负责启动应用!

@EnableAutoConfiguration

@EnableAutoConfiguration :开启自动配置功能

以前我们需要自己配置的东西,而现在SpringBoot可以自动帮我们配置 ;@EnableAutoConfiguration告诉SpringBoot开启自动配置功能,这样自动配置才能生效;

点进注解接续查看:

@AutoConfigurationPackage :自动配置包

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

@import :Spring底层注解@import , 给容器中导入一个组件

Registrar.class 作用:将主启动类的所在包及包下面所有子包里面的所有组件扫描到Spring容器 ;

@Import({AutoConfigurationImportSelector.class}) :给容器导入组件 ;

AutoConfigurationImportSelector :自动配置导入选择器

1、这个类中有一个这样的方法

// 获得候选的配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    //这里的getSpringFactoriesLoaderFactoryClass()方法
    //返回的就是我们最开始看的启动自动导入配置文件的注解类;EnableAutoConfiguration
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
}

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

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

3、我们继续点击查看 loadSpringFactories 方法

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    //获得classLoader , 我们返回可以看到这里得到的就是EnableAutoConfiguration标注的类本身
    MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
    if (result != null) {
        return result;
    } else {
        try {
            //去获取一个资源 "META-INF/spring.factories"
            Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
            LinkedMultiValueMap result = new LinkedMultiValueMap();

            //将读取到的资源遍历,封装成为一个Properties
            while(urls.hasMoreElements()) {
                URL url = (URL)urls.nextElement();
                UrlResource resource = new UrlResource(url);
                Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                Iterator var6 = properties.entrySet().iterator();

                while(var6.hasNext()) {
                    Entry<?, ?> entry = (Entry)var6.next();
                    String factoryClassName = ((String)entry.getKey()).trim();
                    String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                    int var10 = var9.length;

                    for(int var11 = 0; var11 < var10; ++var11) {
                        String factoryName = var9[var11];
                        result.add(factoryClassName, factoryName.trim());
                    }
                }
            }

            cache.put(classLoader, result);
            return result;
        } catch (IOException var13) {
            throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
        }
    }
}

起关键作用的两个注解

@SpringBootConfiguration :springboot的配置
     @Configuration :spring配置类 
         @Component:说明这也是一个spring的组件


@EnableAutoConfiguration : 自动配置
     @AutoConfigurationPackage :自动配置包
           @Import({Registrar.class}) :自动配置“包注册”
     @Import({AutoConfigurationImportSelector.class}) :自动配置导入选择


//获取所有的配置
List<string> configurations = getCandidateConfigurations(annotationMetadata,attributes);

META-INF/spring.factories:自动配置的核心文件

Properties properties = PropertiesLoaderUtils.loadProperties(resource);
所有资源加载到配置类中

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

1.springboot在启动的时候,从类路径下/META-IN/spring.factories 获取指定的值;

2将这些自动配置的类导入容器,自动配置就会生效,帮我们进行自动配置!

3.在学习ssm框架时需要我们手动配置的东西,现在springboot帮我们做了!

4.整合javaEE,解决方案和自动配置的东西都在spring-boot-autoconfigure-2.7.0.jar这个包里面(jar包一直都在更新)

5.它会把所有需要导入的组件,以全类名的方式返回,这些组件就会被添加到容器;

6.容器中也会存在非常多的xxxAutoConfiguration的文件(@Bean),就是这些类给容器中导入了这个场景需要的所有组件;并自动配置,@Configuration,这些xxxAutoConfiguration文件就像用Java类来配置成Config

7.有了自动配置类,就免去了我们手动编写配置文件的工作

三.SpringApplication

run

这不仅是运行了一个main方法,而且还开启了一个服务

@SpringBootApplication
public class DemoApplication {

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

分析该方法主要分两部分,一部分是SpringApplication的实例化,二是run方法的执行;

SpringApplication

这个类主要做了以下四件事情

1.推断应用的类型是普通的项目还是Web项目

2.查找并加载所有可用初始化器,设置到initializers属性中

3.找出所有的应用程序监听器,设置到listeners属性中

4.推断并设置main方法的定义类,找到运行的主类

SpringApplication构造器: 

面试注意:关于SpringBoot,谈谈你的理解:

  • 自动装配
  • run()
  • SpringApplication

run方法流程分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值