SpringBoot自动配置和执行过程

news2024/9/22 4:14:15

Spring的执行流程


1. 加载容器(加载配置文件)

2. 根据配置完成Bean的初始化(扫描配置范围内的五大类注解)

 3. 将被五大类注解修饰的类注册到Spring容器中

                (将对象交给Spring IoC容器管理)

4.注入Bean对象(@Autowired、@Resource)


Spring Boot自动配置

Spring Boot的自动配置是Spring Boot框架提供的一项特性,它在Spring容器启动后会自动加载一些配置类和Bean对象到IoC容器中,无需手动声明,从而简化了开发流程,减少了繁琐的配置操作。

具体来说,Spring Boot的自动配置是通过扫描classpath下的各种配置类和标记了特定注解的类来实现的。这些配置类通常位于依赖jar包中,其中可能包含了一些默认的配置信息、Bean定义以及各种组件。Spring Boot会自动识别这些配置类,并根据特定的规则将它们加载到Spring IoC容器中。

在加载这些配置类时,Spring Boot会根据条件判断是否需要应用这些配置。例如,它会检查当前项目中的其他配置、环境变量、系统属性等,来决定是否应用某个配置类。这样一来,开发者可以根据自己的需求对自动配置进行定制,从而实现更灵活和个性化的配置。

总的来说,Spring Boot的自动配置使得开发者可以更加专注于业务逻辑的实现,而无需过多关注底层的配置细节,极大地提高了开发效率和代码质量。

我们了解主要分以下两个方面:

1. Spring 是如何把对象加载到SpringIoC容器中的

2. SpringBoot 是如何实现的

Spring 加载Bean

问题描述

需求:使用Spring管理第三方的jar包配置。

引入第三方的包,其实就是在该项目下,引⼊第三方的代码。我们采⽤在该项目下创建不同的目录来模拟第三方的代码引入。

数据准备:

第三方文件代码:

第三⽅⽂件代码:
@Component
 public class BiteConfig {
 public void study(){
 System.out.println("start study...");
 }
 }
获取 BiteConfig 这个Bean
写测试代码
@SpringBootTest
class SpringAutoconfigApplicationTests {
 @Autowired
 private ApplicationContext applicationContext;
 @Test
 void contextLoads() {
 BiteConfig biteConfig = applicationContext.getBean(BiteConfig.class, 
"biteConfig");
 System.out.println(biteConfig);
 }
}
运⾏程序:
观察⽇志: No qualifying bean of type 'com.bite.autoconfig.BiteConfig' available
没有 com.bite.autoconfig.BiteConfig 这个类型的Bean
原因分析
Spring通过五⼤注解和 @Bean 注解可以帮助我们把Bean加载到SpringIoC容器中, 以上有个前提就是这些注解类需要和SpringBoot启动类在同⼀个⽬录下
(@SpringBootApplication 标注的类就是SpringBoot项⽬的启动类)
启动类所在⽬录为: com.example.demo , ⽽ BiteConfig 这个类在
com.bite.autoconfig 下, 所以SpringBoot并没有扫描到.
解决方案

当我们引入第三方的 jar 包时,其代码目录通常不会与 Spring Boot 项目的启动类在同一个目录下。为了让 Spring 能够扫描到这些第三方 jar 包中的组件并加载到 Spring IoC 容器中,我们需要采取一些解决方案。常见的解决方案有两种:

  1. @ComponentScan 组件扫描: 在 Spring Boot 项目中,通常会有一个主启动类,该类上会使用 @SpringBootApplication 注解进行标注。这个注解会自动进行组件扫描并将其加载到 Spring IoC 容器中。除了主启动类之外,其他需要被 Spring 管理的组件也可以使用 @ComponentScan 注解或者其他方式指定扫描的包路径,以确保它们被 Spring 框架扫描到并加载到 IoC 容器中。
  2. @Import 导入: 使用 @Import 注解可以导入其他的配置类或者普通的 Java 类,被导入的类会被 Spring 加载到 IoC 容器中。通过在主配置类上使用 @Import 注解导入需要加载的类,可以让 Spring 加载这些类并管理它们。

@ComponentScan:

通过 @ComponentScan 注解,指定Spring扫描路径。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan("com.bite.autoconfig")
@SpringBootApplication
public class SpringAutoconfigApplication {
 public static void main(String[] args) {
 SpringApplication.run(SpringAutoconfigApplication.class, args);
 }
}
可以指定扫描多个包
@ComponentScan({"com.bite.autoconfig","com.example.demo"})
Spring 是否使⽤了这种⽅式呢?
⾮常明显, 没有.(因为我们引⼊第三⽅框架时, 没有加扫描路径. ⽐如mybatis)
如果Spring Boot采⽤这种⽅式, 当我们引⼊⼤量的第三⽅依赖, ⽐如Mybatis, jackson等时, 就需要在启动类上配置不同依赖需要扫描的包, 这种⽅式会⾮常繁琐.

具体来说:

Spring Boot 采用了自动配置的方式来管理第三方依赖,而不是使用 @ComponentScan 这种方式。自动配置是通过在 Spring Boot 启动类上使用 @SpringBootApplication 注解来实现的。这个注解包含了多个注解的功能,其中包括了 @ComponentScan 注解。

当我们引入第三方依赖时,Spring Boot 会根据依赖的类路径自动检测并配置相应的组件。例如,当引入 MyBatis 依赖时,Spring Boot 会自动检测到 MyBatis 相关的配置类,并将其集成到应用程序中。

因此,我们无需手动配置扫描路径或使用 @ComponentScan 注解来扫描第三方依赖的包。这种自动配置的方式大大简化了开发流程,并使得应用程序的配置更加简洁和易于维护。

@Import

@Import 注解主要有以下几种形式:

导入类: 可以直接将一个或多个类导入到当前的配置类中。这些类可以是普通的配置类、普通的 Bean 类或者其他注解类。

@Import({MyConfiguration.class, MyBean.class})

导入 ImportSelector 接口实现类: ImportSelector 接口允许我们根据条件动态地选择要导入的配置类。通过实现 ImportSelector 接口,我们可以根据条件返回需要导入的配置类的全限定名数组。

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        // 根据条件动态选择要导入的配置类
        if (someCondition) {
            return new String[]{MyConfiguration1.class.getName()};
        } else {
            return new String[]{MyConfiguration2.class.getName()};
        }
    }
}

然后需要在配置类中使用 @Import 注解导入 ImportSelector 接口实现类。

@Import(MyImportSelector.class)
@Import(MyImportSelector.class)
@SpringBootApplication
public class SpringAutoconfigApplication {
 public static void main(String[] args) {
 SpringApplication.run(SpringAutoconfigApplication.class, args);
 }
}

可以看到, 我们采⽤这种⽅式也可以导⼊第三⽅依赖提供的Bean.
问题:
但是他们都有⼀个明显的问题, 就是使⽤者需要知道第三⽅依赖中有哪些Bean对象或配置类. 如果漏掉其中⼀些Bean, 很可能导致我们的项⽬出现⼤的事故.
这对程序员来说⾮常不友好.
依赖中有哪些Bean, 使⽤时需要配置哪些bean, 第三⽅依赖最清楚, 那能否由第三⽅依赖来做这件事呢?
⽐较常⻅的⽅案就是第三⽅依赖给我们提供⼀个注解, 这个注解⼀般都以@EnableXxxx开头的注解, 注解中封装的就是 @Import 注解

第三⽅依赖提供注解 

import org.springframework.context.annotation.Import;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(MyImportSelector.class)//指定要导⼊哪些类
public @interface EnableBiteConfig {
}

 注解中封装 @Import 注解, 导⼊ MyImportSelector.class

在启动类上使⽤第三⽅提供的注解
@EnableBiteConfig
@SpringBootApplication
public class SpringAutoconfigApplication {
 public static void main(String[] args) {
 SpringApplication.run(SpringAutoconfigApplication.class, args);
 }
}

SpringBoot原理分析

源码阅读

SpringBoot 是如何帮助我们做的呢? ⼀切的起源自SpringBoot的启动类:

定义一个注解 @SpringBootApplication,用于标识 Spring Boot 应用程序的主类。该注解包含了 @SpringBootConfiguration、@EnableAutoConfiguration 和 @ComponentScan 注解,并且提供了一些属性用于配置自动配置和组件扫描。

// 声明一个注解,用于标注 Spring Boot 应用的主类
package org.springframework.boot.autoconfigure;
 
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.core.annotation.AliasFor;
 
@Target({ElementType.TYPE}) // 该注解可以作用于类上
@Retention(RetentionPolicy.RUNTIME) // 注解信息保留到运行时
@Documented // 注解包含在 Javadoc 中
@Inherited // 允许子类继承父类的注解
@SpringBootConfiguration // 该注解标注当前类是 Spring Boot 的配置类
@EnableAutoConfiguration // 启用自动配置
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    Class<?>[] exclude() default {}; // 排除自动配置的类
 
    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    String[] excludeName() default {}; // 排除自动配置的类的名称
 
    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackages"
    )
    String[] scanBasePackages() default {}; // 扫描的基础包路径
 
    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackageClasses"
    )
    Class<?>[] scanBasePackageClasses() default {}; // 扫描的基础包路径下的类
 
    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "nameGenerator"
    )
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class; // 生成 Bean 名称的策略类,默认为 BeanNameGenerator
 
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true; // 是否启用代理 Bean 方法,默认为 true
}

@SpringBootApplication 是一个组合注解,注解中包含了:

元注解

元注解是一种特殊类型的注解,用于对其他注解进行注解。在Java开发工具包(JDK)中,有四个标准的元注解,也称为meta-annotation,分别是@Target、@Retention、@Documented和@Inherited。

  • @Target:用于描述被修饰的注解可以应用的范围。这意味着它指定了注解可以放置在哪些元素上,例如类、方法、字段等。通过指定不同的ElementType参数,可以限制注解的使用范围,从而确保注解的正确使用。
  • @Retention:用于描述注解被保留的时间范围。这决定了注解的生命周期,即它在什么时候会被丢弃。有三种保留策略:
  1. RetentionPolicy.SOURCE:编译器将会丢弃该注解,它不会包含在编译后的类文件中。
  2. RetentionPolicy.CLASS:注解将会被包含在编译后的类文件中,但在运行时不可获取。
  3. RetentionPolicy.RUNTIME:注解将被包含在类文件中,并且在运行时可以通过反射机制获取到。
  • @Documented:用于描述是否在使用Java文档工具(如javadoc)为类生成文档时保留其注解信息。如果一个注解被@Documented修饰,那么在生成文档时,这个注解会被包含进去,使得开发者能够清晰地了解类的注解信息。
  • @Inherited:使被它修饰的注解具有继承性。如果某个类使用了被@Inherited修饰的注解,则其子类将自动具有该注解。这意味着如果一个类被标注为某个注解,那么它的子类也会继承这个注解,除非子类显式地覆盖了这个注解。这对于定义一些通用的行为或特征并让子类继承这些行为或特征是非常有用的。
@SpringBootConfiguration

这段代码定义了一个自定义的注解@SpringBootConfiguration,它实际上是对@Configuration注解的封装,并添加了一些额外的功能。⾥⾯就是@Configuration, 标注当前类为配置类, 其实只是做了⼀层封装改了个名字⽽已.

(@Indexed注解,是⽤来加速应⽤启动的, 不⽤关⼼)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
 @AliasFor(
 annotation = Configuration.class
 )
 boolean proxyBeanMethods() default true;
}
@EnableAutoConfiguration (开启⾃动配置)
Spring⾃动配置的核⼼注解, 下⾯详细讲解
@ComponentScan (包扫描)
可以通过 basePackageClasses basePackages 来定义要扫描的特定包, 如果没有定义
特定的包, 将从声明该注解的类的包开始扫描, 这也是为什么SpringBoot项⽬声明的注解类必须要在
启动类的⽬录下.
excludeFilters ⾃定义过滤器, 通常⽤于排除⼀些类, 注解等.
EnableAutoConfiguration 详解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
 String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
 Class<?>[] exclude() default {};
 String[] excludeName() default {};
}
这个注解包含两部分:
@Import({AutoConfigurationImportSelector.class})
使⽤@Import注解,导⼊了实现ImportSelector接⼝的实现类.
public class AutoConfigurationImportSelector implements
DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, 
BeanFactoryAware, EnvironmentAware, Ordered {
 public String[] selectImports(AnnotationMetadata annotationMetadata) {
 if (!this.isEnabled(annotationMetadata)) {
 return NO_IMPORTS;
 } else {
 //获取⾃动配置的配置类信息
 AutoConfigurationEntry autoConfigurationEntry = 
this.getAutoConfigurationEntry(annotationMetadata);
 return
StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
 }
}
}
selectImports() ⽅法底层调⽤ getAutoConfigurationEntry() ⽅法, 获取可⾃动配置的
配置类信息集合.
/**
 * 根据提供的注解元数据获取自动配置条目。
 *
 * @param annotationMetadata 提供有关注解组件上的注解信息的注解元数据。
 * @return AutoConfigurationEntry,表示自动配置条目
 */
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
    // 如果未启用自动配置,则返回一个空的自动配置条目
    if (!this.isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    } else {
        // 获取注解属性
        AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
        // 获取候选配置类列表
        List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
        // 去除重复的配置类
        configurations = this.removeDuplicates(configurations);
        // 获取排除的配置类列表
        Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
        // 检查排除的配置类是否存在重复
        this.checkExcludedClasses(configurations, exclusions);
        // 从候选配置类中移除排除的配置类
        configurations.removeAll(exclusions);
        // 应用配置类过滤器
        configurations = this.getConfigurationClassFilter().filter(configurations);
        // 触发自动配置导入事件
        this.fireAutoConfigurationImportEvents(configurations, exclusions);
        // 返回新的自动配置条目
        return new AutoConfigurationEntry(configurations, exclusions);
    }
}
getAutoConfigurationEntry() ⽅法通过调⽤getCandidateConfigurations(annotationMetadata, attributes) ⽅法获取在配置⽂件中配置的所有⾃动配置类的集合
//获取所有基于
//METAINF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports⽂件
//META-INF/spring.factories⽂件中配置类的集合
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, 
AnnotationAttributes attributes) {
 List<String> configurations = new
ArrayList(SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderF
actoryClass(), this.getBeanClassLoader()));
 ImportCandidates.load(AutoConfiguration.class, 
this.getBeanClassLoader()).forEach(configurations::add);
 Assert.notEmpty(configurations, "No auto configuration classes found in 
META-INF/spring.factories nor in METAINF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. 
If you are using a custom packaging, make sure that file is correct.");
 return configurations;
 }
getCandidateConfigurations ⽅法的功能:
获取所有基于 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imp
orts ⽂件, META-INF/spring.factories ⽂件中配置类的集合.
在引⼊的起步依赖中, 通常都有包含以上两个⽂件

这⾥⾯包含了很多第三⽅依赖的配置⽂件

在加载⾃动配置类的时候, 并不是将所有的配置全部加载进来, ⽽是通过@Conditional等注解的判
断进⾏动态加载.
@Conditional是spring底层注解, 意思就是根据不同的条件, 来进⾏⾃⼰不同的条件判断,如果满⾜指定的条件,那么配置类⾥边的配置才会⽣效.
META-INF/spring.factories⽂件是Spring内部提供的⼀个约定俗成的加载⽅式, 只需要在模块的
META-INF/spring.factories⽂件中配置即可, Spring就会把相应的实现类注⼊到Spring容器中.
注: 会加载所有jar包下的classpath路径下的META-INF/spring.factories⽂件, 这样⽂件不⽌⼀个

@AutoConfigurationPackage
源码如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({AutoConfigurationPackages.Registrar.class})
public @interface AutoConfigurationPackage {
 String[] basePackages() default {};
 Class<?>[] basePackageClasses() default {};
}
这个注解主要是导⼊⼀个配置⽂件 AutoConfigurationPackages.Registrar.class
static class Registrar implements ImportBeanDefinitionRegistrar, 
DeterminableImports {
 Registrar() {
 }
 public void registerBeanDefinitions(AnnotationMetadata metadata, 
BeanDefinitionRegistry registry) {
 AutoConfigurationPackages.register(registry, (String[])(new
PackageImports(metadata)).getPackageNames().toArray(new String[0]));
 }
 public Set<Object> determineImports(AnnotationMetadata metadata) {
 return Collections.singleton(new PackageImports(metadata));
 }
}
Registrar实现了 ImportBeanDefinitionRegistrar 类, 就可以被注解@Import导⼊到spring
容器⾥.
/**
 * 内部静态类Registrar实现了ImportBeanDefinitionRegistrar和DeterminableImports接口
 * 用于注册Bean定义和确定导入项
 */
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
    Registrar() {
    }
 
    /**
     * 注册Bean定义的方法,将自动配置包注册到注册表中
     * @param metadata 注解元数据
     * @param registry Bean定义注册表
     */
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        // 使用PackageImports类获取包名,并将其注册到自动配置包中
        AutoConfigurationPackages.register(registry, (String[])(new PackageImports(metadata)).getPackageNames().toArray(new String[0]));
    }
 
    /**
     * 确定导入项的方法
     * @param metadata 注解元数据
     * @return 包含PackageImports类的集合
     */
    public Set<Object> determineImports(AnnotationMetadata metadata) {
        return Collections.singleton(new PackageImports(metadata));
    }
}

(String[])(new PackageImports(metadata)).getPackageNames().toArray(new
String[0]) : 当前启动类所在的包名.
所以: @AutoConfigurationPackage 就是将启动类所在的包下⾯所有的组件都扫描注冊到
这段代码的目的是将特定的包名注册到Spring Boot的自动配置包中,以便Spring能够自动扫描这些包中的类,并将它们实例化为Bean,以供应用程序使用。
  • PackageImports(metadata):这行代码创建了一个PackageImports对象,该对象从传入的metadata中获取了与注解相关的信息,然后通过这些信息确定了需要注册到自动配置包的包名。
  • new PackageImports(metadata).getPackageNames():这部分代码调用了PackageImports对象的getPackageNames()方法,以获取到需要注册到自动配置包中的包名集合。
  • .toArray(new String[0]):将获取到的包名集合转换为数组。
  • AutoConfigurationPackages.register(registry, ...):这一行代码调用了AutoConfigurationPackages类的register方法,该方法接受一个BeanDefinitionRegistry对象和一个包名数组作为参数。在Spring Boot内部,AutoConfigurationPackages类负责管理自动配置包,并将注册的包名添加到自动配置包中。这样一来,Spring在启动时就会扫描这些包,寻找带有特定注解的类,并将它们实例化为Bean。

综上所述,我们可以来总结一下:

当我们使用@EnableAutoConfiguration注解时,它实际上是启动了Spring Boot的自动配置功能,其实现原理涉及几个关键部分:

@Import({AutoConfigurationImportSelector.class})

通过@Import注解,导入了实现了ImportSelector接口的AutoConfigurationImportSelector类。ImportSelector接口的实现类可以根据条件动态地选择需要导入的配置类。

AutoConfigurationImportSelector

AutoConfigurationImportSelector类的selectImports()方法负责选择需要导入的配置类。底层调用了getAutoConfigurationEntry()方法,获取可自动配置的配置类信息集合。

getAutoConfigurationEntry()方法

getAutoConfigurationEntry()方法通过调用getCandidateConfigurations()方法获取在配置文件中配置的所有自动配置类的集合。

getCandidateConfigurations()方法

getCandidateConfigurations()方法获取所有基于META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件和META-INF/spring.factories文件中配置类的集合。这些配置文件通常包含了许多第三方依赖的自动配置类。

动态加载自动配置类

在加载自动配置类时,并不是将所有的配置全部加载进来,而是通过@Conditional等注解的判断进行动态加载。@Conditional是Spring底层注解,根据不同的条件进行不同的条件判断,如果满足指定的条件,配置类里边的配置才会生效。

@AutoConfigurationPackage注解

@AutoConfigurationPackage注解将启动类所在的包下面所有的组件都扫描注册到Spring容器中。这样,Spring容器就能够扫描到启动类所在包及其子包中的所有组件,并将其注册为Spring Bean。


总的来说,@EnableAutoConfiguration注解启用了Spring Boot的自动配置功能,它通过导入AutoConfigurationImportSelector类和@AutoConfigurationPackage注解,动态加载自动配置类,并根据条件进行判断和加载,最终完成Spring应用程序的自动配置。

SpringBoot ⾃动配置原理的大概流程如下:

当Spring Boot程序启动时,会自动加载配置文件中所定义的配置类,并通过@Import注解将这些配置类全部加载到Spring的IOC容器中,交由IOC容器管理。这样做的目的是为了简化Spring应用的配置和开发过程,让开发者专注于业务逻辑的实现而不必过多关注框架的配置。

具体来说,Spring Boot的自动配置原理可以概括如下:

  1. 启动过程:当Spring Boot应用启动时,会自动扫描classpath下的META-INF/spring.factories文件,该文件中列出了所有自动配置类的全限定名。
  2. 自动配置类:Spring Boot通过这些自动配置类来自动配置应用的各种组件,比如数据源、JPA、Web容器等等。这些自动配置类通过注解@Configuration标识,告诉Spring这是一个配置类。
  3. 条件装配:自动配置类中的各个Bean的创建是有条件的,Spring Boot利用条件注解(如@ConditionalOnClass、@ConditionalOnMissingBean等)来根据类路径、Bean是否存在等条件来决定是否创建某个Bean。
  4. 加载配置:Spring Boot会加载应用的配置文件(application.properties或application.yml),对一些默认配置值进行修改,并将这些配置信息注入到相应的Bean中
  5. IOC容器管理:最终,这些自动配置类中的Bean会被添加到Spring的IOC容器中进行管理。开发者可以通过@Autowired注解或者其他方式来获取并使用这些Bean。

总之,Spring Boot的自动配置机制大大简化了Spring应用的开发和部署流程,我们只需要遵循约定大于配置的原则,即可快速搭建出一个功能完善的Spring应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1982685.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux - - - Linux 添加环境变量

1.添加环境变量 编辑环境变量配置文件。 vim /etc/profile在最后面新增一行&#xff0c;导出 PATH 变量并在之前的 PATH 变量后面添加冒号&#xff0c;然后添加上你的可执行文件的目录。 export PATH$PATH:/usr/local/aspnetcore/aspnetcore-runtime-8.0.7-linux-x64/2.加载…

GD32 SPI 通信协议

1.0 SPI 简介 SPI是一种串行通信接口&#xff0c;相对于IIC而言SPI需要的信号线的个数多一点&#xff0c;时钟的信号是主机产生的。 MOSI&#xff1a;主机发送&#xff0c;从机接收 MISO&#xff1a;主机接收&#xff0c;从机发送 CS&#xff1a;表示的是片选信号 都是单向…

在线Banner设计工具大比拼:谁更胜一筹

在数字营销的时代&#xff0c;一个吸引眼球的 Banner 广告是吸引潜在客户、提高品牌知名度的关键。为了帮助营销人员和设计师快速创建专业的 Banner 广告&#xff0c;市面上出现了多种易于使用的 Banner 设计工具。本文将介绍几个受欢迎的 Banner 设计工具&#xff0c;包括即时…

路径规划——A*算法

路径规划——A*算法 算法原理 为了解决Dijkstra算法效率低的问题&#xff0c;A Star 算法作为一种启发式算法被提出。该算法在广度优先的基础上加入了一个估价函数。如BFS和常规方法如Dijsktra算法结合在一起的算法&#xff0c;有点不同的是&#xff0c;类似BFS的启发式经常给…

RGB红绿灯——Arduino

光的三原色 牛顿发现光的色散奥秘之后&#xff0c;进一步计算发现&#xff1a;七种色光中只有红、绿、蓝三种色光无法被分解&#xff0c;而其他四种颜色的光均可由这三种色光以不同比例相合而成。于是红、绿、蓝被称为“三原色光”或“光的三原色”。后经证实&#xff1a;红、绿…

提升C++开发效率的利器:深入解析Clang Power Tools

目录 一、引言 二、Clang Power Tools 简介 什么是 Clang Power Tools&#xff1f; 背景与发展历史 与 Clang 编译器的关系 主要开发团队和社区支持 系统要求 安装步骤 基本配置和使用 三、主要功能 代码格式化&#xff08;Clang-Format&#xff09; 代码质量提升 …

springboot+Loki+Loki4j+Grafana搭建轻量级日志系统

文章目录 前言一、日志组件介绍1.1 Loki组件1.2 Loki4j组件1.3 Grafana 二、组件下载安装运行Loki下载安装运行Grafana下载安装运行 三、创建springboot项目总结 前言 日志在任何一个web应用中都是不可忽视的存在&#xff0c;它已经成为大部分系统的标准组成部分。搭建日志可视…

【大模型】Unsloth安装及使用教程

Unsloth是一个开源的大模型训练加速项目&#xff0c;使用OpenAI的Triton对模型的计算过程进行重写&#xff0c;大幅提升模型的训练速度&#xff0c;降低训练中的显存占用。Unsloth能够保证重写后的模型计算的一致性&#xff0c;实现中不存在近似计算&#xff0c;模型训练的精度…

【Material-UI】Button 组件中的基本按钮详解

文章目录 一、基本按钮变体1. 文本按钮&#xff08;Text Button&#xff09;2. 实心按钮&#xff08;Contained Button&#xff09;3. 轮廓按钮&#xff08;Outlined Button&#xff09; 二、应用场景与注意事项1. 使用场景2. 注意事项 三、总结 Material-UI 的 Button 组件是前…

ShardingProxy使用自定义策略,数据迁移方案

文章目录 ShardingProxy功能扩展分库分表数据迁移方案 ShardingProxy功能扩展 我们在使用ShardingJDBC时&#xff0c;会进行自定义分布式主键生成策略、自定义分片策略 如果我们想要我们自定义的这些策略在ShardingProxy中也能使用&#xff0c;应该如何操作嘞&#xff1f; 我…

使用F1C200S从零制作掌机之I2C传感器

访问I2C设备&#xff08;比如eeprom&#xff09;&#xff0c;我知道的有三总方法&#xff1a; &#xff08;一&#xff09;i2c-dev操作I2C设备&#xff1a;不用添加设备驱动&#xff0c;用户直接在应用层完成对具体I2C 设备的驱动工作。 &#xff08;二&#xff09;sysfs操作…

微信小程序教程011-:2:京西购物商城实战之TabBar实现

2、tabBar 2.0 创建tabBar分支 运行如下命令,基于master分支,创建本地tabBar子分支,用来开发和tabBar相关的功能 git checkout -b tabbar2.1 创建tabBar页面 在pages目录中,创建首页(home)、分类(cate)、购物车(cart)、我的(my)这4个tabBar页面,在HBuilderX中…

【网络世界】数据链路层

目录 &#x1f308;前言&#x1f308; &#x1f4c1; 初识数据链路层 &#x1f4c2; 概念 &#x1f4c2; 协议格式 &#x1f4c1; MAC地址 &#x1f4c2; 概念 &#x1f4c2; 与IP地址的区别 &#x1f4c1; MTU &#x1f4c2; 对IP协议的影响 &#x1f4c2; 对UDP协议的影响…

思维+位运算,CF 1934D1 - XOR Break --- Solo Version

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1934D1 - XOR Break --- Solo Version 二、解题报告 1、思路分析 合法操作会让 n 越变越小 假如最高位1为 b1, 次高位1 为b2 那么我们去掉b1 的 1最大能够得到的数为 &#xff08;1 << b2&#xff…

图像传感器 - 从零开始认识各种传感器【二十六期】

图像传感器|从零开始认识各种传感器 1、什么是图像传感器&#xff1f; 图像传感器是将光信号转换为电信号的设备&#xff0c;图像传感器通过捕捉光子并将其转化为电子信号&#xff0c;从而生成数字图像。它是数码相机、摄像机、智能手机、无人机、自动驾驶汽车以及各种工业和医…

良心推荐!分享6个强大的电脑软件,每一个都非常实用

良心推荐&#xff01;分享6个功能强大的电脑软件&#xff0c;每一个都非常实用&#xff01; 1.Listen1 一个可以免费听音乐的软件&#xff0c;也可以在浏览器上作为插件使用&#xff0c;曲库丰富&#xff0c;里面涵盖了QQ音乐、酷狗音乐、网易云音乐等多个平台的歌单资源&…

【MySQL】索引——索引的实现、B+ vs B、聚簇索引 VS 非聚簇索引、索引操作、创建索引、查询索引、删除索引

文章目录 MySQL5. 索引的实现5.1 B vs B5.2 聚簇索引 VS 非聚簇索引 6. 索引操作6.1 创建主键索引6.2 创建唯一索引6.3 创建普通索引6.4 创建全文索引6.5 查询索引6.6 删除索引 MySQL 5. 索引的实现 因为MySQL和磁盘交互的基本单位为Page&#xff08;页&#xff09;。 MySQL 中…

LTrack:实现夜间多目标追踪,并开放低光多目标追踪数据集LMOT

摘要 低光场景在现实应用中很常见&#xff08;例如&#xff0c;夜间的自动驾驶和监控&#xff09;。最近&#xff0c;多目标跟踪在各种实际用例中受到了很多关注&#xff0c;但黑暗场景中的多目标跟踪却很少被考虑。在本文中&#xff0c;我们专注于黑暗场景中的多目标跟踪。为…

点菜吧——随便点 C#生成套餐

前言 一到食堂发现有多种选择&#xff0c;但是有一个固定的套路&#xff0c;只能是一个荤&#xff0c;二个小荤&#xff0c;菜品数量也不少&#xff0c;任君选择&#xff0c;如果是一个选择困难症&#xff0c;就有点烦了&#xff0c;所以出品这个自动生成套餐软件。各位老板可…

Mysql原理与调优-InnoDB行记录结构

目录 1.绪论 2.InnoDB的记录格式分类 3.compact格式 3.1 基本组成 3.2 记录额外信息 3.2.1 记录额外信息组成 3.2.2 变成字段长度列表 3.2.3 null值列表 3.2.4 记录头信息 3.3 实际记录 3.3.1 溢出页 3.3.2 varchar最多可以储存多少个字符的数据 4.其他记录格式和c…