Spring Boot源码(四) - prepareEnvironment、反射创建ApplicationContext对象、prepareContext

目录

一、创建和配置Environment

1、创建Environment对象(getOrCreateEnvironment)

2、配置Environment(ConversionService、main方法传入的args参数、Profile)

3、SpringApplicationRunListener的environmentPrepared回调

4、自定义Environment

二、反射创建ApplicationContext对象

三、prepareContext

1、为Spring容器设置初始化的环境

2、为ConfigurableApplicationContext设置属性

3、回调ApplicationContextInitializer的initialize方法

4、回调SpringApplicationRunListener的contextPrepared方法

5、将applicationArguments、Banner注册成单例Bean

6、是否添加LazyInitializationBeanFactoryPostProcessor进行懒加载处理

7、 将main类注册BeanDefinition

8、回调SpringApplicationRunListener的contextLoaded方法


// 将main方法的args参数进行封装
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备Environment
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 配置忽略注入的Bean
configureIgnoreBeanInfo(environment);
// 打印banner图
Banner printedBanner = printBanner(environment);
// 反射创建ApplicationContext对象
context = createApplicationContext();
// 还在加载自动装配的SpringBootExceptionReporter类型, 默认只有FailureAnalyzers
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
// 为ApplicationContext设置属性、做refresh的准备工作
prepareContext(context, environment, listeners, applicationArguments, printedBanner);

一、创建和配置Environment

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
                                                   ApplicationArguments applicationArguments) {
    // Create and configure the environment
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    ConfigurationPropertySources.attach(environment);
    listeners.environmentPrepared(environment);
    bindToSpringApplication(environment);
    if (!this.isCustomEnvironment) {
        environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
                deduceEnvironmentClass());
    }
    ConfigurationPropertySources.attach(environment);
    return environment;
}

1、创建Environment对象(getOrCreateEnvironment)

private ConfigurableEnvironment getOrCreateEnvironment() {
    if (this.environment != null) {
        return this.environment;
    }
    switch (this.webApplicationType) {
        case SERVLET:
            return new StandardServletEnvironment();
        case REACTIVE:
            return new StandardReactiveWebEnvironment();
        default:
            return new StandardEnvironment();
    }
}

    根据之前断定的webApplicationType类型(run之前可以通过set方法进行修改),创建不同类型的Environment类型。

2、配置Environment(ConversionService、main方法传入的args参数、Profile)

protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
    if (this.addConversionService) {
        ConversionService conversionService = ApplicationConversionService.getSharedInstance();
        environment.setConversionService((ConfigurableConversionService) conversionService);
    }
    configurePropertySources(environment, args);
    configureProfiles(environment, args);
}

3、SpringApplicationRunListener的environmentPrepared回调

void environmentPrepared(ConfigurableEnvironment environment) {
    for (SpringApplicationRunListener listener : this.listeners) {
        listener.environmentPrepared(environment);
    }
}

4、自定义Environment

    如果是自定义Environment,则使用EnvironmentConverter进行处理。

 

二、反射创建ApplicationContext对象

protected ConfigurableApplicationContext createApplicationContext() {
    Class<?> contextClass = this.applicationContextClass;
    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) { // 省略部分代码  }
    }
    return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}

    与配置ConfigurableEnvironment 一样,根据webApplicationType通过反射创建ConfigurableApplicationContext 类型对象。

 

三、prepareContext

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
                            SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {

    // 为Spring容器设置初始化的环境
    context.setEnvironment(environment);

    // 为ConfigurableApplicationContext设置属性(bean名称生成器、Resource加载器和 
    // ConversionService)
    postProcessApplicationContext(context);
    // 回调ApplicationContextInitializer的initialize方法
    applyInitializers(context);
    // 回调SpringApplicationRunListener的contextPrepared方法
    listeners.contextPrepared(context);
    if (this.logStartupInfo) {
        logStartupInfo(context.getParent() == null);
        logStartupProfileInfo(context);
    }
    // Add boot specific singleton beans
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    // 将applicationArguments、Banner注册成单例Bean
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    if (printedBanner != null) {
        beanFactory.registerSingleton("springBootBanner", printedBanner);
    }
    if (beanFactory instanceof DefaultListableBeanFactory) {
        ((DefaultListableBeanFactory) beanFactory)
                .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    // 是否添加LazyInitializationBeanFactoryPostProcessor进行懒加载处理
    if (this.lazyInitialization) {
        context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
    }

    // 将sources注册BeanDefinition,没有特殊添加,则会将main注册BeanDefinition
    Set<Object> sources = getAllSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    load(context, sources.toArray(new Object[0]));

    // 回调SpringApplicationRunListener的contextLoaded方法
    listeners.contextLoaded(context);
}

1、为Spring容器设置初始化的环境

    context.setEnvironment(environment);

2、为ConfigurableApplicationContext设置属性

    默认bean名称生成器、Resource加载器为空,则不会进行设置。ConversionService则会设置ApplicationConversionService.sharedInstance单例对象。

3、回调ApplicationContextInitializerinitialize方法

    循环调用ApplicationContextInitializerinitialize初始化方法。

4、回调SpringApplicationRunListener的contextPrepared方法


5、将applicationArguments、Banner注册成单例Bean

    其Bean名称和Bean对象对应关系为(后续我们需要的时候可以通过getBean方法进行获取,使用):

springApplicationArguments
ApplicationArguments对象
springBootBanner
SpringBootBanner


6、是否添加LazyInitializationBeanFactoryPostProcessor进行懒加载处理

7、 将main类注册BeanDefinition

将sources注册BeanDefinition,没有特殊添加,则会将main注册BeanDefinition。个人理解,上面将不会再进行修改的applicationArguments等直接注册成Bean。而将可能通过BeanPostProcessor修改的main方法类,只是注册成BeanDefinition。

8、回调SpringApplicationRunListener的contextLoaded方法

 

©️2020 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值