SpringBoot源码分析

SpringBoot 2.6.4。2022-1024-keep heart


在应用启动过程中涉及到多个事件,通过EventPublishingRunListener来触发他们,同时又调用了ApplicationContextInitializer接口完成一些特定操作

开始启动-> 准备环境 -> 准备上下文 -> 刷新上下文 -> 后置处理

public ConfigurableApplicationContext run(String... args) {
    long startTime = System.nanoTime();
    DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
    ConfigurableApplicationContext context = null;
    this.configureHeadlessProperty();
    // 1. 获取所有的SpringApplicationRunListener接口实例  (SpringApplicationRunListener接口被EventPublishingRunListener实现)
    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    listeners.starting(bootstrapContext, this.mainApplicationClass);

    try {
        // 创建  ApplicationArguments 对象 初始化默认应用参数类
        // args是启动Spring应用的命令行参数,该参数可以在Spring应用中被访问。如:--server.port=9000
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        // 2. 项目运行环境Environment的预配置
        ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
        this.configureIgnoreBeanInfo(environment);
        // 准备Banner打印器
        Banner printedBanner = this.printBanner(environment);
        // 3. 创建Spring容器
        context = this.createApplicationContext();
        context.setApplicationStartup(this.applicationStartup);
        // 4. Spring容器前置处理
        // 这一步主要是在容器刷新之前的准备动作。包含一个非常关键的操作:将启动类注入容器,为后续开启自动化配置奠定基础。
        this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
        // 5. 刷新容器
        this.refreshContext(context);
        // 6. Spring容器后置处理
        this.afterRefresh(context, applicationArguments);
        Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
        if (this.logStartupInfo) {
            (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), timeTakenToStartup);
        }
		// 7. 发出结束执行的事件通知
        listeners.started(context, timeTakenToStartup);
        // 8. 执行Runners
        this.callRunners(context, applicationArguments);
    } catch (Throwable var12) {
        this.handleRunFailure(context, var12, listeners);
        throw new IllegalStateException(var12);
    }

    try {
        Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
        listeners.ready(context, timeTakenToReady);
        return context;
    } catch (Throwable var11) {
        this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null);
        throw new IllegalStateException(var11);
    }
}

1. 注册监听器

SpringApplicationRunListeners listeners = this.getRunListeners(args);

解析getRunListeners

private SpringApplicationRunListeners getRunListeners(String[] args) {
    Class<?>[] types = new Class[]{SpringApplication.class, String[].class};
    return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args), this.applicationStartup);
}

分析SpringApplicationRunListeners构造函数,包含3个参数,将SpringApplicationRunListener接口进行包装

class SpringApplicationRunListeners {
    private final Log log;
    private final List<SpringApplicationRunListener> listeners;
    private final ApplicationStartup applicationStartup;

    SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners, ApplicationStartup applicationStartup) {
        this.log = log;
        this.listeners = new ArrayList(listeners);
        this.applicationStartup = applicationStartup;
    }
    // ...
}

实际包装的SpringApplicationRunListener接口

public interface SpringApplicationRunListener {
    default void starting(ConfigurableBootstrapContext bootstrapContext) {
    }

    default void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
    }

    default void contextPrepared(ConfigurableApplicationContext context) {
    }

    default void contextLoaded(ConfigurableApplicationContext context) {
    }

    default void started(ConfigurableApplicationContext context, Duration timeTaken) {
        this.started(context);
    }

    /** @deprecated */
    @Deprecated
    default void started(ConfigurableApplicationContext context) {
    }

    default void ready(ConfigurableApplicationContext context, Duration timeTaken) {
        this.running(context);
    }

    /** @deprecated */
    @Deprecated
    default void running(ConfigurableApplicationContext context) {
    }

    default void failed(ConfigurableApplicationContext context, Throwable exception) {
    }
}

主要分析SpringApplicationRunListener接口的starting()方法,由EventPublishingRunListener实现

public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
    private final SpringApplication application;
    private final String[] args;
    private final SimpleApplicationEventMulticaster initialMulticaster;
    
    // 构造函数
    public EventPublishingRunListener(SpringApplication application, String[] args) {
        this.application = application;
        this.args = args;
        this.initialMulticaster = new SimpleApplicationEventMulticaster();
        Iterator var3 = application.getListeners().iterator();

        while(var3.hasNext()) {
            ApplicationListener<?> listener = (ApplicationListener)var3.next();
            this.initialMulticaster.addApplicationListener(listener);
        }

    }

	public void starting(ConfigurableBootstrapContext bootstrapContext) {
        this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
    }
    
}

什么是initialMulticaster?分析构造函数可知,initialMulticaster即是SimpleApplicationEventMulticaster,并且将SpringApplication中的Listener都addApplicationListener()添加进去

什么是multicastEvent()?在其中传入new ApplicationStartingEvent(bootstrapContext, this.application, this.args)。分析multicastEvent()源码,每一个类型的处理方法都会传入一个指定的事件

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
    Executor executor = this.getTaskExecutor();
    // 1.迭代器获取所有的监听器
    Iterator var5 = this.getApplicationListeners(event, type).iterator();

    while(var5.hasNext()) {
        ApplicationListener<?> listener = (ApplicationListener)var5.next();
        if (executor != null) {
            executor.execute(() -> {
                // 2.调用监听器
                this.invokeListener(listener, event);
            });
        } else {
            this.invokeListener(listener, event);
        }
    }

}

可以看出在处理事件的方法内部做了两件事(multicastEvent方法内部标红的方法调用):

  1. 获取所有的监听器
  2. 调用监听器
// 获取所有的监听器
protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {
    Object source = event.getSource();
    Class<?> sourceType = source != null ? source.getClass() : null;
    AbstractApplicationEventMulticaster.ListenerCacheKey cacheKey = new AbstractApplicationEventMulticaster.ListenerCacheKey(eventType, sourceType);
    AbstractApplicationEventMulticaster.CachedListenerRetriever newRetriever = null;
    AbstractApplicationEventMulticaster.CachedListenerRetriever existingRetriever = (AbstractApplicationEventMulticaster.CachedListenerRetriever)this.retrieverCache.get(cacheKey);
    if (existingRetriever == null && (this.beanClassLoader == null || ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
        newRetriever = new AbstractApplicationEventMulticaster.CachedListenerRetriever();
        existingRetriever = (AbstractApplicationEventMulticaster.CachedListenerRetriever)this.retrieverCache.putIfAbsent(cacheKey, newRetriever);
        if (existingRetriever != null) {
            newRetriever = null;
        }
    }

    if (existingRetriever != null) {
        Collection<ApplicationListener<?>> result = existingRetriever.getApplicationListeners();
        if (result != null) {
            return result;
        }
    }
	// 实际获取逻辑
    return this.retrieveApplicationListeners(eventType, sourceType, newRetriever);
}
// 循环判断监听器声明的事件类型是否和本次处理的事件类型相同,本次处理的类型为ApplicationStartingEvent,不符合事件类型的事件会被排除,只调用声明了此类型的监听器。
private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable AbstractApplicationEventMulticaster.CachedListenerRetriever retriever) {
    List<ApplicationListener<?>> allListeners = new ArrayList();
    Set<ApplicationListener<?>> filteredListeners = retriever != null ? new LinkedHashSet() : null;
    Set<String> filteredListenerBeans = retriever != null ? new LinkedHashSet() : null;
    LinkedHashSet listeners;
    LinkedHashSet listenerBeans;
    synchronized(this.defaultRetriever) {
        listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
        listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans);
    }

    Iterator var9 = listeners.iterator();

    // 循环判断
    while(var9.hasNext()) {
        ApplicationListener<?> listener = (ApplicationListener)var9.next();
        if (this.supportsEvent(listener, eventType, sourceType)) {
            if (retriever != null) {
                filteredListeners.add(listener);
            }

            allListeners.add(listener);
        }
    }
    
    while(var16.hasNext()) {
        String listenerBeanName = (String)var16.next();

        try {
            // 循环判断所有的监听器(ApplicationListener)判断其是否支持当前所处理的事件(ApplicationStartingEvent)
            if (this.supportsEvent(beanFactory, listenerBeanName, eventType)) {
                // ...
            }
        }
    }

    // ...

    return allListeners;
}

深钻supportsEvent(beanFactory, listenerBeanName, eventType)

// 在判断当前监听器是否支持指定事件之前,将当前监听器转换为了GenericApplicationListener
protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
    GenericApplicationListener smartListener = listener instanceof GenericApplicationListener ? (GenericApplicationListener)listener : new GenericApplicationListenerAdapter(listener);
    // 使用GenericApplicationListener的supportsEventType()方法
    return ((GenericApplicationListener)smartListener).supportsEventType(eventType) && ((GenericApplicationListener)smartListener).supportsSourceType(sourceType);
}

分析上述代码如果Listener是GenericApplicationListener,那更好直接赋值;否则就new一个GenericApplicationListenerAdapter并将当前listener丢进去,继续深钻GenericApplicationListenerAdapter做了些什么?

private static final Map<Class<?>, ResolvableType> eventTypeCache = new ConcurrentReferenceHashMap();
private final ApplicationListener<ApplicationEvent> delegate;
@Nullable
private final ResolvableType declaredEventType;

// GenericApplicationListenerAdapter构造函数
public GenericApplicationListenerAdapter(ApplicationListener<?> delegate) {
    Assert.notNull(delegate, "Delegate listener must not be null");
    this.delegate = delegate;
    this.declaredEventType = resolveDeclaredEventType(this.delegate);
}

分析GenericApplicationListenerAdapter的构造函数可知获取了监听器声明的事件类型,即resolveDeclaredEventType(this.delegate)

@Nullable
private static ResolvableType resolveDeclaredEventType(ApplicationListener<ApplicationEvent> listener) {
    ResolvableType declaredEventType = resolveDeclaredEventType(listener.getClass());
    if (declaredEventType == null || declaredEventType.isAssignableFrom(ApplicationEvent.class)) {
        Class<?> targetClass = AopUtils.getTargetClass(listener);
        if (targetClass != listener.getClass()) {
            declaredEventType = resolveDeclaredEventType(targetClass);
        }
    }

    return declaredEventType;
}

比较了当前处理的事件和监听器处理的事件是否相符

public boolean supportsEventType(ResolvableType eventType) {
    if (this.delegate instanceof GenericApplicationListener) {
        return ((GenericApplicationListener)this.delegate).supportsEventType(eventType);
    } else if (this.delegate instanceof SmartApplicationListener) {
        Class<? extends ApplicationEvent> eventClass = eventType.resolve();
        return eventClass != null && ((SmartApplicationListener)this.delegate).supportsEventType(eventClass);
    } else {
        return this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType);
    }
}

监听器列表

LoggingApplicationListener
BackgroundPreinitializer
DelegatingApplicationListener
LiquibaseServiceLocatorApplicationListener

最先执行的Starting事件我们可以得知SpringBoot是如何处理事件,以及事件的匹配是如何实现。后续的其他事件处理都是同样的方式。

在run方法的try catch代码块内部,开始处理有关上下文的一些流程。SpringBoot也设计了精简的流程来处理不同的任务,具体来说就是如下几个方法共同完成每个阶段的任务。

ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);

在准备环境和准备上下文的过程中都传入了监听器,意味着它们会被调用。


2. 环境准备阶段

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
    // 1. 获取或者创建一个ConfigurableEnvironment
    ConfigurableEnvironment environment = this.getOrCreateEnvironment();
    // 2. 配置环境
    this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
    // 3. 将ConfigurationPropertySource支持附加到指定的环境
    ConfigurationPropertySources.attach((Environment)environment);
    // 4. 触发环境信息准备完毕事件
    listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
    DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
    Assert.state(!((ConfigurableEnvironment)environment).containsProperty("spring.main.environment-prefix"), "Environment prefix cannot be set via properties.");
    // 5. 绑定环境信息到当前应用程序
    this.bindToSpringApplication((ConfigurableEnvironment)environment);
    if (!this.isCustomEnvironment) {
        environment = this.convertEnvironment((ConfigurableEnvironment)environment);
    }
	// 6. 重复了第3步操作
    ConfigurationPropertySources.attach((Environment)environment);
    return (ConfigurableEnvironment)environment;
}

此处有一个疑问,为什么第6步要重复一下第3步的操作?

    1. 深究ConfigurableEnvironment对象的创建过程:
private ConfigurableEnvironment getOrCreateEnvironment() {
    if (this.environment != null) {
        return this.environment;
    } else {
        switch(this.webApplicationType) {
            case SERVLET:
                return new ApplicationServletEnvironment();
            case REACTIVE:
                return new ApplicationReactiveWebEnvironment();
            default:
                return new ApplicationEnvironment();
        }
    }
}

若environment不为null则直接返回,否则根据webApplicationType来创建环境对象,比如此处我们的应用为SERVLET,return new ApplicationServletEnvironment();

class ApplicationServletEnvironment extends StandardServletEnvironment {
    ApplicationServletEnvironment() {
    }

    protected String doGetActiveProfilesProperty() {
        return null;
    }

    protected String doGetDefaultProfilesProperty() {
        return null;
    }

    protected ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) {
        return ConfigurationPropertySources.createPropertyResolver(propertySources);
    }
}

继续下钻发现ApplicationServletEnvironment继承了StandardServletEnvironment

public class StandardServletEnvironment extends StandardEnvironment implements ConfigurableWebEnvironment {
    public static final String SERVLET_CONTEXT_PROPERTY_SOURCE_NAME = "servletContextInitParams";
    public static final String SERVLET_CONFIG_PROPERTY_SOURCE_NAME = "servletConfigInitParams";
    public static final String JNDI_PROPERTY_SOURCE_NAME = "jndiProperties";
    private static final boolean jndiPresent = ClassUtils.isPresent("javax.naming.InitialContext", StandardServletEnvironment.class.getClassLoader());

    public StandardServletEnvironment() {
    }

    protected StandardServletEnvironment(MutablePropertySources propertySources) {
        super(propertySources);
    }

    protected void customizePropertySources(MutablePropertySources propertySources) {
        propertySources.addLast(new StubPropertySource("servletConfigInitParams"));
        propertySources.addLast(new StubPropertySource("servletContextInitParams"));
        if (jndiPresent && JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
            propertySources.addLast(new JndiPropertySource("jndiProperties"));
        }

        super.customizePropertySources(propertySources);
    }

    public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
        WebApplicationContextUtils.initServletPropertySources(this.getPropertySources(), servletContext, servletConfig);
    }
}

这里可以看到customizePropertySources(MutablePropertySources propertySources)方法中addLast了两个配置集,分别是servletConfigInitParams/servletContextInitParams,jndiProperties配置集视情况再增加。之后调用父类StandardEnvironment的方法super.customizePropertySources(propertySources);

public class StandardEnvironment extends AbstractEnvironment {
    public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";
    public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";

    public StandardEnvironment() {
    }

    protected StandardEnvironment(MutablePropertySources propertySources) {
        super(propertySources);
    }

    protected void customizePropertySources(MutablePropertySources propertySources) {
        propertySources.addLast(new PropertiesPropertySource("systemProperties", this.getSystemProperties()));
        propertySources.addLast(new SystemEnvironmentPropertySource("systemEnvironment", this.getSystemEnvironment()));
    }
}

父类其中还是继续增加配置集,分别是系统级别的配置集systemProperties和systemEnvironment

至此一般就包括了4个配置集:

  • servletConfigInitParams
  • servletContextInitParams
  • systemEnvironment
  • systemProperties

环境信息就是profiles和配置文件以及系统环境信息的封装,在开发过程中我们根据官方指南和经验得知一个profile是有一套配置信息的,那么它的功能实现肯定是首先获取profile,然后再获取配置。但是我们在环境对象创建的时候发现它已经初始化了4个配置集,并且包含了系统配置(当前应用所运行的载体的配置信息)。但是这些配置信息除了系统配置之外其他都为空值,可以推断它只是预先初始化好配置容器,后续进行填充更新

问题来了:

  1. 配置什么时候被填充?
  2. 被填充的配置怎么来?

回到SpringApplication的run() -> prepareEnvironment()->configureEnvironment()方法

protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
    // 1. 注册ConversationServoce,Spring内部用来处理统一类型转换的服务(将配置文件中的不同类型转换为它所要表示的类型例如:xxx.enable = false,将会将false转换为真正的boolean对象),一些常见的转换服务有StringToDurationConverter、DurationToStringConverter、StringToDataSizeConverter等
    if (this.addConversionService) {
        environment.setConversionService(new ApplicationConversionService());
    }
	// 2. 配置属性资源
    this.configurePropertySources(environment, args);
    // 3. 配置profiles
    this.configureProfiles(environment, args);
}
深钻2. 配置属性资源this.configurePropertySources(environment, args);
protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) {
    // 1. 获取环境对象中的配置对象
    MutablePropertySources sources = environment.getPropertySources();
    // 2. 检查并插入默认配置
    if (!CollectionUtils.isEmpty(this.defaultProperties)) {
        DefaultPropertiesPropertySource.addOrMerge(this.defaultProperties, sources);
    }
	// 3. 检查并插入命令行配置
    if (this.addCommandLineProperties && args.length > 0) {
        String name = "commandLineArgs";
        if (sources.contains(name)) {
            PropertySource<?> source = sources.get(name);
            CompositePropertySource composite = new CompositePropertySource(name);
            composite.addPropertySource(new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));
            composite.addPropertySource(source);
            sources.replace(name, composite);
        } else {
            sources.addFirst(new SimpleCommandLinePropertySource(args));
        }
    }
}
深钻3. 配置profiles,this.configureProfiles(environment, args);

TODO:留一个坑,为什么可以预留一个空方法体,如何实现调用

// 啥都没有?
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
}
  • 初始化可变环境信息对象,初始化4个系统级别的配置集
  • 将应用启动的参数信息填入环境信息对象
  • 包装为SpringConfigurationPropertySources对象放入环境信息中

监听器触发ConfigDataEnvironmentPostProcessor

(从2.4.0开始弃用ConfigFileApplicationListener,改用ConfigDataEnvironmentPostProcessor)

在spring.factories中注册了该监听器:

org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor,\
public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {}

ConfigDataEnvironmentPostProcessor实现了Ordered接口,意味着它具有排序能力(相同接口实现列表中的排序优先级),并且它的优先级被设置为了最高-10(Integer.MIN_VALUE为最高优先级,+10就相当于数值加大优先级减10):DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 10。

// EnvironmentPostProcessorApplicationListener
@Override
public void onApplicationEvent(ApplicationEvent event) {
    if (event instanceof ApplicationEnvironmentPreparedEvent) {
        onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
    }
    if (event instanceof ApplicationPreparedEvent) {
        onApplicationPreparedEvent();
    }
    if (event instanceof ApplicationFailedEvent) {
        onApplicationFailedEvent();
    }
}

private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
    
    ConfigurableEnvironment environment = event.getEnvironment();
    SpringApplication application = event.getSpringApplication();
    // 1. 遍历获取所有的EnvironmentPostProcessor
    for (EnvironmentPostProcessor postProcessor : getEnvironmentPostProcessors(application.getResourceLoader(),
                                                                               event.getBootstrapContext())) {
        // 2.执行所有的Processor
        postProcessor.postProcessEnvironment(environment, application);
    }
}

默认情况下加载以下Processor(优先级从高到低):

  • RandomValuePropertySourceEnvironmentPostProcessor
  • SystemEnvironmentPropertySourceEnvironmentPostProcessor
  • SpringApplicationJsonEnvironmentPostProcessor
  • CloudFoundryVcapEnvironmentPostProcessor
  • ConfigDataEnvironmentPostProcessor
  • DebugAgentEnvironmentPostProcessor
  • IntegrationPropertiesEnvironmentPostProcessor

TODO Processor分析

① 配置文件的加载动作是由监听器ConfigDataEnvironmentPostProcessor触发
② 根据指定的不同profile匹配指定的配置文件名称,默认支持的文件后缀为:properties/xml/yml/yaml;默认支持的配置文件路径有:classpath:/,classpath:/config/,file:./,file:./config/
③ 不同类型的文件有对应的解析器处理
④ 配置文件的优先级首先以profile的声明顺序为主,后声明的优先级高,文件类型以默认支持的文件类型顺序为主,最先声明的优先级最高
⑥ 指定profile可以通过参数spring.profiles.active=dev,common指定,也可以在配置文件中声明spring.profiles=dev,common来指定,不推荐使用后者
⑦ 指定配置文件的位置可以通过参数spring.config.location=xxxx来指定
⑧ 指定配置文件的名称可以通过参数spring.config.name=xxxx来指定

3. 准备上下文阶段

// 创建Spring容器
context = createApplicationContext();
// 预处理上下文容器
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);

解析prepareContext()

// SpringApplication.java
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
                            ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
                            ApplicationArguments applicationArguments, Banner printedBanner) {
    // 设置环境对象,传入解析完毕的profiles的对象,Context内部则是不完整的对象
    context.setEnvironment(environment);
    // *设置上下文参数
    postProcessApplicationContext(context);
    // *加载ApplicationContextInitializers
    applyInitializers(context);
    // 触发开始准备上下文事件
    listeners.contextPrepared(context);
    bootstrapContext.close(context);
    if (this.logStartupInfo) {
        logStartupInfo(context.getParent() == null);
        // 记录活动的profiles日志
        logStartupProfileInfo(context);
    }
    // Add boot specific singleton beans
    // 将启动参数包装为名为springApplicationArguments的DefaultApplicationArguments对象,并以单例模式注册
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    // 设置打印的Banner
    if (printedBanner != null) {
        beanFactory.registerSingleton("springBootBanner", printedBanner);
    }
    //设置是否允许覆盖BeanDefinition
    if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
        ((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
        if (beanFactory instanceof DefaultListableBeanFactory) {
            ((DefaultListableBeanFactory) beanFactory)
            .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
    }
    if (this.lazyInitialization) {
        context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
    }
    // 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);
}

深钻设置上下文参数postProcessApplicationContext(context);:

// SpringApplication.java
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
    // 以单例模式注册beanNameGenerator
    if (this.beanNameGenerator != null) {
        context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
                                                   this.beanNameGenerator);
    }
    // 为上下文设置资源加载器和类加载器
    if (this.resourceLoader != null) {
        if (context instanceof GenericApplicationContext) {
            ((GenericApplicationContext) context).setResourceLoader(this.resourceLoader);
        }
        if (context instanceof DefaultResourceLoader) {
            ((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader());
        }
    }
    // 为上下文设置转换服务
    if (this.addConversionService) {
        context.getBeanFactory().setConversionService(context.getEnvironment().getConversionService());
    }
}

深钻加载ApplicationContextInitializers,applyInitializers(context);

protected void applyInitializers(ConfigurableApplicationContext context) {
    // 调用每一个实现类的initialize方法
    for (ApplicationContextInitializer initializer : getInitializers()) {
        Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
                                                                        ApplicationContextInitializer.class);
        Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
        // 初始化
        initializer.initialize(context);
    }
}

// 将之前获取到的集合进行排序并返回只读集合
public Set<ApplicationContextInitializer<?>> getInitializers() {
    return asUnmodifiableOrderedSet(this.initializers);
}

// DelegatingApplicationContextInitializer.java
@Override
public void initialize(ConfigurableApplicationContext context) {
    // 获取环境对象 
    ConfigurableEnvironment environment = context.getEnvironment();
    // 获取context.initializer.classes属性指定的实现类
    List<Class<?>> initializerClasses = getInitializerClasses(environment);
    if (!initializerClasses.isEmpty()) {
        // 调用initialize()方法
        applyInitializerClasses(context, initializerClasses);
    }
}


private List<Class<?>> getInitializerClasses(ConfigurableEnvironment env) {
    // 通过指定属性去获取,此处常量属性值为context.initializer.classes
    String classNames = env.getProperty(PROPERTY_NAME);
    List<Class<?>> classes = new ArrayList<>();
    if (StringUtils.hasLength(classNames)) {
        for (String className : StringUtils.tokenizeToStringArray(classNames, ",")) {
            // 根据代码可以推断出 context.initializer.classes的值可以用逗号拼接
            classes.add(getInitializerClass(className));
        }
    }
    return classes;
}
// SpringApplication.java
protected void logStartupProfileInfo(ConfigurableApplicationContext context) {
    Log log = getApplicationLog();
    if (log.isInfoEnabled()) {
        List<String> activeProfiles = quoteProfiles(context.getEnvironment().getActiveProfiles());
        if (ObjectUtils.isEmpty(activeProfiles)) {
            List<String> defaultProfiles = quoteProfiles(context.getEnvironment().getDefaultProfiles());
            String message = String.format("%s default %s: ", defaultProfiles.size(),
                                           (defaultProfiles.size() <= 1) ? "profile" : "profiles");
            log.info("No active profile set, falling back to " + message
                     + StringUtils.collectionToDelimitedString(defaultProfiles, ", "));
        }
        else {
            String message = (activeProfiles.size() == 1) ? "1 profile is active: "
                : activeProfiles.size() + " profiles are active: ";
            log.info("The following " + message + StringUtils.collectionToDelimitedString(activeProfiles, ", "));
        }
    }
}

将参数对象注册为单例模式

// SpringApplication.java#prepareContext()
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);

是否允许覆盖Bean定义

// SpringApplication.java#prepareContext()
// spring.main.allow-bean-definition-overriding参数有关,默认情况下在DefaultListableBeanFactory中是true,但是SpringBoot在此处给设置成了false
if (beanFactory instanceof DefaultListableBeanFactory) {
    ((DefaultListableBeanFactory) beanFactory)
    .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}

加载bean到上下文中

// SpringApplication.java#prepareContext()
// Load the sources 获取当前应用要加载的资源
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
// *加载bean
load(context, sources.toArray(new Object[0]));

// SpringApplication.java#prepareContext()->load()
// 创建Bean加载器,并加载
protected void load(ApplicationContext context, Object[] sources) {
    if (logger.isDebugEnabled()) {
        logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
    }
    // 创建BeanDefinitionLoader
    BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
    if (this.beanNameGenerator != null) {
        loader.setBeanNameGenerator(this.beanNameGenerator);
    }
    if (this.resourceLoader != null) {
        loader.setResourceLoader(this.resourceLoader);
    }
    if (this.environment != null) {
        loader.setEnvironment(this.environment);
    }
    loader.load();
}

初始化BeanDefinitionLoader:通过观察它的内部属性和构造方法可以看出,它支持加载基于编程方式配置的类,支持xml文件配置的类,支持groovy和xml混合定义的类的加载。它使用门面模式封装了这些具体的加载器。此处只需要先知道BeanDefinitionLoader用于加载Bean,且它内部封装了多个类读取器即可
不必深入。先了解大体的功能性即可。

// SpringApplication.java#prepareContext()->load()->createBeanDefinitionLoader()
protected BeanDefinitionLoader createBeanDefinitionLoader(BeanDefinitionRegistry registry, Object[] sources) {
    return new BeanDefinitionLoader(registry, sources);
}
// 实体类
class BeanDefinitionLoader {

	// Static final field to facilitate code removal by Graal
	private static final boolean XML_ENABLED = !SpringProperties.getFlag("spring.xml.ignore");

	private static final Pattern GROOVY_CLOSURE_PATTERN = Pattern.compile(".*\\$_.*closure.*");
	// 类的来源
	private final Object[] sources;
	// JavaConfig类读取器
	private final AnnotatedBeanDefinitionReader annotatedReader;
	// xml文件类读取器
	private final AbstractBeanDefinitionReader xmlReader;

	private final BeanDefinitionReader groovyReader;
	// classpath类读取器
	private final ClassPathBeanDefinitionScanner scanner;
	// 资源加载器
	private ResourceLoader resourceLoader;
    
    BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
		Assert.notNull(registry, "Registry must not be null");
		Assert.notEmpty(sources, "Sources must not be empty");
		this.sources = sources;
		this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
		this.xmlReader = (XML_ENABLED ? new XmlBeanDefinitionReader(registry) : null);
		this.groovyReader = (isGroovyPresent() ? new GroovyBeanDefinitionReader(registry) : null);
		this.scanner = new ClassPathBeanDefinitionScanner(registry);
		this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
	}
    
    // 省略...
}

使用BeanDefinitionLoader加载Bean

// BeanDefinitionLoader.java
// 统一加载方法
void load() {
    for (Object source : this.sources) {
        load(source);
    }
}
// 根据传入的资源类型选择不同的加载方式
private void load(Object source) {
    Assert.notNull(source, "Source must not be null");
    // 经典加载模式
    if (source instanceof Class<?>) {
        load((Class<?>) source);
        return;
    }
    if (source instanceof Resource) {
        load((Resource) source);
        return;
    }
    if (source instanceof Package) {
        load((Package) source);
        return;
    }
    if (source instanceof CharSequence) {
        load((CharSequence) source);
        return;
    }
    throw new IllegalArgumentException("Invalid source type " + source.getClass());
}

此处我们选择SpringBoot典型的资源加载方式Class方式来分析,在应用程序启动入口我们使用的是SpringApplication.run(Example.class, args);而Example.class是我们的main函数所在类,以它作为资源来加载。

// BeanDefinitionLoader.java load((Class<?>) source)

private void load(Class<?> source) {
    // 判断是否支持Groovy
    if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
        // Any GroovyLoaders added in beans{} DSL can contribute beans here
        GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
        ((GroovyBeanDefinitionReader) this.groovyReader).beans(loader.getBeans());
    }
    // 判断是否可注册
    if (isEligible(source)) {
        // 读取@Component注解进行注册
        this.annotatedReader.register(source);
    }
}


private boolean isEligible(Class<?> type) {
    return !(type.isAnonymousClass() || isGroovyClosure(type) || hasNoConstructors(type));
}

注册:

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
    // 1. 创建一个带注解元数据的类定义
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
	// 2. 判断是否有@Conditional注解
    if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        // 3. 设置一个创建Bean的回调。基本都是空值
        abd.setInstanceSupplier(supplier);
        // 4. 获取当前Bean的作用域元数据,判断依据是是否包含@Scope注解。ScopeMetadata包含类的作用域描述(singleton | prototype)和代理模式描述ScopedProxyMode,默认为单例模式,不使用代理创建。
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        abd.setScope(scopeMetadata.getScopeName());
        String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
        // 5. 处理常用注解,包括@Lazy、@Primary、@Role、@Description、@DependsOn,他们将被设置到BeanDefinition的属性当中。
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
        int var10;
        int var11;
        // 6. 检查传入的Qualifiers
        if (qualifiers != null) {
            Class[] var9 = qualifiers;
            var10 = qualifiers.length;

            for(var11 = 0; var11 < var10; ++var11) {
                Class<? extends Annotation> qualifier = var9[var11];
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                } else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                } else {
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }

        if (customizers != null) {
            BeanDefinitionCustomizer[] var13 = customizers;
            var10 = customizers.length;

            for(var11 = 0; var11 < var10; ++var11) {
                BeanDefinitionCustomizer customizer = var13[var11];
                customizer.customize(abd);
            }
        }

        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }
}

发布ApplicationPreparedEvent事件,EventPublishingRunListener.contextLoaded(ConfigurableApplicationContext context)方法触发。

在真正触发事件之前,它处理了ApplicationContextAware实现,为其设置了上下文。为ApplicationContextAware扩展接口设置上下文

@Override
public void contextLoaded(ConfigurableApplicationContext context) {
    for (ApplicationListener<?> listener : this.application.getListeners()) {
        if (listener instanceof ApplicationContextAware) {
            ((ApplicationContextAware) listener).setApplicationContext(context);
        }
        // 将所有监听器赋值给上下文
        context.addApplicationListener(listener);
    }
    this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}
ConfigFileApplicationListener

添加了一个BeanFactoryPostProcessor:PropertySourceOrderingPostProcessor,用于重排序defaultProperties

LoggingApplicationListener

以单例模式注册注册当前日志系统

总结:在预处理上下文时将先前加载的一些属性赋值给context,执行了ApplicationContextInitializers的实现类,为ApplicationContextAware接口填充context对象。

4. 刷新容器

5. 后置处理阶段

参考资料:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值