springboot启动后加载某个类 springboot加载类的过程_初始化

1.    main方法里直接调用了  SpringApplication.run(DemoApplication.class, args);  方法,并传入了这个当前类的class对象和参数(外部传入进来的)

springboot启动后加载某个类 springboot加载类的过程_赋值_02

2.    这里使用了我们传入的class对象创建了一个springapplication对象,然后执行run方法,传入我们给定的参数。

springboot启动后加载某个类 springboot加载类的过程_springboot启动后加载某个类_03

       (1) 创建springapplication的时候主要的操作就是对其内部的属性进行了一些赋值。

springboot启动后加载某个类 springboot加载类的过程_springboot启动后加载某个类_04

                比如为这个resourceloader赋值,尽管传过来的值为null

 

springboot启动后加载某个类 springboot加载类的过程_spring_05

           为这个primarysources赋值,就是我们main方法中传过来的class对象

springboot启动后加载某个类 springboot加载类的过程_springboot启动后加载某个类_06

      为initializers属性赋值,这些类都继承 ApplicationContextInitializer,

springboot启动后加载某个类 springboot加载类的过程_spring_07

主要是在初始化applicationcontext的时候可以做一些工作,比如注册配置的属性资源,指定激活的profile等。

springboot启动后加载某个类 springboot加载类的过程_spring_08

设置完初始化器之后开始设置监听器,比如在applicationcontext启动或者关闭的时候可以监听到,处理一些事件

springboot启动后加载某个类 springboot加载类的过程_赋值_09

最后这是主类

springboot启动后加载某个类 springboot加载类的过程_springboot_10

主要是根据线程栈里获取到方法名为  main  的方法所在的那个class,就断定出他是主类。

 

到目前为止,一个springapplication就创建完成了,主要是对齐属性进行了赋值,接下来就会执行他的run方法了。

 

3.  执行springapplication的run方法

springboot启动后加载某个类 springboot加载类的过程_springboot_11

(1) run方法主要是运行springapplication的,创建并刷新一个applicationcontext

springboot启动后加载某个类 springboot加载类的过程_spring_12

springboot启动后加载某个类 springboot加载类的过程_springboot启动后加载某个类_13

stopwatch是用来记录一个任务启动或运行的时间,主要是包装的一个时间戳(  System.currentTimeMillis()  ),就是当前applicationcontext的开始启动时间,记录了下来,以及当前任务的名称。

springboot启动后加载某个类 springboot加载类的过程_spring_14

ConfigurableApplicationContext, 说明这个applicationcontext是可以配置的

springboot启动后加载某个类 springboot加载类的过程_spring_15

这个类继承了applicationcontext,可以对其设置一些属性,比如applicationlistener,environment,beanfactorypostprocessor(注意: 不是beanpostprocessor),shutdownhook等。

(对于异常报告 和 设置 headless属性就略过了,,没什么说的), 看一下 springapplicationrunlistener(不是springapplicationlistener)

springboot启动后加载某个类 springboot加载类的过程_赋值_16

这里只有一个listeners属性,,维护了listener的list,list中也只有一个listener,就是用来发布事件的。只要你写一个类实现ApplicationListener接口,,那么就会接收到通知。

springboot启动后加载某个类 springboot加载类的过程_赋值_17

listeners.starting();  触发监听器,说明springapplication要开始启动了

springboot启动后加载某个类 springboot加载类的过程_springboot_18

先是对我们传进来的参数进行了封装,形成了一个 DefaultApplicationArguments 对象,然后使用我们的这个DefaultApplicationArguments,和springapplicationrunlistener对初始化并预处理一个environment。

springboot启动后加载某个类 springboot加载类的过程_springboot启动后加载某个类_19

springboot启动后加载某个类 springboot加载类的过程_spring_20

这里配置一些要忽略的bean信息,也就是spring在ioc容器中不会创建和初始化他们。

紧接着打印banner

springboot启动后加载某个类 springboot加载类的过程_初始化_21

 

我们可以看到,控制台打印了。。。

 

说一下这个print方法

springboot启动后加载某个类 springboot加载类的过程_赋值_22

首先它判断了当前的bannermode,如果是off,,则不打印(我们可以通过配置来改变他的值),否则创建一个默认的resourceloader进行打印(我们刚开始第一步的时候说给springapplication的属性赋值也就是创建springapplication创建的时候这个属性值是null,并没有一开始都初始化了)

 

这里就开始创建了applicationcontext了

springboot启动后加载某个类 springboot加载类的过程_初始化_23

这里主要是根据 webApplicationType 的值来创建。这个值也是在创建applicationcontext的时候就赋值好了(在上面的图中可以看到),通过  deduceWebApplicationType() 方法赋值的。

springboot启动后加载某个类 springboot加载类的过程_springboot_24

主要是看你当前的classpath下有哪个类,spring就会推断出你当前的应用是什么类型的应用

springboot启动后加载某个类 springboot加载类的过程_赋值_25

springboot启动后加载某个类 springboot加载类的过程_spring_26

springboot启动后加载某个类 springboot加载类的过程_初始化_27

springboot启动后加载某个类 springboot加载类的过程_赋值_28

最终我这个项目

springboot启动后加载某个类 springboot加载类的过程_springboot_29

也就是会实例化一个

springboot启动后加载某个类 springboot加载类的过程_springboot启动后加载某个类_30

至此,ConfigurableApplicationContext 创建完毕

exceptionreport也不说了,是这个样子

springboot启动后加载某个类 springboot加载类的过程_springboot启动后加载某个类_31

就是程序启动过程中哪里出错了都会有一些推断,或者分析,以便于定位原因(spring的功能还是很完善啊。。。)

创建applicationcontext完成之后就得对他进行一些初始化工作,,或者说预处理工作(代码给的是 prepare)

private void prepareContext(ConfigurableApplicationContext context,
      ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
      ApplicationArguments applicationArguments, Banner printedBanner) {
# 这里将之前创建的environment赋值给applicationcontext,environment主要记录一些属性文件,激活哪个profile等信息
   context.setEnvironment(environment);
#  这个下面说
   postProcessApplicationContext(context);
#  这里主要是调用所有的 ApplicationContextInitializer 的 initialize方法。这些ApplicationContextInitializer 在创建springapplication的时候已经赋值好了,这里在applicationcontext初始化的时候拿来调用了
   applyInitializers(context);
# listener 也是一样,在springapplication创建的时候赋值好,这里调用,触发其方法
   listeners.contextPrepared(context);

#  日志打印的一些功能。。。
   if (this.logStartupInfo) {
      logStartupInfo(context.getParent() == null);
      logStartupProfileInfo(context);
   }

#  这里先往内部的beanfactory中注册一些必要的单例的bean,applicationArguments,printedBanner,既然这个时候注入了beanfactory中,,那么我们程序代码里也可以获取到(通过autowire注解等)
   // Add boot specific singleton beans
   context.getBeanFactory().registerSingleton("springApplicationArguments",
         applicationArguments);
   if (printedBanner != null) {
      context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
   }

   // Load the sources
   Set<Object> sources = getAllSources();
   Assert.notEmpty(sources, "Sources must not be empty");
#  这个sources 就是我们的主类
   load(context, sources.toArray(new Object[0]));
#  触发监听器,,applicationcontext加载完成了
   listeners.contextLoaded(context);
}

 

说一下这个  postProcessApplicationContext

springboot启动后加载某个类 springboot加载类的过程_赋值_32

这里向beanfactor中注入了一个单例的bean ("org.springframework.context.annotation.internalConfigurationBeanNameGenerator")用来对bean生成其对应的name,通常是class的第一个首字母小写来作为他的名字。。

 

springboot启动后加载某个类 springboot加载类的过程_springboot启动后加载某个类_33

这里控制台打印了一些信息,显示了触发默认的profile,就是在applicationcontext的prepare阶段完成的。

springboot启动后加载某个类 springboot加载类的过程_赋值_34

作完了一些预处理工作,下面就开始执行refresh方法了。这里的东西以后再说,太多了。。。

springboot启动后加载某个类 springboot加载类的过程_spring_35

这个方法执行之后,所有的单实例的,不是lazy加载的bean都已经创建并初始化好了。。我们自己写的程序也运行起来了(我这里用的undertow服务器)

springboot启动后加载某个类 springboot加载类的过程_springboot_36

这里会打印出程序运行后的日志信息

springboot启动后加载某个类 springboot加载类的过程_赋值_37

(我中间debug的时候有点长啊。。。。)

 

之后stopwatch.stop(),整个springcontext或者说springapplication就正式运行起来了

 

springboot启动后加载某个类 springboot加载类的过程_赋值_38

这一步就是令监听器触发applicationcontext完成的方法。

可以说监听器在springapplication的生命周期的各个阶段都在发挥着作用。

springboot启动后加载某个类 springboot加载类的过程_赋值_39

callrunner就是你从命令行输入的参数或运行程序时传递的参数都会被传送到这里进行处理。。

 

springboot启动后加载某个类 springboot加载类的过程_springboot_40

再之后,,触发监听器的运行方法。。。表示applicationcontext正在运行中

 

springboot启动后加载某个类 springboot加载类的过程_spring_41

 

springboot启动后加载某个类 springboot加载类的过程_赋值_42

最后返回到了这个最初的方法,启动结束,我们的项目运行起来了。。(走了一大遭)

 

 

 

 

最后补充一下

springboot启动后加载某个类 springboot加载类的过程_赋值_43

最后我们可以拿到我们的applicationcontext,来通过代码关闭它,这样应用程序就结束啦。