前言:
此刻大家对“观察者模式spring”大概比较注重,大家都需要知道一些“观察者模式spring”的相关文章。那么小编在网上搜集了一些对于“观察者模式spring””的相关内容,希望你们能喜欢,各位老铁们快快来学习一下吧!观察者模式直白解释:可理解为订阅和通知的过程,即订阅者(或者监听者、观察者)向注册和通知中心注册自己以及关注的事件,发布者(或者被观察者、通知者)向注册和通知中心发布事件消息,委托注册和通知中心向关注了该事件的观察者发布通知。通过注册和通知中心解耦了观察者和发布者,观察者不需要关心发布者是谁,只需关注自己对什么感兴趣;发布者不需关心观察者是谁,只需关注自己及时的发布通知。相关类图不再赘述,网上有很多,下图是观察者模式的交互方式,旨在便于理解。
Spring中的事件编程模型就是观察者设计模式的实现,SpringBoot正是利用了Spring的事件编程模型来实现了Application启动过程中的相关事件的广播。
Spring中观察者模式核心类如下:
ApplicationListener:应用监听者,即观察者,继承了JDK中EventListener,当监听的事件发生后,该类中唯一方法onApplication会被回调;ApplicationEvent:事件抽象类,继承自JDK的EventObject,Spring及SpringBoot中所有事件都是该类的子类;ApplicationEventMulticaster:事件注册和广播中心,用于事件监听器的注册和事件的广播;ApplicationContext:Spring的IOC容器,同时也是发布者,因为ApplicationContext继承了ApplicationEventPublisher,通过publishEvent(Object event)方法发布事件。
分析SpringBoot的启动过程会发现,大量的代码都是在做事件通知和扩展点设置,他们近乎喧宾夺主,占据了SpringBoot启动过程的大半江山,抛去这些扩展点,剩下的核心逻辑无非只是初始化并准备ApplicationContext容器了。关于SpringBoot的启动过程和其他扩展点解析,笔者会在后续发文中逐一解析,现在暂且关注事件模型。
SpringBoot启动核心代码,其中注释标注出了事件通知代码
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); configureHeadlessProperty(); //向注册和通知中心注册SpringBoot监听者,并返回注册和通知中心实例 SpringApplicationRunListeners listeners = getRunListeners(args); //向注册和通知中心发布应用正在启动的事件通知 listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); //准备配置环境,并向通知和注册中心发布环境准备好了的事件通知 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); Banner printedBanner = printBanner(environment); context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances( SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } //向通知和注册中心发布应用启动启动完毕的事件通知 listeners.started(context); callRunners(context, applicationArguments); } catch (Throwable ex) { //处理运行失败异常,并向通知和注册中心发布应用启动失败事件通知 handleRunFailure(context, listeners, exceptionReporters, ex); throw new IllegalStateException(ex); } //向通知和注册中心发布引用正在运行的事件通知 listeners.running(context); return context; }
其中getRunListeners方法,会借助SpringFactoriesLoader机制从spring.factories文件中加载SpringApplicationRunListener类型的实现类,该类为SpringBoot提供的用于监听SpringBoot启动状态的观察者类,其唯一实现为EventPublishingRunListener,位于spring-boot-2.0.0.RELEASE.jar包中META-INF下spring.factories核心代码如下:
# Run Listenersorg.springframework.boot.SpringApplicationRunListener=\org.springframework.boot.context.event.EventPublishingRunListener
SpringFactoriesLoader机制正是SpringBoot自动装配的核心逻辑,关于其原理可以阅读笔者的这篇关于starter的原理解析:拒绝花里胡哨,极简springboot starter及原理,那么SpringBoot中的监听者注册就是通过这种方式注册到注册和通知中心的。
SpringBoot的注册和通知中心为SpringApplicationRunListeners,其实这个名字不够语义化,实际上该类包含了一个SpringApplicationRunListener列表和事件通知方法。
SpingBoot的发布者为SpringApplication实体,SpringBoot的启动核心流程均定义在该类下。
SpringBoot从ApplicationEvent扩展出了SpringApplicationEvent事件抽象类,其子类有ApplicationStartingEvent、ApplicationReadyEvent等,均代表了应用启动状态
那么SpringBoot的事件机制是怎样利用Spring的事件模型的呢,答案就在EventPublishingRunListener这个SpringBoot的监听者中,原来当SpringApplication向注册和通知中心发布启动状态事件后,事件会通知到该观察者,但是该观察者接收到事件后并没做其他事情,仅仅是将该事件通过Spring中的广播者SimpleApplicationEventMulticaster再将事件广播到Spring中的监听者,源码及注释如下:
@Override public void starting() { //initialMulticaster即为Spring中的广播者 this.initialMulticaster.multicastEvent( new ApplicationStartingEvent(this.application, this.args)); }
那么这些Spring监听者是在什么时候被注册进去的呢,其实在SpringBoot启动之初,会构建SpringApplication对象,这里同样是借助SpringFactoriesLoader机制,来加载SpringBoot提供的一些ApplicationListener的监听者,源码及注释如下:
//SpringApplication构造方法 public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); this.webApplicationType = deduceWebApplicationType(); setInitializers((Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class)); //通过SpringFactoriesLoader机制注册Spring的监听者 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); }
位于spring-boot-2.0.0.RELEASE.jar包中META-INF下spring.factories核心代码如下:
# Application Listenersorg.springframework.context.ApplicationListener=\org.springframework.boot.ClearCachesApplicationListener,\org.springframework.boot.builder.ParentContextCloserApplicationListener,\org.springframework.boot.context.FileEncodingApplicationListener,\org.springframework.boot.context.config.AnsiOutputApplicationListener,\org.springframework.boot.context.config.ConfigFileApplicationListener,\org.springframework.boot.context.config.DelegatingApplicationListener,\org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\org.springframework.boot.context.logging.LoggingApplicationListener,\org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
至此,SpringBoot中的观察者模式原理就讲完了,SpringBoot中的监听者可以自定义,并通过SpringFactoriesLoader机制注册,您可以试下以检验自己的理解程度。
如果您熟悉观察者模式这一内功心法,当在研究SpringBoot及Spring源码招式的时候,相信会理解起来事半功倍,希望这篇文章对您理解原理有所帮助。
标签: #观察者模式spring