springboot启动解析九

本章节继续分析run方法的第16-22行代码:

public ConfigurableApplicationContext run(String... args) {
        1.StopWatch stopWatch = new StopWatch();
        2.stopWatch.start();
        3.ConfigurableApplicationContext context = null;
        4.Collection exceptionReporters = new ArrayList<>();
        5.configureHeadlessProperty();
        6.SpringApplicationRunListeners listeners = getRunListeners(args);
        7.listeners.starting();
        try {
        8.  ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
        9.  ConfigurableEnvironment environment = prepareEnvironment(listeners,
                    applicationArguments);
        10. configureIgnoreBeanInfo(environment);
        11. Banner printedBanner = printBanner(environment);
        12. context = createApplicationContext();
        13. exceptionReporters = getSpringFactoriesInstances(
                SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
        14.     prepareContext(context, environment, listeners, applicationArguments,
                    printedBanner);
        15. refreshContext(context);
        16. afterRefresh(context, applicationArguments);
        17. stopWatch.stop();
        18. if (this.logStartupInfo) {
        19.     new StartupInfoLogger(this.mainApplicationClass)
                        .logStarted(getApplicationLog(), stopWatch);
            }
        20. listeners.started(context);
        21. callRunners(context, applicationArguments);
        }
        catch (Throwable ex) {
        22. handleRunFailure(context, ex, exceptionReporters, listeners);
            throw new IllegalStateException(ex);
        }

        try {
        23. listeners.running(context);
        }
        catch (Throwable ex) {
        24. handleRunFailure(context, ex, exceptionReporters, null);
            throw new IllegalStateException(ex);
        }
        return context;
    }

16行目前为空的实现

17行就是记录执行的任务的耗时

20行 就是发布ApplicationStartedEvent事件

21行 获取ApplicationRunner和CommandLineRunner 然后执行run方法

23 行就是发布ApplicationReadyEvent事件

至此springboot启动解析都写完了 这是我写的第一个系列文章,说实话 我这些真的是皮毛 好多更深入的内容我并没有解析,这是之后我本人会细细研究的。后期也会将研究成果写出来


spring容器初始化所有非懒加载单例bean逻辑

初始化剩余的非懒加载的单例
1.首先初始化所有单例非懒加载
1.1 获取MergedLocalBeanDefinition,然后判断MergedLocalBeanDefinition是否属于单例 非懒加载 非抽象类
1.1.1 MergedLocalBeanDefinition就是先根据beanName获取原生的beanDefinition,然后根据获取原生的beanDefinition的
beanDefinition,然后设置父类的相关属性到子类的beanDefinition
1.2首先判断是否是factoryBean,如果不是则直接采用该beanName去获取bean
1.3如果是获取factoryBean,则修改beanName,然后获取factorybean,这个时候我们要查看其是否isEagerInit
如果是 则获取其getObject的对象
1.4整个getBean的流程如下:
1.4.1:获取正确的beanName
1.4.2从1,2,3个缓存获取单例对象
1.4.3如果对象存在则根据原生的beanName返回实例本身还是factoryBean的getObject
1.4.4 检测是否是prototype类型bean存在重复调用,然后尝试让父类容器去生成bean
1.4.5如果上述都ok了则在typeCheckOnly情况下markBeanAsCreated,也就是说删除该mergedBeanDefinitions中的BeanDefinition,且将将要生成bean的BeanName加入到alreadyCreated,对于非单例来说,他每次都需要重新mergerBeanDefinition
1.4.6 获取mergerBeanDefinition,检测是否为抽象类,然后获取其dependOn的beanName,优先加载他们
1.4.7 然后根据单例,原型,scope三种方式创建bean的实例,然后检测获取的bean的class类型是否为我们需要的class
如果不是的话则尝试更改,更改失败则抛出异常
1.4.8对于socpe 其是先检测该bean是否已经存在对应的区域中了(比如servletcontext,或者session)
如果没有,则才调用objectFactory去创建,而objectFactory中会通过threadlocal来避免单个线程重复生成bean
1.4.9 对于原型,其是也是通过threadlocal来避免单个线程重复生成bean
1.4.10 对于单例其是通过set和锁来避免生成多个bean
2.调用所有单例的自己的afterSingletonsInstantiated ,其需要我们的bean实现SmartInitializingSingleton

bean加载的过程

1.1获取实例化的class resolvedClass
1.2 处理需要替换的method(look-up和replace-method)
1.3 在spring按照自己逻辑生成bean实例并初始化bean之前,调用resolveBeforeInstantiation
该方法会先调用实例化前的方法,如果获取到bean了,那么说明我不需要按照spring的逻辑生成bean
直接调用初始化之后的方法BeanPostProcessorsAfterInitialization
1.4 如果上述没有获取到bean则下面就是真正的实例化,和初始化方法(只要调用实例化之后的方法,初始化前后的方法)
1.5 spring自己生成bean的方式是先获取factoryBean调用getObject的缓存
1.6 如果获取失败 则尝试自己创建bean
1.6.1:按照Supplier,factory-method,获取构造函数(可以通过@Autowired指定)
1.7 处理MergedBeanDefinitionPostProcessors
1.8 是否支持单例循环依赖注入,如果支持则将我们的bean包装成ObjectFactory,并将其存入
singletonFactories,当我们需要获取单例是否存在时候,可以通过spring的扩展点SmartInstantiationAwareBeanPostProcessor,调用其getEarlyBeanReference方法
1.9 然后调用populateBean,其主要是调用实例化之后的方法,以及设置bean的属性,其中postProcessPropertyValues
是用来对即将要注入的属性进行处理 比如@Required
1.10 initializeBean是用来调用初始化前后的方法以及初始化方法
1.11 注册disposable方法

你可能感兴趣的:(springboot启动解析九)