图1
spring boot的启动 两种启动方式。
图2
这个注解类很重要,下次讲。
图3
图4
图5
图6
图7
注意spring 传的resourceLoader为null ,270行推断webApplicationType的类型。推断出来这个servlet; 273行,获取所有ApplicationListener为key的 和ApplicationContextInitializer一样。图27,28 274行推断main方法的主类。图29
图8
这个项目是一个web项目。
图9
推断webApplicationType的类型。ClassUtils.isPresent判断这个类是否存在。 那问题来了返回REACTIVE 是什么,reactive什么类型(webflux 响应式编程),orcle收购了sun公司,他慢慢在收费,spring 的生态依赖javaee 。而webflux 不能运行在tomcat,而是在reactive容器上运行。spring 不确定将来的javaee发展到什么情况,如果有一天servlet被淘汰,spring框架还用这种servlet也将会面临淘汰。所以spring 5就有了一个新特性,支持webflux的 recactive容器。支持这种容器但是我们并不一定要用,所以要推断。
图19
图20
图21
图22
119行 loadSpringFactories 这行代码相当于返回对应key 所有值,aaa,bbb,cccc,ddddd 参看图25
图23
先从缓存中获取,获取到返回。 从spirng.factories的配置文件中,拿出所有的url路径,遍历,转化为Properties. 把properties中的属性变成对象。有一个key对应多个value, 遍历所有的value 放在一个map中返回。(key,values)
图24
图25
图26
从配置文件读取key为ApplicationContextInitializer 的所有value 并放在initializers的list中。
图27
所有springboot中为10个
图28
图29
这种情况下怎么推断主类,假如有一个内部类。
图30
spring boot采取的方法是,抛出一个异常,遍历异常的栈,看看这个栈里的方法那个包含main包含即为启动类,主类。
到这个new SpringApplication已经看完了,看run方法。
图31
stopWatch 不用管,记录的启动时间。configureHeadlessProperty() 对band的一些设置不重要。318行图33 EventPublishingRunListener
图33-0 319行执行代码 ;323行又回发布一个事件,图
图32
banner的一些设置。
图33
图33-0
图34
把
最开始获取的那10个监听器依次添加到广播器中。
starting方法,是我们springboot 启动的时候发布一个事件,这个事件是容器该启动的一个事件。当我们要加载一个配置文件的时候,environmentPrepared 环境变量什么的都构建完之后,也要发一个事件。当我们的上下文准备好之后也要发一个事件。当上下文需要load一个bean的时候也要发一个事件。当我们上下文需要启动的时候也需要发一个事件。 当我们上下文失败,或者正在跑都会发送一个事件。
图35
注意这个SimpleApplicationEventMulticaster 是spring类。
图36
先了解一下怎么发布事件
图37
我们发送一个事件的时候,会把这个时间放到广播器里面,然后把这个event事件给第一个listener 看他感兴趣吗,不感兴趣给第二个listener,第二个不感兴趣给第三个, 第三个感兴趣的话执行这个事件。那我们怎么知道这个listener是不是感兴趣呢,这个就是订阅
那如何订阅呢,
图38
当我们springboot 程序,启动的时候,会发布一个事件,这个事件springboot抽象出来一个类为ApplicationStartingEvent来描述。但是这个启动的事件,监听器是否感兴趣呢,把事件给了广播器,
图39
拿到所有的监听器,依次执行。
图39-0
图39-1
图39-2
为什么要实现GenericApplicationListener , 如果不实现这个是没有任何意义的, 如果强转为GenericApplicationListenerAdapeter 没有任何意义了。
图40
ResolvableType是对event事件的一种包装。 ResolvableType 是一个类,event是一个对象。 对应的这个event的事件类型是什么,图41
ApplicationStartingEvent
图41
图42
图43
图44
监听器执行对应的事件。
举例说明上面的
图45
自己健一个配置类。
supportsEventType 是指对什么事件感兴趣,如果返回true表示对任何事件都感兴趣。
图46
打印了好多次证明有好多监听对这个事件感兴趣。
图47
再看spirngboot中的例子,
两处订阅,第一次 supportsEventType() 还有一个是 supportsSourceType() .因为是&& 的关系。
还有就是在执行的时候,我也可以订阅。
loggingApplicationListener 只要订阅了这几个类型的事件,只要包含这几个类型,就表示感兴趣,这个监听器就会执行。
如何发布一个事件,不就是广播一个事件呗。
加一个广告
图48
这种方式也可以创建一个bean但是没有太大的意义。 没有那一个业务类是单独存在的,添加到spirng中是和其他的类是有依赖的。
图50
广播了一个事件; ApplicationEnvironmentproparpar这个事件的作用是控制配置文件的同属性覆盖。到底谁覆盖谁,图51
图51
resources 下的application.yml port:9098 ; config application.yml 的端口是9089 那么config 的 9099 会覆盖9098