源码分析Spring Boot (v3.3.0)

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.3.0)

pom

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • jdk: openjdk_21
  • 源码:git@github.com:shenshuxin01/upDownloadFlie.git
java 复制代码
//启动类
@SpringBootApplication
public class UpdownloadfileApplication {

    public static void main(String[] args) {
        SpringApplication.run(UpdownloadfileApplication.class, args);
        // SpringApplication springApplication = new SpringApplication(new Class<?>[]{UpdownloadfileApplication.class});
        // springApplication.run(args);
    }

}

1. 实例化SpringApplication

调用代码

java 复制代码
/**
    创建新 SpringApplication 实例。应用程序上下文将从指定的主要源加载 bean(有关详细信息,请参见 class-level 文档)。可以在调用 run(String...)之前自定义实例。
    参数:
    resourceLoader -- 要使用的资源加载器 primarySources -- 主要的 bean 来源
    另请参见:
    run(Class, String[]), setSources(Set)
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    this.bootstrapRegistryInitializers = new ArrayList<>(
            getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = deduceMainApplicationClass();
}

1.1. 推断web类型是servlet还是reactive还是none

通过包名去匹配 ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet")

1.2. 初始化BootstrapRegistryInitializer对象

回调接口,可用于在使用前对其进行初始化 BootstrapRegistry 。

调用方法:getSpringFactoriesInstances(BootstrapRegistryInitializer.class)

java 复制代码
private <T> List<T> getSpringFactoriesInstances(Class<BootstrapRegistryInitializer> type, ArgumentResolver argumentResolver) {
    return SpringFactoriesLoader.forDefaultResourceLocation(getClassLoader()).load(type, argumentResolver);
}

这个方法分为两部分

  • 扫描META-INF/spring.factories资源
  • 实例化BootstrapRegistryInitializer类

1.2.1. 扫描META-INF/spring.factories资源

调用方法:Map<String, List<String>> loadFactoriesResource(ClassLoader classLoader, "META-INF/spring.factories")

核心方法是: classLoader.getResources("META-INF/spring.factories")获取到java环境中的所有此文件夹下面的文件,例如返回MAP结构

key = "org.springframework.boot.ApplicationContextFactory"
value = 
 0 = "org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContextFactory"
 1 = "org.springframework.boot.web.servlet.context.ServletWebServerApplicationContextFactory"

就是spring.factories文件里面的内容

1.2.2. 实例化BootstrapRegistryInitializer类

转换成全限定类名: org.springframework.boot.BootstrapRegistryInitializer

去匹配上面的MAP获取实例化列表类名

1.2.3. 如果项目中引入了spring-cloud-starter-config,就会加载BootstrapRegistryInitializer对象

(可用于加载远程配置中心 springboot-config、nacos)

xml 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

这个jar包的META-INF/spring.factories文件中包含

sh 复制代码
# Spring Boot BootstrapRegistryInitializers
org.springframework.boot.BootstrapRegistryInitializer=\
org.springframework.cloud.config.client.ConfigClientRetryBootstrapper

1.2.4. BootstrapRegistryInitializer实现类列表

bootstrapRegistryInitializers = {ArrayList@3639} size = 0

1.3. 初始化ApplicationContextInitializer对象

用于在刷新之前初始化 Spring ConfigurableApplicationContext 的回调接口。

通常用于需要对应用程序上下文进行一些编程初始化的 Web 应用程序。

调用方法:getSpringFactoriesInstances(ApplicationContextInitializer.class)

java 复制代码
private <T> List<T> getSpringFactoriesInstances(Class<ApplicationContextInitializer> type, ArgumentResolver argumentResolver) {
    return SpringFactoriesLoader.forDefaultResourceLocation(getClassLoader()).load(type, argumentResolver);
}

原理同上

1.3.1. ApplicationContextInitializer实现类列表

initializers = {ArrayList@3658}  size = 7
 0 = {DelegatingApplicationContextInitializer@3552} 
 1 = {SharedMetadataReaderFactoryContextInitializer@3589} 
 2 = {ContextIdApplicationContextInitializer@3509} 
 3 = {ConfigurationWarningsApplicationContextInitializer@3648} 
 4 = {RSocketPortInfoApplicationContextInitializer@3573} 
 5 = {ServerPortInfoApplicationContextInitializer@3581} 
 6 = {ConditionEvaluationReportLoggingListener@3606} 

1.4. 初始化ApplicationListener对象

由应用程序事件侦听器实现的接口。

基于 Observer 设计模式的标准 EventListener 接口。

可以 ApplicationListener 泛型地声明它感兴趣的事件类型。当注册到 Spring ApplicationContext时,事件将被相应地过滤,仅针对匹配的事件对象调用侦听器。

调用方法:getSpringFactoriesInstances(ApplicationListener.class)

java 复制代码
private <T> List<T> getSpringFactoriesInstances(Class<ApplicationListener> type, ArgumentResolver argumentResolver) {
    return SpringFactoriesLoader.forDefaultResourceLocation(getClassLoader()).load(type, argumentResolver);
}

原理同上

1.4.1. ApplicationListener实现类列表

listeners = {ArrayList@3699}  size = 8
 0 = {EnvironmentPostProcessorApplicationListener@3706} 
 1 = {AnsiOutputApplicationListener@3707} 
 2 = {LoggingApplicationListener@3708} 
 3 = {BackgroundPreinitializer@3709} 
 4 = {DelegatingApplicationListener@3710} 
 5 = {ParentContextCloserApplicationListener@3711} 
 6 = {ClearCachesApplicationListener@3712} 
 7 = {FileEncodingApplicationListener@3713} 

1.5. 推断启动类

this.mainApplicationClass = deduceMainApplicationClass();

获取当前堆栈帧信息遍历
if getMethodName() == "main": return Class<?>;

2. 运行run()方法

调用代码

java 复制代码
/**
    运行 Spring 应用程序,创建并刷新新的 ApplicationContext.
    参数:
    args -- 应用程序参数(通常从 Java 主方法传递)
    返回:
    一个正在运行的 ApplicationContext
 */
public ConfigurableApplicationContext run(String... args) {
    Startup startup = Startup.create();
    if (this.registerShutdownHook) {
        SpringApplication.shutdownHook.enableShutdownHookAddition();
    }
    DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    ConfigurableApplicationContext context = null;
    configureHeadlessProperty();
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting(bootstrapContext, this.mainApplicationClass);
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
        Banner printedBanner = printBanner(environment);
        context = createApplicationContext();
        context.setApplicationStartup(this.applicationStartup);//赋值
        prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
        refreshContext(context);
        afterRefresh(context, applicationArguments);//空实现
        startup.started();
        if (this.logStartupInfo) {
            //输出启动日志 Started UpdownloadfileApplication in 407.403 seconds (process running for 411.983)
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), startup);
        }
        //EventPublishingRunListener发布 ApplicationStartedEvent事件给监听器
        listeners.started(context, startup.timeTakenToStarted());
        //获取Runner实例bean,并调用接口方法,例如CommandLineRunner接口,实现初始化代码,自定义业务逻辑
        callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
        throw handleRunFailure(context, ex, listeners);
    }
    try {
        if (context.isRunning()) {
            listeners.ready(context, startup.ready());
        }
    }
    catch (Throwable ex) {
        throw handleRunFailure(context, ex, null);
    }
    return context;
}

2.1. 启动计时器

Startup startup = Startup.create();
private final Long startTime = System.currentTimeMillis();

2.2. 创建启动上下文

DefaultBootstrapContext bootstrapContext = createBootstrapContext();

实例化BootstrapContext并调用实现类的initializer方法,如果项目集成了nacos配置中心,这一步就会调用。

java 复制代码
private DefaultBootstrapContext createBootstrapContext() {
    DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
    this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
    return bootstrapContext;
}

DefaultBootstrapContext主要实现的接口方法:

java 复制代码
/**
向注册表注册特定类型。如果指定的类型已注册且尚未作为 获取 singleton,则它将被替换。
参数:
type -- 实例类型 instanceSupplier -- 实例供应商
 */
<T> void register(Class<T> type, InstanceSupplier<T> instanceSupplier);

/**
如果类型已注册,则从上下文中返回实例。如果之前未访问过该实例,则会创建该实例。
参数:
type -- 实例类型
返回:
由 Context 管理的实例
抛出:
IllegalStateException -- 如果类型尚未注册
    */
<T> T get(Class<T> type) throws IllegalStateException;

2.3. 设置无图形环境true

java 复制代码
private void configureHeadlessProperty() {
    System.setPropertyIfAbsent("java.awt.headless",true);
}

在无头模式下,Java 应用程序无法使用任何依赖于图形环境的功能,如 AWT(Abstract Window Toolkit)和 Swing。这包括:•创建窗口和对话框•显示图像•使用剪贴板•播放音频

2.4. 创建运行监听getRunListeners实例

SpringApplicationRunListeners listeners = getRunListeners(args);

获取配置的类并实例化

java 复制代码
private SpringApplicationRunListeners getRunListeners(String[] args) {
    List<SpringApplicationRunListener> listeners = getSpringFactoriesInstances(SpringApplicationRunListener.class);
    SpringApplicationHook hook = applicationHook.get();
    SpringApplicationRunListener hookListener = hook.getRunListener(this);
    if (hookListener != null) { //第一次启动,这里是null。
        listeners.add(hookListener);
    }
    return new SpringApplicationRunListeners(listeners);
}

getSpringFactoriesInstances方法创建的对象:

listeners = {ArrayList@3099}  size = 1
 0 = {EventPublishingRunListener@3098} 

EventPublishingRunListener实现的接口方法:

java 复制代码
public interface SpringApplicationRunListener{
    /**
     * 在 run 方法首次启动时立即调用。可用于非常早期的初始化。
     */
    void starting(ConfigurableBootstrapContext bootstrapContext);

    /**
     * 在准备好环境后但在创建环境之前 ApplicationContext 调用。
     */
    void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment);

    //省略...
}

2.5. 启动运行监听实例EventPublishingRunListener

listeners.starting(bootstrapContext, this.mainApplicationClass);

java 复制代码
void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
    this.listeners.forEach((listener) -> listener.starting(bootstrapContext));
}

这里的listeners集合只有一个对象EventPublishingRunListener,注意这个监听是runListeners,而不是最开始的applicationListeners,

2.5.1. 再来看一下这个对象的starting方法

java 复制代码
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
    multicastInitialEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
}

private void multicastInitialEvent(ApplicationEvent event) {
    refreshApplicationListeners();//保证监听器只执行一次,把已经执行过的监听器在集合中删除
    this.initialMulticaster.multicastEvent(event);//执行监听器方法
}

@Override
public void multicastEvent(ApplicationEvent event) {
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {//从applicationListeners中获取类型是ApplicationStartingEvent的监听器
        listener.onApplicationEvent(event);
    }
}

2.5.2. 上一步获取到的ApplicationEvent监听器

getApplicationListeners(event, type) = {ArrayList@3309}  size = 3
 0 = {LoggingApplicationListener@3174} 
 1 = {BackgroundPreinitializer@3175} 
 2 = {DelegatingApplicationListener@3176} 

ApplicationListener函数式接口的方法:

java 复制代码
void onApplicationEvent(E event);

2.6. 加载环境配置

ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);

方法内容

java 复制代码
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
        DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
    // Create and configure the environment
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    ConfigurationPropertySources.attach(environment);
    listeners.environmentPrepared(bootstrapContext, environment);
    DefaultPropertiesPropertySource.moveToEnd(environment);//把default配置放到最后
    Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
            "Environment prefix cannot be set via properties.");
    bindToSpringApplication(environment);
    if (!this.isCustomEnvironment) {
        EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());
        environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
    }
    ConfigurationPropertySources.attach(environment);//把configurationProperties配置放到集合中第一个
    return environment;
}

2.6.1. 创建环境实例

java 复制代码
ConfigurableEnvironment environment = getOrCreateEnvironment();
//getOrCreateEnvironment这个方法中主要代码是
SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class);//就是从spring.factories文件中加载实例
// 默认获取到2个实例
//  0 = {ReactiveWebServerApplicationContextFactory@2803} 
//  1 = {ServletWebServerApplicationContextFactory@2804} 
return new ApplicationServletEnvironment();//最终是创建了这个servlet类型环境上下文

ApplicationServletEnvironment这个类实现了PropertyResolver接口

java 复制代码
public interface PropertyResolver {
    String getProperty(String key);

2.6.2. 配置环境上下文

configureEnvironment(environment, applicationArguments.getSourceArgs());

java 复制代码
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
    if (this.addConversionService) {
        //添加转换服务,用于解析配置文件做类型转换
        environment.setConversionService(new ApplicationConversionService());
    }
    //解析命令行参数
    configurePropertySources(environment, args);
    //配置默认激活文件 spring.profiles.active
    configureProfiles(environment, args);
}

//添加转换服务主要代码
converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry));
converterRegistry.addConverter(new StringToTimeZoneConverter());
converterRegistry.addConverter(new ZoneIdToTimeZoneConverter());
converterRegistry.addConverter(new ZonedDateTimeToCalendarConverter());
converterRegistry.addConverter(new ObjectToObjectConverter());
converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry));
converterRegistry.addConverter(new FallbackObjectToStringConverter());
converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService) converterRegistry));
registry.addFormatter(new CharArrayFormatter());
registry.addFormatter(new InetAddressFormatter());
registry.addFormatter(new IsoOffsetFormatter());

2.6.3. 继续添加系统环境

ConfigurationPropertySources.attach(environment);

attach方法主要逻辑:

java 复制代码
public static void attach(Environment environment) {
    MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
    attached = new ConfigurationPropertySourcesPropertySource("configurationProperties",
            new SpringConfigurationPropertySources(sources));
    sources.addFirst(attached);
}

2.6.4. 执行监听器配置环境

listeners.environmentPrepared(bootstrapContext, environment);

java 复制代码
void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
    //注意这个监听是runListeners,而不是最开始的applicationListeners
    //listeners集合只有一个对象`EventPublishingRunListener`
    this.listeners.forEach((listener) -> 
        listener.environmentPrepared(bootstrapContext, environment)
    );
}
//代码继续往下执行,调用EventPublishingRunListener.environmentPrepared()方法
@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
    multicastInitialEvent(
            //这里创建了一个ApplicationEnvironmentPreparedEvent事件类
            new ApplicationEnvironmentPreparedEvent(bootstrapContext, this.application, this.args, environment));
}

private void multicastInitialEvent(ApplicationEvent event) {
    refreshApplicationListeners();//保证监听器只执行一次,把已经执行过的监听器在集合中删除
    this.initialMulticaster.multicastEvent(event);//执行监听器方法
}
//代码继续执行
@Override
public void multicastEvent(ApplicationEvent event) {//入参是ApplicationEnvironmentPreparedEvent事件类
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {//从applicationListeners中获取类型是ApplicationEnvironmentPreparedEvent的监听器
        listener.onApplicationEvent(event);
    }
}
2.6.4.1. EventPublishingRunListener待执行的事件类

从applicationListeners中获取类型是ApplicationEnvironmentPreparedEvent的监听器:

getApplicationListeners(event, type) = {ArrayList@4265}  size = 6
 0 = {EnvironmentPostProcessorApplicationListener@3936} 
 1 = {AnsiOutputApplicationListener@4267} 
 2 = {LoggingApplicationListener@4268} 
 3 = {BackgroundPreinitializer@4269} 
 4 = {DelegatingApplicationListener@4270} 
 5 = {FileEncodingApplicationListener@3894} 

上面这几步和【2.6.1.】标题逻辑一样

2.6.4.1.1. EnvironmentPostProcessorApplicationListener监听器执行onApplicationEvent事件
java 复制代码
//下面是给applicationEnvironment环境上下文新增配置
private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
    ConfigurableEnvironment environment = event.getEnvironment();
    SpringApplication application = event.getSpringApplication();
    for (EnvironmentPostProcessor postProcessor : getEnvironmentPostProcessors(application.getResourceLoader(), event.getBootstrapContext())) {
        postProcessor.postProcessEnvironment(environment, application);
    }
}
//调用了load方法
@Override
public List<EnvironmentPostProcessor> getEnvironmentPostProcessors(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext) {
    ArgumentResolver argumentResolver = ArgumentResolver.of(DeferredLogFactory.class, logFactory);
    argumentResolver = argumentResolver.and(ConfigurableBootstrapContext.class, bootstrapContext);
    argumentResolver = argumentResolver.and(BootstrapContext.class, bootstrapContext);
    argumentResolver = argumentResolver.and(BootstrapRegistry.class, bootstrapContext);
    //这一步就是把spring.factories配置的EnvironmentPostProcessor类实例化,具体参考【1.2.】标题
    return this.loader.load(EnvironmentPostProcessor.class, argumentResolver);
}

this.loader.load获取到的实例

getEnvironmentPostProcessors() = {ArrayList@4241}  size = 7
 0 = {RandomValuePropertySourceEnvironmentPostProcessor@4243} 
 1 = {SystemEnvironmentPropertySourceEnvironmentPostProcessor@4244} 
 2 = {CloudFoundryVcapEnvironmentPostProcessor@4245} 
 3 = {SpringApplicationJsonEnvironmentPostProcessor@4246} 
 4 = {ConfigDataEnvironmentPostProcessor@4247} 
 5 = {ReactorEnvironmentPostProcessor@4248} 
 6 = {IntegrationPropertiesEnvironmentPostProcessor@4249} 

代码遍历执行上面的实例,运行postProcessEnvironment()方法。下面重点看一下ConfigDataEnvironmentPostProcessor

2.6.4.1.1.1. ConfigDataEnvironmentPostProcessor加载项目配置数据

ConfigDataEnvironmentPostProcessor类中的方法

java 复制代码
void postProcessEnvironment(ConfigurableEnvironment environment, ResourceLoader resourceLoader, Collection<String> additionalProfiles) {
    this.logger.trace("Post-processing environment to add config data");
    resourceLoader = (resourceLoader != null) ? resourceLoader : new DefaultResourceLoader();
    //重点看下面这个方法
    getConfigDataEnvironment(environment, resourceLoader, additionalProfiles)//创建configDataEnvironment对象
        .processAndApply();//扫描配置并写入environment
}
//创建configDataEnvironment对象
class ConfigDataEnvironment{
    //初始化静态块
    static {
        List<ConfigDataLocation> locations = new ArrayList<>();
        locations.add(ConfigDataLocation.of("optional:classpath:/;optional:classpath:/config/"));
        locations.add(ConfigDataLocation.of("optional:file:./;optional:file:./config/;optional:file:./config/*/"));
        DEFAULT_SEARCH_LOCATIONS = locations.toArray(new ConfigDataLocation[0]);
    }

    //ConfigDataEnvironment中的方法
    void processAndApply() {
        ConfigDataImporter importer = new ConfigDataImporter(this.logFactory, this.notFoundAction, this.resolvers,
                this.loaders);
        registerBootstrapBinder(this.contributors, null, DENY_INACTIVE_BINDING);
        ConfigDataEnvironmentContributors contributors = processInitial(this.contributors, importer);
        ConfigDataActivationContext activationContext = createActivationContext(
                contributors.getBinder(null, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE));
        contributors = processWithoutProfiles(contributors, importer, activationContext);
        activationContext = withProfiles(contributors, activationContext);
        contributors = processWithProfiles(contributors, importer, activationContext);
        //这一步会读取项目中的src/main/resources/application.properties等文件
        applyToEnvironment(contributors, activationContext, importer.getLoadedLocations(),
                importer.getOptionalLocations());
    }
}

processAndApply()方法会向applicationEnvironment环境上下文新增配置

js 复制代码
name = "Config resource 'class path resource [application.properties]' via location 'optional:classpath:/'"
source = {Collections$UnmodifiableMap@5118}  size = 5
 "spring.application.name" -> {OriginTrackedValue$OriginTrackedCharSequence@5127} "updownloadfile"
 "spring.servlet.multipart.max-file-size" -> {OriginTrackedValue$OriginTrackedCharSequence@5129} "500MB"
 "spring.servlet.multipart.max-request-size" -> {OriginTrackedValue$OriginTrackedCharSequence@5131} "500MB"
 "ssx.up.path" -> {OriginTrackedValue$OriginTrackedCharSequence@5133} "C:/Users/shenshuxin/Downloads/up/"
 "spring.threads.virtual.enabled" -> {OriginTrackedValue$OriginTrackedCharSequence@5135} "true"

2.7. 打印banner图

Banner printedBanner = printBanner(environment);

没什么好说的

sh 复制代码
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.3.0)

2.8. 创建applicationContext上下文

context = createApplicationContext();

java 复制代码
//其中的主要方法:
class DefaultApplicationContextFactory implements ApplicationContextFactory {
    private ConfigurableApplicationContext getFromSpringFactories(WebApplicationType webApplicationType) {
        for (ApplicationContextFactory candidate : SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class)) {
            //实际上创建的是 AnnotationConfigServletWebServerApplicationContext extends ConfigurableApplicationContext   
            ConfigurableApplicationContext result = candidate.create(webApplicationType);
            if (result != null) {
                return result;
            }
        }
    }
}

2.8.1. 创建beanFactory

创建applicationContext的构造方法中,默认创建了beanFactory

java 复制代码
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

public GenericApplicationContext() {
    this.beanFactory = new DefaultListableBeanFactory();
}
2.8.1.1. beanFactory实现的主要方法
java 复制代码
//注册bean到singletonObjects
void registerSingleton(String beanName, Object singletonObject);

//获取bean从singletonObjects
Object getSingleton(String beanName);
2.8.1.2. DefaultListableBeanFactory构造方法
java 复制代码
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"));

这个类ConfigurationClassPostProcessor很重要,在扫描项目中的bean的时候用到了

2.9. 配置上下文applicationContext

prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);

java 复制代码
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
        ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
        ApplicationArguments applicationArguments, Banner printedBanner) {
    context.setEnvironment(environment);//赋值环境变量
    postProcessApplicationContext(context);//转换服务赋值到beanFactory
    addAotGeneratedInitializerIfNecessary(this.initializers);//AOT是一种编译技术,可以在编译时生成优化的字节码,从而在运行时提高性能
    applyInitializers(context);
    listeners.contextPrepared(context);
    bootstrapContext.close(context);
    if (this.logStartupInfo) {
        logStartupInfo(context.getParent() == null);
        logStartupProfileInfo(context);
    }
    // Add boot specific singleton beans
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    if (printedBanner != null) {
        beanFactory.registerSingleton("springBootBanner", printedBanner);
    }
    if (beanFactory instanceof AbstractAutowireCapableBeanFactory autowireCapableBeanFactory) {
        autowireCapableBeanFactory.setAllowCircularReferences(this.allowCircularReferences);
        if (beanFactory instanceof DefaultListableBeanFactory listableBeanFactory) {
            listableBeanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
    }
    if (this.lazyInitialization) {
        context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
    }
    if (this.keepAlive) {
        context.addApplicationListener(new KeepAlive());
    }
    context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
    if (!AotDetector.useGeneratedArtifacts()) {
        // Load the sources
        Set<Object> sources = getAllSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        load(context, sources.toArray(new Object[0]));
    }
    listeners.contextLoaded(context);
}

2.9.1. 运行applicationInitializers

applyInitializers(context);

java 复制代码
//获取applicationContextInitializer集合并调用初始化方法
//这里的集合是在【1.3.】标题中添加的
protected void applyInitializers(ConfigurableApplicationContext context) {
    for (ApplicationContextInitializer initializer : getInitializers()) {
        Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
                ApplicationContextInitializer.class);
        Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
        initializer.initialize(context);//初始化
    }
}
// 0 = {DelegatingApplicationContextInitializer@5971} 
// 1 = {SharedMetadataReaderFactoryContextInitializer@5972} 
// 2 = {ContextIdApplicationContextInitializer@5973} 
// 3 = {ConfigurationWarningsApplicationContextInitializer@5974} 
// 4 = {RSocketPortInfoApplicationContextInitializer@5975} 
// 5 = {ServerPortInfoApplicationContextInitializer@5976} 
// 6 = {ConditionEvaluationReportLoggingListener@5977} 

BeanDefinitionRegistryPostProcessor接口定义

java 复制代码
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    //在标准初始化后修改应用程序上下文的内部 Bean 定义注册表
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
   
    //在标准初始化后修改应用程序上下文的内部 Bean 工厂
    @Override
    default void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}
2.9.1.1. SharedMetadataReaderFactoryContextInitializer初始化方法

新增CachingMetadataReaderFactoryPostProcessor,实现了BeanDefinitionRegistryPostProcessor接口

java 复制代码
BeanFactoryPostProcessor postProcessor = new CachingMetadataReaderFactoryPostProcessor(applicationContext);
applicationContext.addBeanFactoryPostProcessor(postProcessor);
2.9.1.2. ConfigurationWarningsApplicationContextInitializer初始化方法

新增ConfigurationWarningsPostProcessor,实现了BeanDefinitionRegistryPostProcessor接口

java 复制代码
context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));

2.9.2. 运行applicationContextInitializedEvent监听事件

listeners.contextPrepared(context);

java 复制代码
void contextPrepared(ConfigurableApplicationContext context) {
    //注意这里的this.listeners是apringApplicationRunListeners,只有一个实例 EventPublishingRunListener
    this.listeners.forEach((listener) -> listener.contextPrepared(context));
}

@Override
public void contextPrepared(ConfigurableApplicationContext context) {
    //创建上下文初始化完成事件 ApplicationContextInitializedEvent
    multicastInitialEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
}

private void multicastInitialEvent(ApplicationEvent event) {
    refreshApplicationListeners();//保证监听器只执行一次,把已经执行过的监听器在集合中删除
    this.initialMulticaster.multicastEvent(event);//执行监听器方法
}

//代码继续执行
@Override
public void multicastEvent(ApplicationEvent event) {//入参是ApplicationContextInitializedEvent事件类
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {//从applicationListeners中获取类型是ApplicationContextInitializedEvent的监听器
        listener.onApplicationEvent(event);
    }
}
2.9.2.1. Event监听获取到的ApplicationContextInitializedEvent实例
getApplicationListeners(event, type) = {ArrayList@6345}  size = 2
 0 = {BackgroundPreinitializer@6218} 
 1 = {DelegatingApplicationListener@6225} 

经过断点查看,这两个实例的onApplicationEvent()方法没有重要的处理逻辑

2.9.3. 运行bootstrapRegistryLinstner结束事件

bootstrapContext.close(context);

java 复制代码
public void close(ConfigurableApplicationContext applicationContext) {
    this.events.multicastEvent(new BootstrapContextClosedEvent(this, applicationContext));
}

@Override
public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
    Executor executor = getTaskExecutor();
    //获取BootstrapContextClosedEvent类型的监听器,这里没有获取到
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        invokeListener(listener, event);
    }
}

2.9.4. 配置日志

java 复制代码
if (this.logStartupInfo) {
    logStartupInfo(context.getParent() == null);
    logStartupProfileInfo(context);
}
//创建StartupInfoLogger
new StartupInfoLogger(this.mainApplicationClass).logStarting(getApplicationLog());
//2024-11-07T17:02:39.195+08:00  INFO 25720 --- [updownloadfile] [           main] c.s.u.UpdownloadfileApplication          : Starting UpdownloadfileApplication using
//2024-11-07T17:05:03.604+08:00  INFO 25720 --- [updownloadfile] [           main] c.s.u.UpdownloadfileApplication          : No active profile set, falling back to 1 default profile: "default"

2.9.5. 添加bean到beanFactory

java 复制代码
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
beanFactory.registerSingleton("springBootBanner", printedBanner);
beanFactory.registerBeanDefinition("updownloadfileApplication", AnnotatedGenericBeanDefinition);
2.9.5.1. 添加PropertySourceOrderingBeanFactoryPostProcessor
java 复制代码
context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));

2.9.6. 运行ApplicationPreparedEvent监听事件

listeners.contextLoaded(context);

java 复制代码
void contextLoaded(ConfigurableApplicationContext context) {
    //注意这里的this.listeners是apringApplicationRunListeners,只有一个实例 EventPublishingRunListener
    this.listeners.forEach((listener) -> listener.contextLoaded(context));
}

@Override
public void contextLoaded(ConfigurableApplicationContext context) {
    for (ApplicationListener<?> listener : this.application.getListeners()) {
        //获取所有的applicationListeners,调用setApplicationContext方法
        if (listener instanceof ApplicationContextAware contextAware) {
            contextAware.setApplicationContext(context);
        }
        context.addApplicationListener(listener);
    }
    multicastInitialEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}

private void multicastInitialEvent(ApplicationEvent event) {
    refreshApplicationListeners();//保证监听器只执行一次,把已经执行过的监听器在集合中删除
    this.initialMulticaster.multicastEvent(event);//执行监听器方法
}

//代码继续执行
@Override
public void multicastEvent(ApplicationEvent event) {//入参是ApplicationPreparedEvent事件类
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {//从applicationListeners中获取类型是ApplicationPreparedEvent的监听器
        listener.onApplicationEvent(event);
    }
}
2.9.6.1. 获取到的applicationPreparedEvent事件
getApplicationListeners(event, type) = {ArrayList@5139}  size = 4
 0 = {EnvironmentPostProcessorApplicationListener@5027}  //将所有延迟日志切换到它们提供的目标
 1 = {LoggingApplicationListener@5136} 
 2 = {BackgroundPreinitializer@5137} 
 3 = {DelegatingApplicationListener@5138} 
2.9.6.2. ApplicationContextAware接口作用

准备完成applicationContext之后,最后一步是执行event监听context完成事件

java 复制代码
if (listener instanceof ApplicationContextAware contextAware) {
    contextAware.setApplicationContext(context);
}

这一步里面会调用setApplicationContext()方法

java 复制代码
/**
 * 接口,由任何希望被通知 ApplicationContext 其运行的对象实现。
 * 例如,当对象需要访问一组协作 bean 时,实现此接口是有意义的。请注意,通过 bean 引用进行配置比仅仅为了 bean 查找目的实现此接口更可取。
 */
public interface ApplicationContextAware extends Aware {
    /**
     * 设置运行此对象的 ApplicationContext。通常,此调用将用于初始化对象。
     */
    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}

2.9.7. 完成contextPrepare方法后,beanFactory中的bean信息

js 复制代码
beanDefinitionNames = {ArrayList@4019}  size = 6
 0 = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"
 1 = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"
 2 = "org.springframework.context.annotation.internalCommonAnnotationProcessor"
 3 = "org.springframework.context.event.internalEventListenerProcessor"
 4 = "org.springframework.context.event.internalEventListenerFactory"
 5 = "updownloadfileApplication"

registeredSingletons = {LinkedHashSet@4041}  size = 7
 0 = "org.springframework.boot.context.ContextIdApplicationContextInitializer$ContextId"
 1 = "autoConfigurationReport"
 2 = "springApplicationArguments"
 3 = "springBootBanner"
 4 = "springBootLoggingSystem"
 5 = "springBootLoggerGroups"
 6 = "springBootLoggingLifecycle"

2.10. 刷新上下文applicationContext

refreshContext(context);

具体方法:

java 复制代码
@Override
public void refresh() throws BeansException, IllegalStateException {
    this.startupShutdownLock.lock();
    try {
        this.startupShutdownThread = Thread.currentThread();

        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

        // Prepare this context for refreshing.
        //初始化environment环境配置信息
        //校验environment配置信息是否正确
        prepareRefresh();

        // Tell the subclass to refresh the internal bean factory.
        //刷新序列化id(暂时没有用到)
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // Prepare the bean factory for use in this context.
        //设置bean忽略某些类(EnvironmentAware、ApplicationContextAware)、添加bean到beanFactory(environment、systemProperties、applicationStartup)
        prepareBeanFactory(beanFactory);

        try {
            // Allows post-processing of the bean factory in context subclasses.
            //使用给定的 BeanFactory 注册特定于 Web 的范围("request"、"session"、"globalSession"),就像 WebApplicationContext 使用的那样。
            postProcessBeanFactory(beanFactory);

            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
            // Invoke factory processors registered as beans in the context.
            //扫描项目中的bean,详情看下面的解释
            invokeBeanFactoryPostProcessors(beanFactory);

            // Register bean processors that intercept bean creation.
            //注册BeanPostProcessor,初始化Bean前后钩子
            registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();

            // Initialize message source for this context.
            //用于解析消息的 Strategy 接口,支持此类消息的参数化和国际化。
            initMessageSource();

            // Initialize event multicaster for this context.
            //事件发布器 负责将事件广播给所有注册的监听器(ApplicationListener)。
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            //创建tomcat服务
            onRefresh();

            // Check for listener beans and register them.
            //注册监听
            registerListeners();

            // Instantiate all remaining (non-lazy-init) singletons.
            //实例化所有的单例、非懒加载的Bean实例
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            //清除缓存、发布ContextRefreshedEvent事件
            finishRefresh();
        }

        catch (RuntimeException | Error ex ) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();

            // Reset 'active' flag.
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
        }

        finally {
            contextRefresh.end();
        }
    }
    finally {
        this.startupShutdownThread = null;
        this.startupShutdownLock.unlock();
    }
}

2.10.1. 调用beanFactoryPostProcessors方法

invokeBeanFactoryPostProcessors(beanFactory);

java 复制代码
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    //静态方法
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}
2.10.1.1. getBeanFactoryPostProcessors集合
js 复制代码
this.beanFactoryPostProcessors = {ArrayList@4190}  size = 3
 0 = {SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor@4816} 
 1 = {ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor@4817} 
 2 = {SpringApplication$PropertySourceOrderingBeanFactoryPostProcessor@4818}

上面这三个processor来源位置:

  • 标题【2.9.1.1. SharedMetadataReaderFactoryContextInitializer初始化方法】
  • 标题【2.9.1.2. ConfigurationWarningsApplicationContextInitializer初始化方法】
  • 标题【2.9.5.1. 添加PropertySourceOrderingBeanFactoryPostProcessor】
2.10.1.2. invokeBeanFactoryPostProcessors方法

源码太长,这里没有粘贴上
https://github.com/spring-projects/spring-framework/blob/main/spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java

2.10.1.2.1. 先执行BeanDefinitionRegistryPostProcessor接口

实现此接口的类有两个

  • SharedMetadataReaderFactoryContextInitializer,作用是注册了beanDef:SharedMetadataReaderFactoryBean
  • ConfigurationWarningsApplicationContextInitializer,作用是检查启动类的包名cn.shenshuxin.updownloadfile是否和org.springframework相等
2.10.1.2.2. 执行beanFactory中实现BeanDefinitionRegistryPostProcessor接口的bean
  • First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
    先获取bean是BeanDefinitionRegistryPostProcessor并且实现了PriorityOrdered接口,只有一个符合的bean:ConfigurationClassPostProcessor,然后调用BeanDefinitionRegistryPostProcessor接口的方法。下面重点分析这个逻辑
  • Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. 然后再获取实现了Ordered接口的bean然后调用接口方法。这个地方没有重要的逻辑
  • Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. 最后获取剩余的接口然后调用接口方法。这个地方没有重要的逻辑
2.10.1.2.2.1. ConfigurationClassPostProcessor扫描项目中的所有bean
js 复制代码
此时beanFactory中的beanDef列表
 0 = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"
 1 = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"
 2 = "org.springframework.context.annotation.internalCommonAnnotationProcessor"
 3 = "org.springframework.context.event.internalEventListenerProcessor"
 4 = "org.springframework.context.event.internalEventListenerFactory"
 5 = "updownloadfileApplication"
 6 = "org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory"
  1. 获取到beanFactory中类型是AnnotatedGenericBeanDefinition的bean,只有一个updownloadfileApplication也就是启动类
  2. 实例化ConfigurationClassParser,并调用parse("updownloadfileApplication")方法
  3. parse方法中最重要的逻辑,循环扫描项目中的bean并加载到beanFactory
java 复制代码
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
    // Recursively process the configuration class and its superclass hierarchy.
    SourceClass sourceClass = null;
    try {
        sourceClass = asSourceClass(configClass, filter);
        //sourceClass = {ConfigurationClassParser$SourceClass@5008} "cn.shenshuxin.updownloadfile.UpdownloadfileApplication"
        do {
            //主要解析方法doProcessConfigurationClass
            sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
        }
        while (sourceClass != null);
    }
    //临时存储项目中创建的bean类
    this.configurationClasses.put(configClass, configClass);//Map<ConfigurationClass, ConfigurationClass>
}

/**
通过从源类中读取注释、成员和方法,应用处理并构建一个完整的 ConfigurationClass 。当发现相关源时,可以多次调用此方法。
参数:
configClass -- 正在构建的 Configuration 类 sourceClass -- 源类
返回:
超类,或者 null 如果未找到或以前处理过
 */
protected final SourceClass doProcessConfigurationClass(
        ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
        throws IOException {
    //configClass是启动类UpdownloadfileApplication,有一个@SpringBootApplication注解(继承了@Component)
    if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
        // Recursively process any member (nested) classes first 
        //如果启动类存在内部类,就获取内部类,递归调用当前这个doProcessConfigurationClass方法
        processMemberClasses(configClass, sourceClass, filter);
    }

    // Process any @PropertySource annotations
    //获取自定义的配置文件,解析到Environment环境上下文中 例如@PropertySource("classpath:/com/myco/app.properties")
    for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
            sourceClass.getMetadata(), org.springframework.context.annotation.PropertySource.class,
            PropertySources.class, true)) {
        if (this.propertySourceRegistry != null) {
            this.propertySourceRegistry.processPropertySource(propertySource);
        }
        else {
            logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                    "]. Reason: Environment must implement ConfigurableEnvironment");
        }
    }

    // Search for locally declared @ComponentScan annotations first.
    //获取启动类的@ComponentScan注解,并且是直接存在于启动类而非继承(忽略@SpringbootApplication继承的注解),这里没获取到
    Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
            sourceClass.getMetadata(), ComponentScan.class, ComponentScans.class,
            MergedAnnotation::isDirectlyPresent);

    // Fall back to searching for @ComponentScan meta-annotations (which indirectly
    // includes locally declared composed annotations).
    //获取启动类的@ComponentScan注解,或者继承的注解。这里获取到了basePackages -> {String[0]@6193} []空数组
    if (componentScans.isEmpty()) {
        componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(),
                ComponentScan.class, ComponentScans.class, MergedAnnotation::isMetaPresent);
    }

    //扫描启动类包下resourcePattern -> **/*.class的类
    if (!componentScans.isEmpty() &&
            !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
        for (AnnotationAttributes componentScan : componentScans) {
            // The config class is annotated with @ComponentScan -> perform the scan immediately
            //如果basePackages是空数组,赋值启动类的包名cn.shenshuxin.updownloadfile;
            //这个parse方法里面是扫描classpath*:cn/shenshuxin/updownloadfile/**/*.class类,通过File类实现的。过滤出包含@Componet注解的类
            Set<BeanDefinitionHolder> scannedBeanDefinitions =
                    this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());//这里只获取到一个符合条件的[cn.shenshuxin.updownloadfile.contr.Controller]
            // Check the set of scanned definitions for any further config classes and parse recursively if needed
            for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                if (bdCand == null) {
                    bdCand = holder.getBeanDefinition();
                }
                if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                    //这个parse方法 className = "cn.shenshuxin.updownloadfile.contr.Controller",beanName = "controller"
                    //里面就是递归调用当前doProcessConfigurationClass方法
                    parse(bdCand.getBeanClassName(), holder.getBeanName());
                    //上面的方法执行完毕后,this.configurationClasses里面新增一个类 [cn/shenshuxin/updownloadfile/contr/Controller.class]
                }
            }
        }
    }

    // Process any @Import annotations
    //获取source类(启动类)上面的@Import注解的值 (@SpringbootApplication继承的注解)
    //新增了一个importBeanDefinitionRegistrars ={AutoConfigurationPackages$Registrar@5427}
    //新增了一个deferredImportSelectors ={ConfigurationClassParser$DeferredImportSelectorHolder@7331} (AutoConfigurationImportSelector)这里导入了一个最重要自动配置类!详细往后看
    processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

    // Process any @ImportResource annotations
    //指示一个或多个包含要导入的 Bean 定义的资源。与 @Import一样
    //项目这里没有配置 是null
    AnnotationAttributes importResource =
            AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
    if (importResource != null) {
        String[] resources = importResource.getStringArray("locations");
        Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
        for (String resource : resources) {
            String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
            configClass.addImportedResource(resolvedResource, readerClass);
        }
    }

    // Process individual @Bean methods
    //获取source类(启动类)里面的方法, @Bean注解的配置方法。并添加到 Set<BeanMethod> beanMethods集合中
    //项目这里没有配置 是null
    Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    for (MethodMetadata methodMetadata : beanMethods) {
        configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    }

    // Process default methods on interfaces
    //获取source类(启动类)的父类,如果父类中的方法存在@Bean注解,也添加到Set<BeanMethod> beanMethods集合中。这里是递归获取父类
    processInterfaces(configClass, sourceClass);

    // Process superclass, if any
    //获取source类(启动类)的父类,如果父类也是一个自定义的类,就返回父类的sourceClass。继续执行doProcessConfigurationClass这个方法
    if (sourceClass.getMetadata().hasSuperClass()) {
        String superclass = sourceClass.getMetadata().getSuperClassName();
        if (superclass != null && !superclass.startsWith("java") &&
                !this.knownSuperclasses.containsKey(superclass)) {
            this.knownSuperclasses.put(superclass, configClass);
            // Superclass found, return its annotation metadata and recurse
            return sourceClass.getSuperClass();
        }
    }

    // No superclass -> processing is complete
    return null;
}
  1. parse方法中另一个重要的逻辑,循环扫描第三方jar包中的bean并加载到beanFactory
java 复制代码
//下面这个集合只有一个元素,是在上面的processImports方法添加的:ConfigurationClassParser$DeferredImportSelectorHolder@7331} 说明一下,这个写法ConfigurationClassParser类里面的内部类DeferredImportSelectorHolder
this.deferredImportSelectorHandler.process();

public void process() {
    //下面这个列表只有一个元素:{ConfigurationClassParser$DeferredImportSelectorHolder@7331} (AutoConfigurationImportSelector)这里获取了一个最重要自动配置类!
    List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
    this.deferredImportSelectors = null;
    try {
        if (deferredImports != null) {
            DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
            deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
            //把AutoConfigurationImportSelector实例添加到handler对象的groupings集合中
            deferredImports.forEach(handler::register);
            //核心逻辑:导入配置类
            handler.processGroupImports();
        }
    }
    finally {
        this.deferredImportSelectors = new ArrayList<>();
    }
}

//核心逻辑:导入配置类
public void processGroupImports() {
    //this.groupings集合中只有一个元素 AutoConfigurationImportSelector
    for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
        //先看getImports()方法:扫描所有的jar包获取配置类
        grouping.getImports().forEach(autoConfigClass -> {
            //扫描配置类中相关的Bean对象,里面其实调用了processConfigurationClass()方法,参考上面标题【##### 2.10.1.2.2.1. ConfigurationClassPostProcessor扫描项目中的所有bean】第三步【3. parse方法中最重要的逻辑,循环扫描项目中的bean并加载到beanFactory】
            processImports("updownloadfileApplication", autoConfigClass);
        });
    }
}

//扫描所有的jar包获取配置类
protected List<String> getImports(AnnotationMetadata annotationMetadata) {
    //annotationMetadata是{updownloadfileApplication}
    AnnotationAttributes attributes = getAttributes(annotationMetadata);

    //通过classLoader获取类资源:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
    //注意这个是META-INF/spring/%s.imports格式的,并不是META-INF/spring.factories因为这是springboot3版本
    List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
    //我这里扫描到了274个配置AutoConfiguration类,例如:
    //org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
    //org.springframework.boot.autoconfigure.jdbc.JdbcClientAutoConfiguration
    //org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
    //等等

    configurations = removeDuplicates(configurations);//去重
    Set<String> exclusions = getExclusions(annotationMetadata, attributes);//删除指定的类(可以在@SpringbootApplication注解中配置)
    checkExcludedClasses(configurations, exclusions);
    configurations.removeAll(exclusions);

    //过滤器:实现逻辑是获取项目中配置的META-INF/spring.factories文件中的AutoConfigurationImportFilter.class,然后执行过滤filter
    configurations = getConfigurationClassFilter().filter(configurations);
    fireAutoConfigurationImportEvents(configurations, exclusions);
    //经过滤后,剩下77个配置类
    return configurations;
}
  1. 扫描项目中所有的bean包含第三方jar的bean,完成后configurationClasses = {LinkedHashMap@5000} size = 131这个集合的配置类
java 复制代码
//通过配置类信息创建对应的beanDefinition到 beanFactory中
this.reader.loadBeanDefinitions(configClasses);

//这个逻辑完成后,beanFactory中信息:
//beanDefinitionNames = size = 322

//registeredSingletons = {LinkedHashSet@5928}  size = 13
 0 = "org.springframework.boot.context.ContextIdApplicationContextInitializer$ContextId"
 1 = "autoConfigurationReport"
 2 = "springApplicationArguments"
 3 = "springBootBanner"
 4 = "springBootLoggingSystem"
 5 = "springBootLoggerGroups"
 6 = "springBootLoggingLifecycle"
 7 = "environment"
 8 = "systemProperties"
 9 = "systemEnvironment"
 10 = "applicationStartup"
 11 = "org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory"
 12 = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"
2.10.1.2.3. 执行beanFactory中实现BeanFactoryPostProcessor接口的bean

逻辑和上面的执行BeanDefinitionRegistryPostProcessor一样,只不过是匹配BeanFactoryPostProcessor这个类的实现

java 复制代码
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

//这些后置处理器的逻辑例如:
String[] errorControllerBeans = beanFactory.getBeanNamesForType(ErrorController.class, false, false);
//处理errorControllerBeans自定义的逻辑

2.10.2. 注册BeanPostProcessor,初始化Bean前后钩子

registerBeanPostProcessors(beanFactory);

java 复制代码
//扫描bean:BeanPostProcessor
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// First, register the BeanPostProcessors that implement PriorityOrdered.
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Now, register all regular BeanPostProcessors.
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
registerBeanPostProcessors(beanFactory, internalPostProcessors);

//上面的registerBeanPostProcessors方法核心逻辑是:
this.beanPostProcessors.addAll(beanPostProcessors); //List<BeanPostProcessor>
2.10.2.1. BeanPostProcessor作用
java 复制代码
public interface BeanPostProcessor {
    /**
    BeanPostProcessor 在任何 bean 初始化回调(如 InitializingBean afterPropertiesSet 的或自定义的 init-method)之前,将此函数应用于给定的新 bean 实例。该 bean 将已填充属性值。返回的 bean 实例可能是原始 bean 实例的包装器。
    默认实现按原样返回给定 bean 的 Implementation。
    参数:
    bean -- 新的 bean 实例 beanName -- 豆子的名称
    返回:
    要使用的 bean 实例,原始实例或包装实例;如果 null,则不会调用后续的 BeanPostProcessors
        */
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    /**
    在任何 bean 初始化回调(如 InitializingBean afterPropertiesSet 或自定义 init-method)之后,将此函数BeanPostProcessor应用于给定的新 bean 实例。该 bean 将已填充属性值。返回的 bean 实例可能是原始 bean 实例的包装器。
    如果是 FactoryBean,则将为 FactoryBean 实例和 FactoryBean 创建的对象(从 Spring 2.0 开始)调用此回调。后处理器可以通过相应的 bean instanceof FactoryBean 检查来决定是应用于 FactoryBean 还是 created 对象,还是同时应用于两者。
    与所有其他BeanPostProcessor回调相反,此回调也将在方法触发InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation短路后调用。
    默认实现按原样返回给定 bean 的 Implementation。
    参数:
    bean -- 新的 bean 实例 beanName -- 豆子的名称
    返回:
    要使用的 bean 实例,原始实例或包装实例;如果 null,则不会调用后续的 BeanPostProcessors
        */
    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

可以自己定义一个Bean实现BeanPostProcessor接口,之后在bean实例化的时候就会调用自定义的逻辑

2.10.2.2. 处理后BeanPostProcessor的集合数据
js 复制代码
beanPostProcessors = {AbstractBeanFactory$BeanPostProcessorCacheAwareList@5918}  size = 14
 0 = {ApplicationContextAwareProcessor@12199} 
 1 = {WebApplicationContextServletContextAwareProcessor@12201} 
 2 = {ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor@12202} 
 3 = {PostProcessorRegistrationDelegate$BeanPostProcessorChecker@12203} 
 4 = {ConfigurationPropertiesBindingPostProcessor@12013} 
 5 = {InfrastructureAdvisorAutoProxyCreator@12069} "proxyTargetClass=true; optimize=false; opaque=false; exposeProxy=false; frozen=false"
 6 = {WebServerFactoryCustomizerBeanPostProcessor@12191} 
 7 = {ErrorPageRegistrarBeanPostProcessor@12192} 
 8 = {HealthEndpointConfiguration$HealthEndpointGroupsBeanPostProcessor@12193} 
 9 = {MeterRegistryPostProcessor@12194} 
 10 = {ObservationRegistryPostProcessor@12195} 
 11 = {CommonAnnotationBeanPostProcessor@12014} 
 12 = {AutowiredAnnotationBeanPostProcessor@12015} 
 13 = {ApplicationListenerDetector@12388} 

2.10.3. 创建tomcat服务

java 复制代码
private void createWebServer() {
    WebServer webServer = this.webServer;
    ServletContext servletContext = getServletContext();
    if (webServer == null && servletContext == null) {
        StartupStep createWebServer = getApplicationStartup().start("spring.boot.webserver.create");
        ServletWebServerFactory factory = getWebServerFactory();
        createWebServer.tag("factory", factory.getClass().toString());
        this.webServer = factory.getWebServer(getSelfInitializer());
        createWebServer.end();
        getBeanFactory().registerSingleton("webServerGracefulShutdown",
                new WebServerGracefulShutdownLifecycle(this.webServer));
        getBeanFactory().registerSingleton("webServerStartStop",
                new WebServerStartStopLifecycle(this, this.webServer));
    }
    else if (servletContext != null) {
        try {
            getSelfInitializer().onStartup(servletContext);
        }
        catch (ServletException ex) {
            throw new ApplicationContextException("Cannot initialize servlet context", ex);
        }
    }
    initPropertySources();
}
相关推荐
Yan.love几秒前
开发场景中Java 集合的最佳选择
java·数据结构·链表
椰椰椰耶4 分钟前
【文档搜索引擎】搜索模块的完整实现
java·搜索引擎
大G哥4 分钟前
java提高正则处理效率
java·开发语言
小_太_阳25 分钟前
Scala_【1】概述
开发语言·后端·scala·intellij-idea
智慧老师34 分钟前
Spring基础分析13-Spring Security框架
java·后端·spring
lxyzcm36 分钟前
C++23新特性解析:[[assume]]属性
java·c++·spring boot·c++23
V+zmm101341 小时前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
Oneforlove_twoforjob2 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
xmh-sxh-13142 小时前
常用的缓存技术都有哪些
java
搬码后生仔2 小时前
asp.net core webapi项目中 在生产环境中 进不去swagger
chrome·后端·asp.net