【一】springboot启动源码
创始人
2025-05-30 14:14:28
0

说明

SpringBoot 版本 2.7.1

SpringApplication.run(),refresh()调用之前解析

  1. SpringApplication在构造方法时,就会读取META-INF/spring.factories的类,缓存到SpringFactoriesLoader中(这是Spring的SPI),注意这里的缓存不仅仅只有org.springframework.boot.autoconfigure.EnableAutoConfiguration,包括文件中所有key-value
    在这里插入图片描述
    在这里插入图片描述
    缓存是一个静态变量
    在这里插入图片描述

  2. SpringApplication第298行,通过SPI从META-INF/spring.factories获取org.springframework.boot.SpringApplicationRunListener的实现类并加载
    在这里插入图片描述
    通过构造器创建自定义RunListener实例
    在这里插入图片描述
    进入到自定义RunListener的构造方法
    在这里插入图片描述

  3. 第299行,通过spring.factories获取的所有SpringApplicationRunListener的实现类,并调用start方法
    在这里插入图片描述
    在这里插入图片描述

  4. SpringApplication第302行,创建spring环境配置类,默认环境变量实现类为ApplicationServletEnvironme
    在这里插入图片描述ApplicationServletEnvironment的抽象父类为AbstractEnvironment,他的成员变量MutablePropertySources propertySources是环境变量核心。包含了List> propertySourceList
    在这里插入图片描述
    PropertySource类结构
    在这里插入图片描述
    继续回到ApplicationServletEnvironment的构造方法创建,在默认调用抽象父类的构造中,执行了customizePropertySources(MutablePropertySources propertySources)方法
    在这里插入图片描述
    这个方法由ApplicationServletEnvironment的直接父类StandardServletEnvironment来实现,添加了两个默认的propertySource,再去调用StandardServletEnvironment的直接父类StandardEnvironment的customizePropertySources(MutablePropertySources propertySources)方法。再添加两个默认的propertySource,这里就包含了系统配置System.getProperties()和系统运行环境System.getenv()
    在这里插入图片描述
    以上只是prepareEnvironment方法的第341行逻辑,341行之后,还会添加一些propertySource、调用省略SpringApplicationRunListener的environmentPrepared方法等
    在这里插入图片描述
    完成spring环境配置类创建

  5. 创建IOC核心ApplicationContext,第305行
    context核心变量的核心包括:
    a. List beanFactoryPostProcessors
    b. ConfigurableEnvironment environment
    c. DefaultListableBeanFactory beanFactory
    在这里插入图片描述
    默认ApplicationContext的实现类是AnnotationConfigServletWebServerApplicationContext
    在这里插入图片描述
    它的间接父类是GenericApplicationContext,构造方法中初始化了beanFactory,这里与spring的ClassPathXmlApplicationContext有区别,ClassPathXmlApplicationContext是在refresh执行时才创建beanFactory,而GenericApplicationContext是在refresh之前
    以上为创建ApplicationContext逻辑。

  6. 进行ApplicationContext赋值处理,SpringApplication第307行prepareContext方法
    在这里插入图片描述
    进入prepareContext方法,这里赋值了environment、添加默认类到IOC容器(beanFactory的间接父类DefaultSingletonBeanRegistry中的singletonObjects,作为一级缓存)、设置循环依赖状态、添加默认BeanFactoryPostProcessor
    在这里插入图片描述
    调用SpringApplicationRunListener的contextPrepared、contextLoaded方法
    在这里插入图片描述
    在这里插入图片描述

  7. SpringApplication第308行,核心方法refreshContext(context);
    在这里插入图片描述
    调用context.refresh(),由AnnotationConfigServletWebServerApplicationContext的间接抽象父类AbstractApplicationContext来实现。

Context.refresh()调用方法解析

  1. AbstractApplicationContext第553行obtainFreshBeanFactory()
    在这里插入图片描述

这里的实现很简单,只是返回了beanFactory对象(如果context是用spring的ClassPathXmlApplicationContext,会在这里进行beanDefinition的构建,这里不做深入区别讨论)

在这里插入图片描述

  1. AbstractApplicationContext第556行,prepareBeanFactory

Prepare the bean factory for use in this context.

在这里插入图片描述
会默认添加一些beanPostProcess实现(比如ApplicationContextAwareProcessor,用来判断bean是否实现了各种Aware接口,如果实现了,ApplicationContextAwareProcessor会在postProcessBeforeInitialization执行回调)。
在这里插入图片描述

会默认注册一些单例bean到ioc容器(比如 environment、systemProperties、systemEnvironment等)。DefaultListableBeanFactory的父类DefaultSingletonBeanRegistry,里面的成员变量 Map singletonObjects,作为IOC容器用来存放单例对象,注册的单例bean会放在这里。
在这里插入图片描述

  1. AbstractApplicationContext第560行,postProcessBeanFactory

Allows post-processing of the bean factory in context subclasses.

在这里插入图片描述
由AnnotationConfigServletWebServerApplicationContext实现
在这里插入图片描述
super.postProcessBeanFactory(beanFactory)。会添加WebApplicationContextServletContextAwareProcessor到BeanPostProcessor

在这里插入图片描述
4. AbstractApplicationContext第564行,invokeBeanFactoryPostProcessors。
这个方法会执行springboot的自动装配核心逻辑

Invoke factory processors registered as beans in the context.

在这里插入图片描述
在这里插入图片描述
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors 方法
第112行invokeBeanDefinitionRegistryPostProcessors
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
进入ConfigurationClassPostProcessor.processConfigBeanDefinitions方法
从beanFactory的beanDefinitionMap中,目前beanDefinitionMap的数据只有初始化时候加入的,如下
在这里插入图片描述

接着第287行 ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory),会依次遍历判断是否有@Configuration注解,启动类因为有@SpringBootApplication,它引用了@SpringBootConfiguration,而@SpringBootConfiguration又引用了@Configuration。把符合要求的BeanDefinition封装成BeanDefinitionHolder(第288行),然后加入到 List configCandidates 集合中

configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));

通过过滤放这里configCandidates集合只有启动类
在这里插入图片描述

第327行
Set candidates = new LinkedHashSet<>(configCandidates);
332行
构建了一个
ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment,this.resourceLoader, this.componentScanBeanNameGenerator, registry);

processConfigBeanDefinitions方法第329-367行,递归遍历candidates集合,解析每一个BeanDefinitionHolder
第331行 parser.parse(candidates)
在这里插入图片描述
ConfigurationClassParser的parse方法,第175行
在这里插入图片描述
ConfigurationClassParser第206行,parse的重载方法
在这里插入图片描述
进入ConfigurationClassParser第225行,processConfigurationClass
第250行,开始处理@Configuration注解的类逻辑
在这里插入图片描述
进入doProcessConfigurationClass,可以看到这里针对类上的注解做了很多判断,是否有@Component、@PropertySource、@ComponentScan、@Import注解等
在这里插入图片描述
先看ConfigurationClassParser-doProcessConfigurationClass-272行,当类上有@Component注解时,判断是否有内部类,再递归判断内部类是否有@Component
在这里插入图片描述

在这里插入图片描述
ConfigurationClassParser-第276行,判断是否有@PropertySources注解
在这里插入图片描述
ConfigurationClassParser-第442行开始,processPropertySource 方法
先判断@PropertySource的value是否为空(这是必要配置),然后加载value的值为Resource对象
ConfigurationClassParser-第463行,factory.createPropertySource(name, new EncodedResource(resource, encoding)),这里的factory默认是DefaultPropertySourceFactory
在这里插入图片描述

ConfigurationClassParser-第479行,进入DefaultPropertySourceFactory.createPropertySource方法

在这里插入图片描述
会创建并返回ResourcePropertySource对象
ResourcePropertySource的构造方法如下,通过getNameForResource(resource.getResource()) 和 *PropertiesLoaderUtils.loadProperties(resource)方法构造成 String name 和 Properties source,继续调用父类构造方法
在这里插入图片描述
最终ResourcePropertySource的顶层抽象类为PropertySource。构造完成后返回
在这里插入图片描述
回到ConfigurationClassParser-463行,将构造返回的propertySource,再调用
addPropertySource(propertySource)*方法

在这里插入图片描述
ConfigurationClassParser-479行,addPropertySource方法
判断environment的propertySources是否已经包含了此propertySource,如果没有包含,添加到propertySources中
第505-510行,是用来判断插入propertySources的位置
在这里插入图片描述
回到ConfigurationClassParser-280行,处理完了@PropertySources的逻辑,继续往下
ConfigurationClassParser-289行,开始处理@ComponentScan逻辑,进入296行componentScanParser.parse
在这里插入图片描述
ComponentScanAnnotationParser-68行parse方法,初始化ClassPathBeanDefinitionScanner类,处理了basePackages的包扫描路径等
在这里插入图片描述
直接看到ComponentScanAnnotationParser-128行,ClassPathBeanDefinitionScanner scanner.doScan(StringUtils.toStringArray(basePackages));
在这里插入图片描述
进入ClassPathBeanDefinitionScanner-272行的doScan方法,入参为scanBasePackages的值
从275行开始,遍历所有basePackages,276行,从basePackage的值开始扫描符合要求的bean,并封装成BeanDefinition
在这里插入图片描述
由父类ClassPathScanningCandidateComponentProvider实现findCandidateComponents 方法,第311行
再进入316行 scanCandidateComponents(basePackage);
在这里插入图片描述
ClassPathScanningCandidateComponentProvider第416行开始
获取classpath下符合basePackage的 .class路径。如这里的: classpath:org/hopehomi/**/*.class
在这里插入图片描述
获取到该路径下所有的 *.class路径
在这里插入图片描述

tips: 
基于class扫描,我们可以自定义ResourceLoaderAware,或者直接继承ClassPathScanningCandidateComponentProvider。
使用ClassPathScanningCandidateComponentProvider的class加载能力package org.hopehomi.core.tool.aware;import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;/*** @author Ledison* @date 2023/3/17*/
public class HopeResourceLoaderAware extends ClassPathScanningCandidateComponentProvider implements ResourceLoaderAware{private ResourceLoader resourceLoader;private final String DEFAULT_RESOURCE_PATTERN = "/**/*.class";private ClassPathScanningCandidateComponentProvider provider;@Overridepublic void setResourceLoader(ResourceLoader resourceLoader) {provider = new ClassPathScanningCandidateComponentProvider(true);provider.setResourceLoader(resourceLoader);this.resourceLoader = resourceLoader;}public Resource[] getPackagePathResources(String packagePath) throws IOException {ResourcePatternResolver resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);packagePath = packagePathParse(packagePath);// classpath*:org/hopehomi/**/*.classreturn resourcePatternResolver.getResources(packagePath);}private String packagePathParse(String packagePath) {packagePath = packagePath.replace(".","/");if (!packagePath.startsWith(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX)) {// 不是以classpath开头packagePath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + packagePath;}if (!packagePath.endsWith(DEFAULT_RESOURCE_PATTERN)) {packagePath += DEFAULT_RESOURCE_PATTERN;}return packagePath;}public List getPackagePathClassNames(String packagePath) throws IOException {List classNames = new ArrayList<>();Resource[] packagePathResources = this.getPackagePathResources(packagePath);CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);for (Resource resource : packagePathResources) {MetadataReader metadataReader = cachingMetadataReaderFactory.getMetadataReader(resource);classNames.add(metadataReader.getClassMetadata().getClassName());}return classNames;}public Set getPackagePathBeanDefinitions(String packagePath) {packagePath = packagePath.replace(".","/");return provider.findCandidateComponents(packagePath);}}

解析每一个resource,429行,通过CachingMetadataReaderFactory将resource构建成MetadataReader
430行isCandidateComponent来判断MetadataReader是否包含@Component注解
在这里插入图片描述
这里进行判断是否有@Component
在这里插入图片描述

如果包含,将metadataReader构建成beanDefinition,加入candidates。
注意这里只要有@Component注解就会加入到集合,并没有处理bean上面的Condition相关注解
在这里插入图片描述
上面的ignoreModel是加了@ConditionalOnBean(Test.class)。Test只是一个普通类

package org.hopehomi.boot.config;import org.hopehomi.boot.controller.Test;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Component;/*** @author Ledison* @date 2023/3/16*/
@ConditionalOnBean(Test.class)
@Component
public class IgoreModel {}
package org.hopehomi.boot.controller;import lombok.Data;/*** @author Ledison* @date 2023/3/16*/
@Data
public class Test  {private String name = "zhangsan";
}

findCandidateComponents方法执行完后,回到ClassPathBeanDefinitionScanner第277行
将返回的Set candidates(@Component的Bean)构造成BeanDefinitionHolder
并在292行,将每个BeanDefinition加入到beanFactory的beanDefinitionMap中
在这里插入图片描述
添加到beanDefinitionMap的过程略,最终beanFactory的beanDefinitionMap结果如下
注意这里只是把beanDefinition放入了beanDefinitionMap,没有对bean进行任何初始化操作

在这里插入图片描述
以上是ConfigurationClassParser-doProcessConfigurationClass-295行的逻辑。通过启动类上ComponentScan注解,加载了包下面符合要求的@Component并构建成BeanDefinitionHolder。
小提一点:springboot是通过扫描来加载beanDefinition,而springXml是通过解析XML文件来加载beanDefinition
从298行开始,会开始递归这些BeanDefinitionHolder,让每一个BeanDefinitionHolder都走一遍刚才的加载流程
在这里插入图片描述
接下来ConfigurationClassParser-doProcessConfigurationClass-311行。
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
先看getImports方法
在这里插入图片描述
进入collectImports(sourceClass, imports, visited);
这里会递归,直到找到@Import注解。比如@SpringBootApplication 上的 @EnableAutoConfiguration上的@Import(AutoConfigurationImportSelector.class)
在这里插入图片描述
这里找到了@HopeSpringBootApplication上有@Import注解。引入了一个我定义的环境配置Selector

package org.hopehomi.core.launch.props;import org.hopehomi.core.launch.selector.EnvironmentConfigurationSelector;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.AliasFor;import java.lang.annotation.*;/*** @author Ledison* @date 2023/3/16*/@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@SpringBootApplication
@Import(EnvironmentConfigurationSelector.class)
public @interface HopeSpringBootApplication {@AliasFor(annotation = SpringBootApplication.class,attribute = "scanBasePackages")String[] scanBasePackages() default {};
}
package org.hopehomi.core.launch.selector;import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;/*** 环境基础配置** @author Ledison* @date 2023/3/16*/
public class EnvironmentConfigurationSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{"org.hopehomi.core.database.config.DruidConfiguration"};}
}

进入ConfigurationClassParser-collectImports-549行,sourceClass.getAnnotationAttributes(Import.class.getName(), “value”)
在这里插入图片描述
进入getAnnotationAttributes,第1068行,这里会获取到@Import的Value值,也就是@Import需要引入的类名
在这里插入图片描述
第1071行,执行getRelated方法,将引入的类名构造成SourceClass,并加入到集合返回
在这里插入图片描述
回到collectImports方法,第549行。添加到所有imports引用类的集合中
在这里插入图片描述
collectImports方法结束并返回,回到ConfigurationClassParser-getImports-522行。
以上代码总结为:获取从启动类开始,一直递归找到@Import的引入类,并放在集合返回,所有结果如下
imports表示满足@Import条件的,visited表示递归过的注解类
这里找到了 org.springframework.boot.autoconfigure.AutoConfigurationImportSelector(自动装配核心Selector),以及我们自定义的org.hopehomi.core.launch.selector.EnvironmentConfigurationSelector环境配置Selector
在这里插入图片描述
getImports方法结束,回到ConfigurationClassParser第311行,执行processImports方法

Process any @Import annotations

在这里插入图片描述
processImports方法,遍历所有importCandidates(SourceClass集合),判断每个SourceClass是否实现ImportSelector
如果实现了,会通过构造器生成实例,并判断Selector类是否实现了aware方法,将environment、beanFactory等变量设置到实例中
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果Selector实现了DeferredImportSelector(延时引入Selector),AutoConfigurationImportSelector实现了。进入578 行逻辑,将Selector放入延时引入的集合中
在这里插入图片描述
在这里插入图片描述

而如果Selector未实现DeferredImportSelector,比如我们自定义的Selector,进入581行逻辑
在这里插入图片描述
第582行,会通过默认的三个Condition(OnClass、OnWeb、OnBean,更详细的在后面还会说明)来判断是否需要过滤掉这个引入的Class,如果不需要过滤,继续将这些class会通过递归,也执行刚才的processImports逻辑
在这里插入图片描述
如果没有实现ImportSelector或者ImportBeanDefinitionRegistrar,会执行第600行逻辑,再执行processConfigurationClass,也是通过递归最终把@Component类,放入ConfigurationClassParser的configurationClasses变量
在这里插入图片描述
以上是通过@Import来加载配置类的逻辑
第ConfigurationClassParser-314行,通过@ImportResource来加载配置类
第326行,通过方法上的@Bean来加载配置类

doProcessConfigurationClass方法结束
在这里插入图片描述
结束方法后,来到ConfigurationClassParser-parse-193行。
这里开始处理延时引入的Selector(AutoConfigurationImportSelector)
在这里插入图片描述
进入process方法,创建DeferredImportSelectorGroupingHandler来处理每一个DeferredImportSelectorHolder
第780行开始执行DeferredImportSelectorHolder的
在这里插入图片描述
遍历DeferredImportSelectorGrouping,调用grouping.getImports()方法
在这里插入图片描述
getImports方法的第879行,进入this.group.process(这里的group是的AutoConfigurationImportSelector内部静态类AutoConfigurationGroup)
在这里插入图片描述
AutoConfigurationGroup-process-434行,准备开始通过Spring Spi读取自动装载类。
440行,进入getAutoConfigurationEntry方法
在这里插入图片描述
getAutoConfigurationEntry方法第125行getCandidateConfigurations
进入
进入getCandidateConfigurations方法,开始装载配置类
AutoConfigurationImportSelector的第182行,通过SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader())) 来装载配置类
在这里插入图片描述
getSpringFactoriesLoaderFactoryClass()方法返回的默认@EnableAutoConfiguration

在这里插入图片描述
getBeanClassLoader()方法返回类加载器(这里是appClassLoader)
在这里插入图片描述
进入SpringFactoriesLoader.loadFactoryNames(Class factoryType, @Nullable ClassLoader classLoader)
这里factoryType是EnableAutoConfiguration.class,classLoader是appClassLoader
表示加载spring.factories下,key为factoryType类型的value值
在这里插入图片描述
这里在applicationContext初始化的时候已经加载过一次SPI,所以SpringFactoriesLoader的cache变量是有值的。再根据factoryType进行过滤,返回EnableAutoConfiguration对应的value
在这里插入图片描述
AutoConfigurationImportSelector-getCandidateConfigurations-184行
ImportCandidates.load方法,用来加载META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件下的类
这个和java的SPI很类似,可以从下图看到初始化定义了很多类,这些类基本都是配置在org.springframework.boot:spring-boot-autoconfigure项目下

在这里插入图片描述org.springframework.boot:spring-boot-autoconfigure下的org.springframework.boot.autoconfigure.AutoConfiguration.imports配置文件
在这里插入图片描述
ImportCandidates.load方法结束,然后把刚才加载的类和上面通过spring.factories加载的EnableAutoConfiguration实现类,合并成集合后返回。getCandidateConfigurations方法结束
在这里插入图片描述
继续回到AutoConfigurationImportSelector第130行,过滤加上Condition相关的注解类,这里的Condition默认有三个(OnBeanCondition、OnClassCondition、OnWebApplicationCondition),依然是配置在spring.factories里面
在这里插入图片描述
在这里插入图片描述
getConfigurationClassFilter().filter(configurations);
getConfigurationClassFilter()返回ConfigurationClassFilter对象,他是AutoConfigurationImportSelector的内部类
进入filter方法,依次执行三个默认Condition类的match方法,match是三个Condition的抽象父类FilteringSpringBootCondition的方法
在这里插入图片描述
通过模板模式,调用Condition的实现类getOutcomes方法
在这里插入图片描述
我这里就以OnBeanCondition举例,因为我的自定义配置类有这个注解,且@ConditionalOnBean(Test.class) 这个Test并不会被加载成bean。
在这里插入图片描述
但是这里依然没有把我自定义的类过滤掉???这个地方后面再回头思考,留一个疑问
在这里插入图片描述
结束*grouping.getImports()*方法,返回Iterable在这里插入图片描述
在这里插入图片描述

遍历所有Entry(获取到的spring.factories加载的EnableAutoConfiguration实现类自动装配类、org.springframework.boot.autoconfigure.AutoConfiguration.imports定义的类),统称为 配置文件扫描自动配置类
到812行,再次执行processImports方法,这里第三个参数Collection importCandidates。数据来自Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter))。
继续将每一个配置文件扫描自动配置类通过processImports来判断是否实现ImportSelector和ImportBeanDefinitionRegistrar类

回忆一下processImports的逻辑,如果实现了ImportSelector切继承DeferredImportSelector类,加入延时Selector;如果没有实现DeferredImportSelector,立即触发selectImports方法
注意区分这里调用processImports和之前递归调用。之前是通过@ComponentScan,扫描包下面的类,依次调用processImports方法。
这里是通过扫描 配置文件扫描自动配置类,来处理processImports逻辑。

在这里插入图片描述
回看process方法,其实方法已经结束,而且parse()方法也已经结束,在finally里把延时Selector集合清空。

总结一下parse()方法,分为两部分,两部分的执行目的就是获取配置类,放在ConfigurationClassParser的configurationClasses中。
第一部分:通过从启动类的@ComponentScan开始,找到符合@Component注解的类,并且在@ComponentScan之前,处理了内部类@Component、@PropertySources自定义配置加载的逻辑。递归判断@Component对象上是否包含了@Import注解,如果包含了判断引用的类是否实现ImportSelector:如果实现ImportSelector且继承自DeferredImportSelector,那么放入延时Selector继承,在后面第二部分进行处理;如果实现ImportSelector但是没有继承DeferredImportSelector,会立即执行引用Selector的selectImports方法。当类没有继承自ImportSelector或者ImportBeanDefinitionRegistrar,会作为普通配置类加入到configurationClasses集合中。这段逻辑在@ComponentScan是递归处理的
第二部分:process()方法处理第一部分获取的延时Selector集合的逻辑,主要是处理核心AutoConfigurationImportSelector,在这里会获取从spring.factories加载的EnableAutoConfiguration实现类自动装配类、org.springframework.boot.autoconfigure.AutoConfiguration.imports定义的类。然后遍历这些类,执行第一部分关于是否实现ImportSelector的逻辑。最终将这些配置放到configurationClasses集合中。

parse()方法,核心字段configurationClasses
在这里插入图片描述
可以看到configurationClasses已经缓存了很多配置类
在这里插入图片描述

相关内容

热门资讯

栈应用——逆波兰算法 个人主页:【😊个人主页】 系列专栏:【❤️数据结构与算法...
python基础数据结构方法和... 文章目录1. int2. str3. list4. dict5. tuple6. set 1. in...
EMQ 南洋万邦云边一体化方... 在工业 4.0 的浪潮之中,全球制造业再度振兴和崛起,并经历着前所未有从流程驱动转向数据驱动的变革。...
linux -- 磁盘存储管理... 情景代入 :在对磁盘进行分区大小规划时,有时往往不能特别确定这个分区要使用的总空间大小...
磁盘I/O %util特别高 一、背景简介 作为一个DBA难免不了会遇到性能问题,那么我们遇到性能问题该如何进行排查...
b01lers CTF web... warmup 按照提示依次 base64 加密后访问,可以访问 ./flag.txt&...
SSM项目 创建一个vue工程:cmd: vue create 项目名npm run serve:...
牧原股份回应赴港上市原因:意在... 新京报贝壳财经讯(记者阎侠)5月30日,牧原股份发布投资者关系活动记录表。今年4月,牧原股份的生猪养...
I. 全球变暖(23分)【df... 具体出处蓝桥杯2018年cpp组【第九届】【省赛】【B组】P8662 [蓝桥杯 2018 省 AB]...
三十四、实战演练之接口自动化平... 一、 环境创建 接口名称:/test_envs/ 请求方式:POST 参...
生成式AI为百度打开想象力 出品 | 何玺 排版 | 叶媛 3月16日,备受期待的百度人工智能系统文心一言正式发布...
javaweb实验室学生考勤签... 管理员信息表,包括自动编号,管理员账号,登录密码等数据字段...
提供一种嵌套表单的校验姿势 文章目录一、表单校验1. 代码演示 一、表单校验 表单校验,前端经常遇到的校验场景&...
go语言入门-一文带你掌握go... 前言 本文go语言入门-掌握go语言函数收录于《go语言学习专栏》专栏,此专栏带你从零...
【Vue3】tinymce富文... 1.简介 TinyMCE是一款易用、且功能强大的所见即所得的富文本编辑器。同类程序有:...
量子计算(10)量子算法2:D...         又到了一周一篇的量子计算啦!全体起立respect! ...
十六、FreeRTOS中如何实... 文章目录1、多任务系统中为什么要引入互斥?2、如何实现互斥访问的3、需要互斥访问内核对...
如何把自有数据接入GPT大模型... ChatGPT引发了AI革命,大家都想探究如何让它发挥更大价值。 以它为代表的大模型并...
美国中重卡销量10强:福莱纳领... 陌生的美国中重卡市场在我们的一般印象中,全球各国的汽车市场互联互通,应该是大同小异的。无论是是美国、...
Android WebView... 1、不使用WebView缓存 使用场景:通过WebView输入用户名和密码进行登录&#...