Springboot启动流程分析五 this.prepareContext

前面说完了context = this.createApplicationContext()过程,接下来我们说下this.prepareContext,但其实在这一步之前,还有一步spring boot的异常上报处理,还是先给个总源码,要讲的俩步标号5,6:

public ConfigurableApplicationContext run(String... args) {
   
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
        this.configureHeadlessProperty();
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting();

        Collection exceptionReporters;
        try {
   
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            Banner printedBanner = this.printBanner(environment);
            context = this.createApplicationContext();
           5、 exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{
   ConfigurableApplicationContext.class}, context);
           6this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
   
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            listeners.started(context);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
   
            this.handleRunFailure(context, var10, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }

        try {
   
            listeners.running(context);
            return context;
        } catch (Throwable var9) {
   
            this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }

先说异常处理,在spring .factoreis查看该定义如下在这里插入图片描述
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);进入方法查看:

//这里从META-INF/spring.factories中获取并初始化SpringBootExceptionReporter子类列表
//获取到一个FailureAnalyzers实例
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
   
        ClassLoader classLoader = this.getClassLoader();
        Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }

FailureAnalyzers类源码

//异常失败原因分析器
final class FailureAnalyzers implements SpringBootExceptionReporter {
   

    //失败分析器
    private final List<FailureAnalyzer> analyzers;

    //构造函数
    FailureAnalyzers(ConfigurableApplicationContext context, ClassLoader classLoader) {
   
        Assert.notNull(context, "Context must not be null");
        this.classLoader = (classLoader != null) ? classLoader : context.getClassLoader();
        //加载失败分析器列表
        this.analyzers = loadFailureAnalyzers(this.classLoader);
        //准备分析异常原因
        prepareFailureAnalyzers(this.analyzers, context);
    }

    //加载异常分析器
    private List<FailureAnalyzer> loadFailureAnalyzers(ClassLoader classLoader) {
   
       //通过META-INF/spring.factories中,获取到FailureAnalyzer的子类列表如下
        //BeanCurrentlyInCreationFailureAnalyzer,
        //BeanDefinitionOverrideFailureAnalyzer,
        //BeanNotOfRequiredTypeFailureAnalyzer,
        //BindFailureAnalyzer,
        //BindValidationFailureAnalyzer,
        //UnboundConfigurationPropertyFailureAnalyzer,
        //ConnectorStartFailureAnalyzer,
        //NoSuchMethodFailureAnalyzer,
        //NoUniqueBeanDefinitionFailureAnalyzer,
        //PortInUseFailureAnalyzer,
        //ValidationExceptionFailureAnalyzer,
        //InvalidConfigurationPropertyNameFailureAnalyzer,
        //InvalidConfigurationPropertyValueFailureAnalyzer,
        //NoSuchBeanDefinitionFailureAnalyzer,
        //DataSourceBeanCreationFailureAnalyzer,
        //ikariDriverConfigurationFailureAnalyzer,
        //NonUniqueSessionRepositoryFailureAnalyzer
        List<String> analyzerNames = SpringFactoriesLoader
                .loadFactoryNames(FailureAnalyzer.class, classLoader);
        List<FailureAnalyzer> analyzers = new ArrayList<>();
        for (String analyzerName : analyzerNames) {
   
            try {
   
                Constructor<?> constructor = ClassUtils.forName(analyzerName, classLoader)
                        .getDeclaredConstructor();
                ReflectionUtils.makeAccessible(constructor);
                analyzers.add((FailureAnalyzer) constructor.newInstance());
            }
            catch (Throwable ex) {
   
                logger.trace("Failed to load " + analyzerName, ex);
            }
        }
        AnnotationAwareOrderComparator.sort(analyzers);
        return analyzers;
    }
}

说完异常分析,进入主题:

6、this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);

直接进入方法:

 private void prepareContext(ConfigurableApplicationContext context,
            ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
            ApplicationArguments applicationArguments, Banner printedBanner) {
   
        //设置context(上下文)环境
        //统一ApplicationContext和Application,使用Application的environment
        context.setEnvironment(environment);
        //ApplicationContext的后置处理
        postProcessApplicationContext(context);
        //执行Initializers
        applyInitializers(context);
        //发布contextPrepared事件
        listeners.contextPrepared(context);
        if (this.logStartupInfo) {
   
            //配置了info日志
            //打印启动和profile日志
            logStartupInfo(context.getParent() == null);
            logStartupProfileInfo(context);
        }
        //获取到DefaultListableBeanFactory实例
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //注册名为springApplicationArguments,值为applicationArguments的单例bean
        beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
        //banner不为空,那么注册名为springBootBanner,值为printedBanner的单例bean
        if (printedBanner != null) {
   
            beanFactory.registerSingleton("springBootBanner", printedBanner);
        }
        if (beanFactory instanceof DefaultListableBeanFactory) {
   
            //allowBeanDefinitionOverriding默认为false
            ((DefaultListableBeanFactory) beanFactory)
                    .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        // 获取sources列表,获取到我们的YanggxApplication.class
        Set<Object> sources = getAllSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        //初始化bean加载器,并加载bean到应用上下文
        load(context, sources.toArray(new Object[0]));
        //发布contextLoaded事件
        listeners.contextLoaded(context);
    }
}

1、context.setEnvironment(environment);,统一ApplicationContext和Application使用的environment
配置ApplicationContext和Application的environment成员变量, 使用Application的environment, AnnotationConfigServletWebServerApplicationContext的bean定读取器reader和bean扫描器scanner都使用Application的environment

点击实现类,其所有实现该方法的context父类都将设置environment
在这里插入图片描述
以最终AnnotationConfigServletWebServerApplicationContext为例:

public class AnnotationConfigServletWebServerApplicationContext
        extends ServletWebServerApplicationContext implements AnnotationConfigRegistry {
   
    @Override
    public void setEnvironment(ConfigurableEnvironment environment) {
   
        //显式调用父类AbstractApplicationContext的setEnvironment方法
        super.setEnvironment(environment);
        //调用AnnotatedBeanDefinitionReader#setEnvironment()方法
        this.reader.setEnvironment(environment);
        
        //ClassPathBeanDefinitionScanner继承了ClassPathScanningCandidateComponentProvider,所以调用了父类setEnvironment方法
        this.scanner.setEnvironment(environment);
    }
}

super.setEnvironment(environment)显式调用父类AbstractApplicationContext的setEnvironment方法,多个父类依次调用。

2、postProcessApplicationContext
ApplicationContext的后置处理
执行了以下三步
1、设置ApplicationContext的beanNameGenerator
2、设置ApplicationContext的resourceLoader和classLoader
3、设置ApplicationContext的类型转换Service

protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
   
        //没有设置beanNameGenerator,默认为null
        if (this.beanNameGenerator != null) {
   
            //如果beanNameGenerator不为空
            //那么注册一个名为internalConfigurationBeanNameGenerator
            //值为beanNameGenerator的单例bean
            context.getBeanFactory().registerSingleton(
                    AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
                    this.beanNameGenerator);
        }
        //没有设置resourceLoader,默认为null
        if (this.resourceLoader != null) {
   
            //如果resourceLoader不为空
            if (context instanceof GenericApplicationContext) {
   
                //context是GenericApplicationContext子类
                //那么设置上下文context的resourceLoader
                ((GenericApplicationContext) context)
                        .setResourceLoader(this.resourceLoader);
            }
            if (context instanceof DefaultResourceLoader) {
   
                //如果当前上下文是DefaultResourceLoader的子类
                //那么设置上下文context的classLoader
                ((DefaultResourceLoader) context
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值