参考视频:

https://www.ixigua.com/7090148232243708446?wid_try=1

public class SpringApplication {......单参数构造方法public SpringApplication(Class... primarySources) {调用双参构造方法this((ResourceLoader)null, primarySources);}双参数构造方法public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {这个构造函数相当于初始化各种属性参数等操作.......在1.0之前这个构造函数是作为init方法存在.........this.sources = new LinkedHashSet();this.bannerMode = Mode.CONSOLE;this.logStartupInfo = true;this.addCommandLineProperties = true;this.addConversionService = true;this.headless = true;this.registerShutdownHook = true;this.additionalProfiles = Collections.emptySet();this.isCustomEnvironment = false;this.lazyInitialization = false;this.applicationContextFactory = ApplicationContextFactory.DEFAULT;this.applicationStartup = ApplicationStartup.DEFAULT;this.resourceLoader = resourceLoader;断言你传过来的字节码文件不能为空,如果为空就给你打印后面这句话Assert.notNull(primarySources, "PrimarySources must not be null");this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));this.webApplicationType = WebApplicationType.deduceFromClasspath();this.bootstrapRegistryInitializers = this.getBootstrapRegistryInitializersFromSpringFactories();this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));this.mainApplicationClass = this.deduceMainApplicationClass();}......run方法public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {生成一个新的数组,数组里存的是Class类型,这些class从哪来,从字节码文件中来。return run(new Class[]{primarySource}, args);}......另一个run方法public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {这里调用了SpringApplication的第一个构造函数return (new SpringApplication(primarySources)).run(args);}......另另一个run方法public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();stopWatch.start();springboot当中用到的最早的一个配置文件类型,它优先加载于application.propertiesDefaultBootstrapContext bootstrapContext = this.createBootstrapContext();ConfigurableApplicationContext context = null;this.configureHeadlessProperty();SpringApplicationRunListeners listeners = this.getRunListeners(args);listeners.starting(bootstrapContext, this.mainApplicationClass);try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);加载环境变量,运行起来控制台会输出类似的Starting Application using Java 1.8.0_131 on PC-202032 with PID 5060(D://.......)ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);this.configureIgnoreBeanInfo(environment);控制台打印的花式文字Banner printedBanner = this.printBanner(environment);创建了spring的核心容器context = this.createApplicationContext();让你的核心容器跑起来context.setApplicationStartup(this.applicationStartup);预处理this.prepareContext(bootstrapContext, 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, listeners);throw new IllegalStateException(var10);}try {listeners.running(context);return context;} catch (Throwable var9) {this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null);throw new IllegalStateException(var9);}}}
@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {// 调用了当前类下的另一个run方法return run(new Class[]{primarySource}, args);
}public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {// 在当前类下的另一个run方法中 调用了当前类的单参构造方法return (new SpringApplication(primarySources)).run(args);
}public SpringApplication(Class... primarySources) {// 单参构造方法中,又去调用了双参构造方法this((ResourceLoader)null, primarySources);
}
// 在双参构造方法中有这么一个ApplicationContextFactory
this.applicationContextFactory = ApplicationContextFactory.DEFAULT;

public class StopWatch {
        ......public void start(String taskName) throws IllegalStateException {if (this.currentTaskName != null) {throw new IllegalStateException("Can't start StopWatch: it's already running");} else {this.currentTaskName = taskName;this.startTimeNanos = System.nanoTime();}}}

它这个run要这个类的字节码有什么用呢? 它这个类上面的注解@SpringBootApplication

SpringUtils中的setApplicationContext到底什么时候被执行了?今天我们研究一下。

参考链接:ApplicationContextAware接口的setApplicationContext方法调用过程_大家说的博客-CSDN博客_setapplicationcontext方法


@Component
public class SpringUtils implements ApplicationContextAware {.........private ApplicationContext applicationContext;private BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition();private DefaultListableBeanFactory autowireCapableBeanFactory;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {if (this.applicationContext == null) {this.applicationContext = applicationContext;}}......
}

SpringApplication.java:

public class SpringApplication {....../*** Refresh the underlying {@link ApplicationContext}.* @param applicationContext the application context to refresh*/protected void refresh(ConfigurableApplicationContext applicationContext) {applicationContext.refresh();}......
}

点击refresh进入ConfigurableApplicationContext 接口

public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {........void refresh() throws BeansException, IllegalStateException;........
}

点击抽象方法refresh() ,进入实现类AbstractApplicationContext.java

在refresh()方法中 点击this.prepareBeanFactory(beanFactory);// 点击进入查看prepareBeanFactory()

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {......public void refresh() throws BeansException, IllegalStateException {Object var1 = this.startupShutdownMonitor;synchronized(this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");this.prepareRefresh();ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();1这里---->this.prepareBeanFactory(beanFactory);//---->beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));---->ApplicationContextAwareProcessor.javatry {this.postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");this.invokeBeanFactoryPostProcessors(beanFactory);this.registerBeanPostProcessors(beanFactory);beanPostProcess.end();this.initMessageSource();this.initApplicationEventMulticaster();this.onRefresh();this.registerListeners();4这里---->this.finishBeanFactoryInitialization(beanFactory);this.finishRefresh();} catch (BeansException var10) {if (this.logger.isWarnEnabled()) {this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);}this.destroyBeans();this.cancelRefresh(var10);throw var10;} finally {this.resetCommonCaches();contextRefresh.end();}}}.........protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {beanFactory.setBeanClassLoader(this.getClassLoader());if (!shouldIgnoreSpel) {beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));}beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
2这里---->beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
3这里---->ApplicationContextAwareProcessor.javabeanFactory.ignoreDependencyInterface(EnvironmentAware.class);beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);beanFactory.ignoreDependencyInterface(MessageSourceAware.class);beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));if (!NativeDetector.inNativeImage() && beanFactory.containsBean("loadTimeWeaver")) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}if (!beanFactory.containsLocalBean("environment")) {beanFactory.registerSingleton("environment", this.getEnvironment());}if (!beanFactory.containsLocalBean("systemProperties")) {beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());}if (!beanFactory.containsLocalBean("systemEnvironment")) {beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());}if (!beanFactory.containsLocalBean("applicationStartup")) {beanFactory.registerSingleton("applicationStartup", this.getApplicationStartup());}}........
5这里---->protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));}if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver((strVal) -> {return this.getEnvironment().resolvePlaceholders(strVal);});}String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);String[] var3 = weaverAwareNames;int var4 = weaverAwareNames.length;for(int var5 = 0; var5 < var4; ++var5) {String weaverAwareName = var3[var5];this.getBean(weaverAwareName);}beanFactory.setTempClassLoader((ClassLoader)null);beanFactory.freezeConfiguration();
6这里---->beanFactory.preInstantiateSingletons();}....
}

在AbstractApplicationContext .java的refresh()的prepareBeanFactory()中查看:beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

我们看到一个new ApplicationContextAwareProcessor(this)类,这个类是一个BeanPostProcessor类型的类。OK,我们先在这里有一个印象,就是在BeanFactory里面加入了一个 ApplicationContextAwareProcessor。
这个过程就是ApplicationContextAwareProcessor的装配过程。

---------------------------------------------------------------------------

AbstractApplicationContext.java的refresh()方法中继续往下执行,执行到AbstractApplicationContext .java的实例化bean的方法
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
代码执行到这个方法。

  • protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)

在AbstractApplicationContext.java的finishBeanFactoryInitialization()方法中:

会执行beanFactory.preInstantiateSingletons();

最终会执行到:

  • AbstractAutowireCapableBeanFactory#doCreateBean方法

方法当中:

Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
        }

点进去

这个方法就是调用 ApplicationContextAwareProcessor的地方,我们进去看看。

我们可以看到,确实在BeanPostProcessors容器中有一个ApplicationContextAwareProcessor类。那么我们进到ApplicationContextAwareProcessor这个类的postProcessBeforeInitialization方法中。

 根据这个源码,我们知道了,确实调用到了setApplicationContext()方法。

SpringApplication的启动过程相关推荐

  1. Spring Boot启动过程(二)

    书接上篇 该说refreshContext(context)了,首先是判断context是否是AbstractApplicationContext派生类的实例,之后调用了强转为AbstractAppl ...

  2. springboot启动过程_不要搞笑哈,你用了5年的SpringBoot框架,竟然不了解它的启动过程?...

    SpringBoot的启动很简单,代码如下: @SpringBootApplicationpublic class MyApplication { public static void main(St ...

  3. SpringBoot启动过程详解

    Spring Boot通常有一个名为*Application的入口类,在入口类里有一个main方法,这个main方法其实就是一个标准的java应用的入口方法. 在main方法中使用SpringAppl ...

  4. SpringBoot 应用程序启动过程探秘

    本文共 946字,阅读大约需要 3分钟 ! 概述 说到接触 SpringBoot 伊始,给我第一映像最深的是有两个关键元素: 对照上面的典型代码,这个两个元素分别是: @SpringBootAppli ...

  5. springboot启动过程_spring5/springboot2源码学习 -- spring boot 应用的启动过程

    推荐阅读: Spring全家桶笔记:Spring+Spring Boot+Spring Cloud+Spring MVC 疫情期间"闭关修炼",吃透这本Java核心知识,跳槽面试不 ...

  6. SpringBoot系列之(三):启动过程

    #.前言 不得不说我们的SpringBoot给Java开发人员带来了很多的便利之处.比如:不用再配置一些的xml文件了:加载程序的容器也帮我们嵌套在代码里了:Web的中心控制器入口也自动写在了代码里: ...

  7. springboot 应用:异常管理,应用启动过程,应用监控 Prometheus 和 Grafana

    异常管理 springboot 应用中默认的全局异常处理类是 BasicErrorController,内部判断 accept 如果是 text/html 则返回 /error 路径的模板:如果是 a ...

  8. [Spring Boot] 2. Spring Boot 启动过程定制化

    在上一篇文章中,从源码角度介绍了Spring Boot的启动过程.启动的代码虽然只有短短的一行,但是背后所做的工作还真不少,其中有一些可以定制化的部分,主要分为以下几个方面: 初始化器(Initial ...

  9. 通过helloworld程序分析springboot的jar包启动过程

    写在前面 源码这里.本文分析的是通过java -jarjar包方式启动,关于直接运行main函数启动过程可以参考这里. 1:创建helloworld程序 1.1:创建maven项目 file-> ...

最新文章

  1. try catch finally
  2. EasyUI环境搭建与入门基础语法
  3. Spring Boot完成示例
  4. emplace_back和push_back区别
  5. 图匠数据等提出高精度零售货架姿态估计算法GSPN
  6. android开发板功能,Android中NFC模块PN532开发板应用/原理图/PCB等全部资料
  7. 一张图图片分块html,css img图片是内联还是块?
  8. 一个程序让你学会C++构造函数与重载构造、析构函数【C++类的经典使用案例】
  9. 如何设置myeclipse的编码格式
  10. 扫二维码缴违章停车罚款?骗你的!
  11. Python2.5.4移植到arm-linux
  12. 图像处理八:前向映射和后向映射
  13. python 身份证识别器_python 识别身份证号码
  14. python使用ip地址定位_python实现ip地址查询经纬度定位详解
  15. MySQL said: Authentication plugin 'caching_sha2_password' cannot be loaded...
  16. 0XU天气上线 从纯粹的网址导航我们正在造纯粹的工具集
  17. LLC谐振变换器的寄生参数对谐振过程影响分析
  18. 【数据分析】基于新闻文本数据分析
  19. MySQL NDB Cluster部署方案与实践
  20. Flowable初始化失败 Table ‘xxxx‘ already exist

热门文章

  1. 2019CAD设置经典模式模板详细步骤
  2. 动态磁盘无损转化为基本磁盘
  3. 微软服务器的根目录在哪里,如何:查找 Web 应用程序根目录
  4. 学习Python难度高吗?零基础可以学习吗?
  5. pscp 项目上传中文文件乱码问题
  6. 合理利用博客群发软件,提升网站权重的关键方法
  7. CDFShop: Exploring and Optimizing Learned Index Structures(SIGMOD21)
  8. Samba服务及多用户samba挂载
  9. 阿里Java面试必问:java爬虫框架使用排行
  10. 用javaweb连接数据库用javabean、severlet实现增删改查