当前位置: 首页 > 科技观察

SpringBoot2.0新特性(二):新增事件ApplicationStartedEvent

时间:2023-03-11 23:31:11 科技观察

今天继续说说SpringBoot2.0的新特性。本文将专门讲讲2.0版本中的事件模型,特别是新增的事件:ApplicationStartedEvent。SpringBoot2.0中对事件模型做了一些增强,主要是增加了ApplicationStartedEvent事件,所以2.0版本中所有事件的执行顺序如下:列表中,我们可以看到ApplicationStartedEvent位于ApplicationPreparedEvent之后和ApplicationReadyEvent之前。接下来我们通过代码直观感受一下这个事件的切入位置,方便以后在这个切入点添加我们需要的逻辑。第一步:我们可以为ApplicationPreparedEvent、ApplicationStartedEvent和ApplicationReadyEvent这三个事件编写监听器,然后在这三个事件触发时打印一些日志来观察它们各自的入口点,比如:@Slf4jpublicclassApplicationPreparedEventListenerimplementsApplicationListener{@OverridepublicvoidonApplicationEvent(ApplicationPreparedEventevent){log.info("...ApplicationPreparedEvent...");}}@Slf4jpublicclassApplicationStartedEventListenerimplementsApplicationListener{@OverridepublicvoidonApplicationEvent(ApplicationStartedEventevent){log.info("...ApplicationStartedEvent......");}}@Slf4jpublicclassApplicationReadyEventListenerimplementsApplicationListener{@OverridepublicvoidonApplicationEvent(ApplicationReadyEventevent){log.info("...ApplicationReadyEvent...");}}第二步:在/src/main中创建一个新的META-INF/spring.factories配置文件/资源/导演y,通过配置org.springframework.context.ApplicationListener加载我们上面写的监听器。org.springframework.context.ApplicationListener=com.didispace.ApplicationPreparedEventListener,\com.didispace.ApplicationReadyEventListener,\com.didispace.ApplicationStartedEventListener此时,我们运行SpringBoot应用可以获得类似如下日志输出:2018-03-0718:15:18.591INFO83387---[main]com.didispace.Application:StartingApplicationonzhaiyongchaodeMacBook-Pro.localwithPID83387(/Users/zhaiyongchao/Documents/git/github/SpringBoot-Learning/Chapter1-2-1/target/classesstartedbyzhaiyongchaoin/Users/zhaiyongchao/Documents/git/github/SpringBoot-Learning/Chapter1-2-1)2018-03-0718:15:18.591INFO83387---[main]com.didispace.Application:Noactiveprofileset,fallingbacktodefaultprofiles:default2018-03-0718:15:18.658INFO83387---[main]c.d.ApplicationPreparedEventListener:......ApplicationPreparedEvent......2018-03-0718:15:18.662INFO83387---[main]ConfigServletWebServerApplicationContext:Refreshingorg.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@20d3d15a:startupdate[WedMar0718:15:18CST2018];rootofcontexthierarchy2018-03-0718:15:19.879INFO83387---[main]o.s.b.w.embedded.tomcat.TomcatWebServer:Tomcatinitializedwithport(s):8080(http)2018-03-0718:19.926INFO83387---[main]o.apache.catalina.core.StandardService:Startingservice[Tomcat]2018-03-0718:15:19.930INFO83387---[main]org.apache.catalina.core.StandardEngine:StartingServletEngine:ApacheTomcat/8.5.282018-03-0718:15:19.946INFO83387---[ost-startStop-1]o.a.catalina.core.AprLifecycleListener:TheAPRbasedApacheTomcatNativelibrarywhichallowsoptimalperformanceinproductionenvironmentswasnotfoundonthejava.library.path:[/Users/zhaiyong/Extension:Joa/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.]2018-03-0718:15:20.068INFO83387---[ost-startStop-1]o.a.c.c.C.[Tomcat].[localhost].[/]:InitializingSpringembeddedWebApplicationContext2018-03-0718:15:20.068INFO83387---[ost-startStop-1]o.s.web.context.ContextLoader:RootWebApplicationContext:initializationcompletedin1410ms2018-03-0718:15:20.210INFO83387---[ost-startStop-1]o.s.b.w.servlet.ServletRegistrationBean:ServletdispatcherServletmappedto[/]2018-03-0718:15:208.384INFO-208.384[ost-startStop-1]o.s.b.w.servlet.FilterRegistrationBean:Mappingfilter:'characterEncodingFilter'to:[/*]2018-03-0718:15:20.214INFO83387---[ost-startStop-1]o.s.b.w.servlet.FilterRegistrationBean:Mappingfilter:'hiddenHttpMethodFilter'到:[/*]2018-03-0718:15:20.214INFO83387---[ost-startStop-1]o.s.b.w.servlet.FilterRegistrationBean:Mappingfilter:'httpPutFormContentFilter'到:[/*]2018-03-0718:15:20.215INFO83387---[ost-startStop-1]o.s.b.w.servlet.FilterRegistrationBean:Mappingfilter:'requestContextFilter'to:[/*]2018-03-0718:15:20.513INFO83387---[main]s.w.s.m.m.a.RequestMappingHandlerAdapter:HandlerAdapterLookingfor@ControllerAdvice:org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@20d3d15a:startupdate[WedMar0718:15:18CST2018];rootofcontexthierarchy2018-03-0718:15:20.592INFO83387---[main]s.w.s.m.m.a.RequestMappingHandlerMapping:Mapped"{[/error]}"ontopublicorg.springframework.http.ResponseEntity>org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)2018-03-0718:15:20.593INFO83387---[main]s.w.s.m.m.a.RequestMappingHandlerMapping:Mapped"{[/error],produces=[text/html]}"ontopublicorg.springframework.web.servlet.ModelAndVieworg.springframework.boot.autoconfigure.web.servlet.error。BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)2018-03-0718:15:20.623INFO83387---[main]o.s.w.s.handler.SimpleUrlHandlerMapping:MappedURLpath[/webjars/**]ontohandleroftype[classorg.springframework.web.servlet.resource.ResourceHttpRequestHandler]2018-03-0718:15:20.623INFO83387---[main]o.s.w.s.handler.SimpleUrlHandlerMapping:MappedURLpath[/**]ontohandleroftype[classorg.springframework.web.servlet.resource.ResourceHttpRequestHandler]2018-03-0718:15:20.660INFO83387---[main]o.s.w.s.handler.SimpleUrlHandlerMapping:MappedURLpath[/**/favicon.ico]ontohandleroftype[classorg.springframework.web.servlet.resource.ResourceHttpRequestHandler]2018-03-0718:15:20.787INFO83387---[main]o.s.j.e.a.AnnotationMBeanExporter:RegisteringbeansforJMXexposureonstartup2018-03-0718:15:20.839INFO83387---[main]o.s.b.w.embedded.tomcat.TomcatWebServer:Tomcatstartedonport(s):8080(http)withcontextpath''2018-03-0718:15:20.843-INFO-83387[main]com.didispace.Application:StartedApplicationin2.866seconds(JVMrunningfor3.337)2018-03-0718:15:20.845INFO83387---[main]c.d.ApplicationStartedEventListener:......ApplicationStartedEvent......2018-03-0718:15:20.847INFO83387---[main]c.d.ApplicationReadyEventListener:......ApplicationReadyEvent......从日在日志中,我们可以清楚的看到ApplicationPreparedEvent、ApplicationStartedEvent、ApplicationReadyEvent的入口点。通过这个例子,读者可能会产生疑惑:ApplicationStartedEvent和ApplicationReadyEvent从事件命名和日志输出位置来看都是在应用程序加载之后发生的。事件,它们之间有什么区别吗?我们来看看官方文档对ApplicationStartedEvent和ApplicationReadyEvent的解释:AnApplicationStartedEventissendaftercontexthasbeenrefreshedbutbeforeanyapplicationandcommand-linerunnershavebeencalled.AnApplicationReadyEventissentafteranyapplicationandcommand-linerunnershave被称为。它表示应用程序已准备好为请求提供服务。从文档中我们可以知道这两者之间有一个进程,也就是所谓的命令行运行器。因此,为了更准确的感受这两个事件的区别,我们在主应用类中加入CommandLineRunner的实现,如:@Slf4j@SpringBootApplicationpublicclassApplication{publicstaticvoidmain(String[]args){SpringApplication.run(Application.class,args);}@BeanpublicDataLoaderdataLoader(){returnnewDataLoader();}@Slf4jstaticclassDataLoaderimplementsCommandLineRunner{@Overridepublicvoidrun(String...strings)throwsException{log.info("Loadingdata...");}}}***,我们运行再次运行程序,这时候我们可以发现上面定义的DataLoader的输出内容是在这两个事件中间输出的,如下:2018-03-0718:15:20.845INFO83387---[main]c.d.ApplicationStartedEventListener:......ApplicationStartedEvent。.....2018-03-0718:15:20.846INFO83387---[main]com.didispace.Application$DataLoader:Loadingdata...2018-03-0718:15:20.847INFO83387---[main]c.d.ApplicationReadyEventListener:...ApplicationReadyEvent...代码示例本文中的相关示例,您可以查看以下仓库中的Chapter1-2-1目录:Github:https://github.com/dyc87112/SpringBoot-LearningGitee:https://gitee.com/didispace/SpringBoot-Learning【本文为专栏作者“翟永超”原创稿件,转载请联系作者获得授权】点此查看作者更多好文