SpringBoot源码解析(三)

开课吧开课吧锤锤2021-07-22 15:01

书接上文,本篇源码主要针对run方法进行展开,源码及注释占比较高,文字性描述会偏少,喜欢的读者请耐心看完。 

SpringBoot源码解析

run方法代码展示  

/**
 * Run the Spring application, creating and refreshing a new
 * {@link ApplicationContext}.
 * @param args the application arguments (usually passed from a Java main method)
 * @return a running {@link ApplicationContext}
 */
public ConfigurableApplicationContext run(String... args) {
    // 创建时间统计对象 计算程序运行时间
    StopWatch stopWatch = new StopWatch();
    // 开始计时
    stopWatch.start();
    // ApplicationContext的子接口 可操作上下文配置
    ConfigurableApplicationContext context = null;
    // 初始化SpringBoot异常报告器数组
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    // 配置headless参数
    configureHeadlessProperty();
    // 通过SPI机制加载META-INF/spring.factories文件下的key为SpringApplicationRunListener对应的values
    SpringApplicationRunListeners listeners = getRunListeners(args);
    // 启动监听器
    listeners.starting();
    try {
        // 参数封装 命令行下启动应用时带的参数
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        // 构建应用上下文应用环境
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
        // 处理需要被忽略的bean
        configureIgnoreBeanInfo(environment);
        // 启动时打印banner
        Banner printedBanner = printBanner(environment);
        // 创建应用上下文对象
        context = createApplicationContext();
        // 获取SpringBootExceptionReporter接口的类 用于支持报告关于启动的错误
        exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                new Class[] { ConfigurableApplicationContext.class }, context);
        // 构建应用上下文前的准备阶段
        prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        // 刷新应用上下文
        refreshContext(context);
        // 刷新应用上下文后的扩展接口(空实现 根据需求自定义)
        afterRefresh(context, applicationArguments);
        // 结束统计
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
        }
        // 调用started
        listeners.started(context);
        // ApplicationRunner
        // CommandLineRunner
        // 获取这两个接口的实现类,并调用其run方法
        callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, listeners);
        throw new IllegalStateException(ex);
    }
    try {
        listeners.running(context);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, null);
        throw new IllegalStateException(ex);
    }
    return context;
}

通过代码和注释,我们大体了解了run方法中都做了些什么,那么下面会针对核心的代码进行深入讲解。  

获取监听器并启动监听  

获取监听器  

// 通过SPI机制加载META-INF/spring.factories文件下的key为SpringApplicationRunListener对应的values
SpringApplicationRunListeners listeners = getRunListeners(args);

private SpringApplicationRunListeners getRunListeners(String[] args) {
    Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
    // SpringApplicationRunListener在整个启动流程中接收不同执行点事件通知的监听者
    // 在各个生命周期广播相应的事件然后去调用实际要执行的ApplicationListener实现类
    return new SpringApplicationRunListeners(logger,
            getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
};

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
    // 获取类加载器
    ClassLoader classLoader = getClassLoader();
    // 根据传入的type(刚刚传入的是ApplicationContextInitializer)和classLoader获取到type对应的value的类的全路径
    Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    // 通过反射 将names集合中的类全路径初始化成对象存到List集合中返回
    List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    // 根据类上的@Order注解中的值 对刚初始化完的实例进行排序
    AnnotationAwareOrderComparator.sort(instances);
    // 返回实例集合
    return instances;
}

启动监听器  

SpringApplicationRunListeners.class
// 该方法在run方法执行时调用
void starting() {
    for (SpringApplicationRunListener listener : this.listeners) {
        listener.starting();
    }
}

EventPublishingRunListener.class
@Override
public void starting() {
    this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}

SimpleApplicationEventMulticaster.class
@Override
public void multicastEvent(ApplicationEvent event) {
    multicastEvent(event, resolveDefaultEventType(event));
}

@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    Executor executor = getTaskExecutor();
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        if (executor != null) {
            executor.execute(() -> invokeListener(listener, event));
        }
        else {
            invokeListener(listener, event);
        }
    }
}

启动监听器比较简单,根据获取到的SpringApplicationRunListeners对象,然后调用starting方法,在方法里面做的就是遍历每一个Listener并启动监听,只是启动监听器的方法层层调用,看起来比较复杂而已。  

构建应用上下文应用环境  

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
        ApplicationArguments applicationArguments) {
    // Create and configure the environment
    // 创建并配置环境
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    // 加载用户配置信息和系统环境信息到environment对象中
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    ConfigurationPropertySources.attach(environment);
    // 启动spring.factories配置的监听器
    listeners.environmentPrepared(environment);
    // 将应用上下文环境对象绑定到SpringApplication
    bindToSpringApplication(environment);
    // 非web环境 将上应用下文环境对象转换成StandardEnvironment
    if (!this.isCustomEnvironment) {
        environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
                deduceEnvironmentClass());
    }
    // 配置PropertySources对它自己的递归依赖
    ConfigurationPropertySources.attach(environment);
    return environment;
}

创建并配置环境  

// 获取或创建应用上下文环境
private ConfigurableEnvironment getOrCreateEnvironment() {
    // 存在则直接返回
    if (this.environment != null) {
        return this.environment;
    }
    // 判断Web应用类型 然后返回相应的上下文对象
    switch (this.webApplicationType) {
        // Servlet环境
    case SERVLET:
        return new StandardServletEnvironment();
        // Reactive环境
    case REACTIVE:
        return new StandardReactiveWebEnvironment();
    default:
        // 非Web环境
        return new StandardEnvironment();
    }
}

加载用户配置信息和系统环境信息到environment对象中  

// 将启动类中main方法的args参数封装成SimpleCommandLinePropertySource加入到环境中
protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) {
    //调用AbstractEnvironment的getPropertySources()方法获取之前配置的属性
    MutablePropertySources sources = environment.getPropertySources();
    if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) {
        // 当defaultProperties不为null时 将defaultProperties添加到propertySources的末尾
        sources.addLast(new MapPropertySource("defaultProperties", this.defaultProperties));
    }
    if (this.addCommandLineProperties && args.length > 0) {
        // 如果命令行有参数
        String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
        // 如果sources中包含"commandLineArgs"
        if (sources.contains(name)) {
            // 如果MutablePropertySources中包含name为commandLineArgs的PropertySource
            // 则把当前命令行参数转换为CompositePropertySource类型与原来的PropertySource进行合并
            // 替换原来的PropertySource
            PropertySource<?> source = sources.get(name);
            CompositePropertySource composite = new CompositePropertySource(name);
            composite.addPropertySource(
                    new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));
            composite.addPropertySource(source);
            sources.replace(name, composite);
        }
        else {
            // 如果MutablePropertySources中不包含name为commandLineArgs的PropertySource的
            // 则将其作为首元素添加到MutablePropertySources中
            sources.addFirst(new SimpleCommandLinePropertySource(args));
        }
    }
}

启动监听器  

SpringApplicationRunListeners.class
// 该方法在environment构建完成且ApplicationContext创建之前调用
void environmentPrepared(ConfigurableEnvironment environment) {
    for (SpringApplicationRunListener listener : this.listeners) {
        listener.environmentPrepared(environment);
    }
}

EventPublishingRunListener.class
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
    this.initialMulticaster
            .multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
}
SimpleApplicationEventMulticaster.class@Override
public void multicastEvent(ApplicationEvent event) {
    multicastEvent(event, resolveDefaultEventType(event));
}

@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    Executor executor = getTaskExecutor();
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        if (executor != null) {
            executor.execute(() -> invokeListener(listener, event));
        }
        else {
            invokeListener(listener, event);
        }
    }
}

启动监听器的代码和上面的差不多,就是传入的参数不一样,最终执行的方法还是一样的。  

处理需要被忽略的Bean  

private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
    // 判断系统属性spring.beaninfo.ignore是否为null
    if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
        // 获取environment中的spring.beaninfo.ignore属性 不存在返回true
        Boolean ignore = environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE);
        // 用environment的value替换System中的value
        System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, ignore.toString());
    }
}

启动时打印Banner  

private Banner printBanner(ConfigurableEnvironment environment) {
    // 判断banner图输出模式 默认为CONSOLE 如果为OFF则不输出返回空
    if (this.bannerMode == Banner.Mode.OFF) {
        return null;
    }
    // 获取resourceLoader this.resourceLoader的初始值为null
    // 创建DefaultResourceLoader对象返回
    ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
            : new DefaultResourceLoader(getClassLoader());
    // 实例化SpringApplicationBannerPrinter对象
    SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
    // 判断banner是否需要输出到日志文件
    if (this.bannerMode == Mode.LOG) {
        return bannerPrinter.print(environment, this.mainApplicationClass, logger);
    }
    // 输出banner到控制台 包括environment信息
    return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}

创建应用上下文对象  

protected ConfigurableApplicationContext createApplicationContext() {
    // 将当前对象的applicationContextClass赋值给contextClass
    Class<?> contextClass = this.applicationContextClass;
    // 如果contextClass为null 则根据Web应用类型创建对应的对象
    if (contextClass == null) {
        try {
            switch (this.webApplicationType) {
            case SERVLET:
                // AnnotationConfigServletWebServerApplicationContext
                contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
                break;
            case REACTIVE:
                // AnnotationConfigReactiveWebServerApplicationContext
                contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
                break;
            default:
                // AnnotationConfigApplicationContext
                contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
            }
        }
        catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                    "Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
        }
    }
    return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}

获取SpringBootExceptionReporter实现类  

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
    // 获取类加载器
    ClassLoader classLoader = getClassLoader();
    // 根据传入的type(刚刚传入的是ApplicationContextInitializer)和classLoader获取到type对应的value的类的全路径
    Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    // 通过反射 将names集合中的类全路径初始化成对象存到List集合中返回
    List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    // 根据类上的@Order注解中的值 对刚初始化完的实例进行排序
    AnnotationAwareOrderComparator.sort(instances);
    // 返回实例集合
    return instances;
}

构建应用上下文前的准备阶段  

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
        SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
    // 给上应用下文设置环境
    context.setEnvironment(environment);
    // 对上下文进行后置处理
    postProcessApplicationContext(context);
    // 应用初始化器
    applyInitializers(context);
    // 向监听器发送已经准备好的事件
    listeners.contextPrepared(context);
    // 日志相关操作 忽略
    if (this.logStartupInfo) {
        logStartupInfo(context.getParent() == null);
        logStartupProfileInfo(context);
    }
    // Add boot specific singleton beans
    // 获取容器对象
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    // 将启动类的args参数封装成单例对象 并注册到容器中
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    // 判断printedBanner对象是为null
    if (printedBanner != null) {
        // 不为null 则将该对象也封装成单例对象注册到容器中
        beanFactory.registerSingleton("springBootBanner", printedBanner);
    }
    // 判断当前beanFactory对象是否是DefaultListableBeanFactory类型
    if (beanFactory instanceof DefaultListableBeanFactory) {
        // 条件成立则将 是否允许Bean的定义被覆盖 属性设置为allowBeanDefinitionOverriding
        ((DefaultListableBeanFactory) beanFactory)
                .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    // 判断当前对象是否为懒加载(默认值为false)
    if (this.lazyInitialization) {
        // 条件成立 为上下文对象添加Bean工厂后处理器(懒加载BeanFactory)
        context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
    }
    // Load the sources
    // 拿到所有的sources 里面会包含启动类
    Set<Object> sources = getAllSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    // 加载启动类 并将其注册到容器中
    load(context, sources.toArray(new Object[0]));
    // 监听器加载容器已经发布的事件
    listeners.contextLoaded(context);
}

对上下文进行后置处理  

protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
    // 判断this.beanNameGenerator是否为null 默认值为null
    if (this.beanNameGenerator != null) {
        // 1.获取IOC容器 注册一个单例internalConfigurationBeanNameGenerator到容器中
        context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
                this.beanNameGenerator);
    }
    // 判断this.resourceLoader是否为null 默认值为null
    if (this.resourceLoader != null) {
        // 类型判断
        if (context instanceof GenericApplicationContext) {
            // 为上下文对象设置resourceLoader
            ((GenericApplicationContext) context).setResourceLoader(this.resourceLoader);
        }
        // 类型判断
        if (context instanceof DefaultResourceLoader) {
            // 为上下文对象设置classLoader
            ((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader());
        }
    }
    // 判断this.addConversionService是否为true 默认值true
    if (this.addConversionService) {
        // 为IOC容器设置转换器
        context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance());
    }
}

应用初始化器  

@SuppressWarnings({ "rawtypes", "unchecked" })
protected void applyInitializers(ConfigurableApplicationContext context) {
    // 遍历ApplicationContextInitializer(SPI加载)
    // 调用ApplicationContextInitializer的initialize来初始化context
    for (ApplicationContextInitializer initializer : getInitializers()) {
        Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
                ApplicationContextInitializer.class);
        Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
        initializer.initialize(context);
    }
}

向监听器发送已经准备好的事件  

SpringApplicationRunListeners.class
// 该方法在ApplicationContext构建完成时调用
void contextPrepared(ConfigurableApplicationContext context) {
    for (SpringApplicationRunListener listener : this.listeners) {
        listener.contextPrepared(context);
    }
}

EventPublishingRunListener.class
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
    this.initialMulticaster
            .multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
}

SimpleApplicationEventMulticaster.class
@Override
public void multicastEvent(ApplicationEvent event) {
    multicastEvent(event, resolveDefaultEventType(event));
}

@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    Executor executor = getTaskExecutor();
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        if (executor != null) {
            executor.execute(() -> invokeListener(listener, event));
        }
        else {
            invokeListener(listener, event);
        }
    }
}

加载启动类并将其注册到容器中  

protected void load(ApplicationContext context, Object[] sources) {

    if (logger.isDebugEnabled()) {
        logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
    }
    // 创建BeanDefinitionLoader 并将sources对象加载到该对象中
    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();
}

int load() {
    int count = 0;
    for (Object source : this.sources) {
        count += load(source);
    }
    return count;
}

private int load(Object source) {
    Assert.notNull(source, "Source must not be null");
    // 从Class加载
    if (source instanceof Class<?>) {
        return load((Class<?>) source);
    }
    // 从Resource加载
    if (source instanceof Resource) {
        return load((Resource) source);
    }
    // 从Package加载
    if (source instanceof Package) {
        return load((Package) source);
    }
    // 从CharSequence加载
    if (source instanceof CharSequence) {
        return load((CharSequence) source);
    }
    throw new IllegalArgumentException("Invalid source type " + source.getClass());
}

private int load(Class<?> source) {
    if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
        // Any GroovyLoaders added in beans{} DSL can contribute beans here
        GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
        load(loader);
    }
    // 判断传入的source对象上是否加上@Component注解
    if (isComponent(source)) {
        //  如果加了注解则通过annotatedReader将启动类注册成bean
        this.annotatedReader.register(source);
        return 1;
    }
    return 0;
}

监听器加载容器已经发布的事件  

// 该方法在ApplicationContext加载完成上下文刷新之前调用
void contextLoaded(ConfigurableApplicationContext context) {
    for (SpringApplicationRunListener listener : this.listeners) {
        listener.contextLoaded(context);
    }
}

EventPublishingRunListener.class
@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));
}


SimpleApplicationEventMulticaster.class
@Override
public void multicastEvent(ApplicationEvent event) {
    multicastEvent(event, resolveDefaultEventType(event));
}

@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    Executor executor = getTaskExecutor();
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        if (executor != null) {
            executor.execute(() -> invokeListener(listener, event));
        }
        else {
            invokeListener(listener, event);
        }
    }
}

刷新应用上下文  

刷新应用上下文最后执行了11个核心方法,也是Spring的核心源码。在本篇中这块内容不进行展开说明。  

刷新应用上下文后的扩展接口  

// 空实现 根据需求自定义
protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {
}

通过本篇文章的讲解,我们对run方法的整体运行流程有了大体的认知,想知道更多细节的小伙伴还是需要动手Debug跑一跑哦。  

以上就是开课吧广场小编为大家整理发布的“SpringBoot源码解析(三)”一文,更多Java教程相关内容尽在开课吧Java教程频道。

免责声明:本站所提供的内容均来源于网友提供或网络搜集,由本站编辑整理,仅供个人研究、交流学习使用。如涉及版权问题,请联系本站管理员予以更改或删除。
有用
分享