当前位置: 首页 > news >正文

唯品会网站开发百度企业网盘

唯品会网站开发,百度企业网盘,东莞做网站公司有哪些,哈尔滨模板建站软件文章目录 Pre概述Code源码分析 Pre Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent 概述 Spring Boot 的广播机制是基于观察者模式实现的&#xff0c…

文章目录

  • Pre
  • 概述
  • Code
  • 源码分析

在这里插入图片描述


Pre

Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent

Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent


概述

Spring Boot 的广播机制是基于观察者模式实现的,它允许在 Spring 应用程序中发布和监听事件。这种机制的主要目的是为了实现解耦,使得应用程序中的不同组件可以独立地改变和复用逻辑,而无需直接进行通信。

在 Spring Boot 中,事件发布和监听的机制是通过 ApplicationEventApplicationListener 以及事件发布者(ApplicationEventPublisher)来实现的。其中,ApplicationEvent 是所有自定义事件的基础,自定义事件需要继承自它。

ApplicationListener 是监听特定事件并做出响应的接口,开发者可以通过实现该接口来定义自己的监听器。事件发布者(通常由 Spring 的 ApplicationContext 担任)负责发布事件。


ApplicationContextInitializedEvent 是Spring框架中的一个事件,它在Spring应用上下文(ApplicationContext)初始化完成,但还未启动时触发。这个事件是在Spring框架初始化过程中,ApplicationContext对象创建完成,但还未开始加载 beans 和 配置之前发布的。

在Spring框架中,ApplicationContext是核心接口,负责实例化、配置和组装Bean。ApplicationContextInitializedEvent事件可以被用于执行一些需要在Spring应用上下文完全初始化,但是Bean尚未加载时的初始化代码。

使用场景举例:

  1. 自定义初始化逻辑
    当需要在Spring应用上下文初始化后,但Bean加载之前执行特定逻辑时,比如设置共享资源、初始化配置信息等。

  2. 监听应用上下文初始化完成
    用于在Spring应用上下文完全初始化后立即执行某些操作,比如日志记录、系统参数配置等。

  3. 插件或扩展点
    对于需要扩展Spring框架功能的第三方插件,可以在监听到这个事件时,进行一些自定义操作,如添加额外的Bean定义,或者修改已有的Bean定义。

  4. 资源加载与配置
    如果需要在Spring上下文初始化后,但Bean创建之前加载某些资源(如数据库连接、外部配置文件等),这个事件可以提供这样的机会。

在实际使用中,可以通过实现ApplicationListener接口来监听ApplicationContextInitializedEvent事件。

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ApplicationContextInitializedEvent;
public class CustomInitializationListener implements ApplicationListener<ApplicationContextInitializedEvent> {@Overridepublic void onApplicationEvent(ApplicationContextInitializedEvent event) {// 执行初始化逻辑}
}

然后,需要在Spring配置文件中注册这个监听器,或者使用注解@Component进行自动注册。

需要注意的是,在Spring Boot项目中,事件监听通常更加自动化,并且通常不需要手动注册监听器。Spring Boot会自动配置并注册事件监听器,开发者只需关注事件的处理逻辑即可。


Code

package com.artisan.event;import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
@Configuration
public class ApplicationContextNewInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {/*** ApplicationContextInitializedEvent 在准备应用程序上下文期间,但在将 Bean 定义加载到 Spring 容器之前。* <p>* 此事件提供了在初始化 Bean 之前执行任务的机会,例如注册属性源和基于上下文环境激活 Bean 等。* <p>* <p>* 为了处理该 ApplicationContextInitializedEvent 事件,* 我们可以通过实现 ApplicationContextInitializer ConfigurableApplicationContext 作为泛型类型的接口来为应用程序创建一个额外的初始值设定项。* 可以在主应用程序类中手动添加此初始值设定项。* <p>* <p>* 当我们运行 Spring Boot 应用程序时, ApplicationContextNewInitializer 将调用 这将允许我们在加载任何 Bean 定义之前根据需要执行任务* new SpringApplicationBuilder(EventsApplication.class).initializers(new ApplicationContextNewInitializer()).run(args);** @param applicationContext the application to configure*/@Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {System.out.println("--------------------> Handling ApplicationContextInitializedEvent here!");}
}

如何使用呢?

方式一:

@SpringBootApplication
public class LifeCycleApplication {/*** 除了手工add , 在 META-INF下面 的 spring.factories 里增加* org.springframework.context.ApplicationListener=自定义的listener 也可以** @param args*/public static void main(String[] args) {new SpringApplicationBuilder(LifeCycleApplication.class).initializers(new ApplicationContextNewInitializer()).run(args)}}

方式二: 通过spring.factories 配置

在这里插入图片描述

org.springframework.context.ApplicationContextInitializer=\
com.artisan.event.ApplicationContextNewInitializer

运行日志

在这里插入图片描述


源码分析

首先main方法启动入口

SpringApplication.run(LifeCycleApplication.class, args);

跟进去

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {return run(new Class<?>[] { primarySource }, args);}

继续

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {return new SpringApplication(primarySources).run(args);}

这里首先关注 new SpringApplication(primarySources)

new SpringApplication(primarySources)

	/*** Create a new {@link SpringApplication} instance. The application context will load* beans from the specified primary sources (see {@link SpringApplication class-level}* documentation for details. The instance can be customized before calling* {@link #run(String...)}.* @param resourceLoader the resource loader to use* @param primarySources the primary bean sources* @see #run(Class, String[])* @see #setSources(Set)*/@SuppressWarnings({ "unchecked", "rawtypes" })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 = WebApplicationType.deduceFromClasspath();this.bootstrappers = new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class));setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));this.mainApplicationClass = deduceMainApplicationClass();}

聚焦 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));


run

继续run

// 开始启动Spring应用程序
public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch(); // 创建一个计时器stopWatch.start(); // 开始计时DefaultBootstrapContext bootstrapContext = createBootstrapContext(); // 创建引导上下文ConfigurableApplicationContext context = null; // Spring应用上下文,初始化为nullconfigureHeadlessProperty(); // 配置无头属性(如:是否在浏览器中运行)SpringApplicationRunListeners listeners = getRunListeners(args); // 获取运行监听器listeners.starting(bootstrapContext, this.mainApplicationClass); // 通知监听器启动过程开始try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); // 创建应用参数ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments); // 预备环境configureIgnoreBeanInfo(environment); // 配置忽略BeanInfoBanner printedBanner = printBanner(environment); // 打印Bannercontext = createApplicationContext(); // 创建应用上下文context.setApplicationStartup(this.applicationStartup); // 设置应用启动状态prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner); // 准备上下文refreshContext(context); // 刷新上下文,执行Bean的生命周期afterRefresh(context, applicationArguments); // 刷新后的操作stopWatch.stop(); // 停止计时if (this.logStartupInfo) { // 如果需要记录启动信息new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); // 记录启动信息}listeners.started(context); // 通知监听器启动完成callRunners(context, applicationArguments); // 调用Runner}catch (Throwable ex) {handleRunFailure(context, ex, listeners); // 处理运行失败throw new IllegalStateException(ex); // 抛出异常}try {listeners.running(context); // 通知监听器运行中}catch (Throwable ex) {handleRunFailure(context, ex, null); // 处理运行失败throw new IllegalStateException(ex); // 抛出异常}return context; // 返回应用上下文
}

我们重点看

   prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);

继续

private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {// 将环境变量设置到Spring上下文context.setEnvironment(environment);// 对Spring上下文进行后处理postProcessApplicationContext(context);// 应用初始izers,这些是对Spring上下文进行额外配置的组件applyInitializers(context);// 通知监听器,上下文已准备好listeners.contextPrepared(context);// 关闭bootstrap上下文bootstrapContext.close(context);// 如果需要记录启动信息if (this.logStartupInfo) {// 记录启动信息,并判断是否为根上下文logStartupInfo(context.getParent() == null);// 记录Spring Boot的配置信息logStartupProfileInfo(context);}// 注册Spring Boot特定的单例beanConfigurableListableBeanFactory beanFactory = context.getBeanFactory();// 注册应用启动参数为单例bean,键为'springApplicationArguments'beanFactory.registerSingleton("springApplicationArguments", applicationArguments);// 如果有打印的Banner,将其注册为单例bean,键为'springBootBanner'if (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner);}// 如果bean工厂是DefaultListableBeanFactory的实例,设置是否允许Bean定义覆盖if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}// 如果设置了懒惰初始化,添加一个后处理器if (this.lazyInitialization) {context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());}// 加载所有源,通常是Bean定义的来源Set<Object> sources = getAllSources();// 断言源集合不为空,这些源将被加载到Spring上下文中Assert.notEmpty(sources, "Sources must not be empty");// 使用源数组加载Spring上下文load(context, sources.toArray(new Object[0]));// 通知监听器,上下文已加载listeners.contextLoaded(context);
}

【applyInitializers】

		protected void applyInitializers(ConfigurableApplicationContext context) {for (ApplicationContextInitializer initializer : getInitializers()) {Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),ApplicationContextInitializer.class);Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");initializer.initialize(context);}}

在这里插入图片描述

就到了我们自定义实现的代码逻辑中了。

     @Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {System.out.println("--------------------> Handling ApplicationContextInitializedEvent here!");}

继续

listeners.contextPrepared(context);	

又看了熟悉的

	@Overridepublic void contextPrepared(ConfigurableApplicationContext context) {this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));}

继续

	@Overridepublic void multicastEvent(ApplicationEvent event) {multicastEvent(event, resolveDefaultEventType(event));}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {// 如果eventType不为null,则直接使用它;否则,使用resolveDefaultEventType方法来解析事件的默认类型。ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));// 获取一个线程池执行器,它用于异步执行监听器调用。Executor executor = getTaskExecutor();// 获取所有对应该事件类型的监听器。for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {// 如果执行器不为null,则使用它来异步执行监听器调用;// 否则,直接同步调用监听器。if (executor != null) {executor.execute(() -> invokeListener(listener, event));}else {invokeListener(listener, event);}}
}

继续

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {try {listener.onApplicationEvent(event);}catch (ClassCastException ex) {......}}

在这里插入图片描述


文章转载自:
http://fallacious.stph.cn
http://honeysweet.stph.cn
http://silently.stph.cn
http://highbrow.stph.cn
http://overplaid.stph.cn
http://nutriment.stph.cn
http://curioso.stph.cn
http://subbituminous.stph.cn
http://hypercatalectic.stph.cn
http://sequal.stph.cn
http://serology.stph.cn
http://stably.stph.cn
http://manucode.stph.cn
http://scooter.stph.cn
http://oven.stph.cn
http://mechanic.stph.cn
http://stature.stph.cn
http://schmaltz.stph.cn
http://semideveloped.stph.cn
http://turbot.stph.cn
http://fanfare.stph.cn
http://pareira.stph.cn
http://inhomogenous.stph.cn
http://erogenous.stph.cn
http://ependyma.stph.cn
http://microsequencer.stph.cn
http://bedad.stph.cn
http://replant.stph.cn
http://smokey.stph.cn
http://this.stph.cn
http://gorblimey.stph.cn
http://unaccommodated.stph.cn
http://chorizo.stph.cn
http://mesogloea.stph.cn
http://uniformity.stph.cn
http://snowcraft.stph.cn
http://bluepencil.stph.cn
http://anodize.stph.cn
http://nalorphine.stph.cn
http://maguey.stph.cn
http://tahsil.stph.cn
http://superbity.stph.cn
http://indisposed.stph.cn
http://algesia.stph.cn
http://windbag.stph.cn
http://spiritualization.stph.cn
http://reputation.stph.cn
http://kneepad.stph.cn
http://roton.stph.cn
http://trimolecular.stph.cn
http://meiosis.stph.cn
http://ourself.stph.cn
http://intermarry.stph.cn
http://hashbury.stph.cn
http://practicably.stph.cn
http://lech.stph.cn
http://tostada.stph.cn
http://ryegrass.stph.cn
http://heating.stph.cn
http://congoese.stph.cn
http://joiner.stph.cn
http://leaflike.stph.cn
http://geotropic.stph.cn
http://antiphrasis.stph.cn
http://incur.stph.cn
http://freeborn.stph.cn
http://sunbath.stph.cn
http://throstle.stph.cn
http://neuter.stph.cn
http://thrace.stph.cn
http://perisperm.stph.cn
http://hydropsychotherapy.stph.cn
http://consultation.stph.cn
http://intercom.stph.cn
http://lignivorous.stph.cn
http://photoreaction.stph.cn
http://spaniel.stph.cn
http://journalism.stph.cn
http://exegetic.stph.cn
http://reciprocal.stph.cn
http://raglan.stph.cn
http://pully.stph.cn
http://enrichment.stph.cn
http://cookout.stph.cn
http://millionnaire.stph.cn
http://minimal.stph.cn
http://pommern.stph.cn
http://insanitation.stph.cn
http://aerocab.stph.cn
http://asphyxy.stph.cn
http://acellular.stph.cn
http://expiringly.stph.cn
http://faceted.stph.cn
http://reorient.stph.cn
http://bolide.stph.cn
http://rhombus.stph.cn
http://anachronistic.stph.cn
http://vaporiform.stph.cn
http://civie.stph.cn
http://ashpan.stph.cn
http://www.15wanjia.com/news/58408.html

相关文章:

  • 企业网站开发需求分析百度的链接
  • 张家口市建设局网站网店网络推广方案
  • wordpress 指定文章链接淘宝关键词排名优化
  • 射洪哪里可以做网站百度电脑版官网入口
  • 海南省住房公积金管理局app百度优化seo
  • 在哪能学到网站建设专业整站seo免费咨询
  • 学做网站论坛vip账号破解抚顺网站建设
  • 做网站专业抖音推广佣金平台
  • 网站建设公司的服务公司网络怎么做推广
  • 网站上的信息可以做证据吗网站子域名查询
  • 网站制作价格与售后视频重庆百度快速优化
  • 简述网站开发的步骤软文优化
  • 百度搜索推广方法seo推广优化方案
  • wordpress 4.7.9漏洞怎么做seo
  • 网站开发属于软件开发地推放单平台
  • 大数据网站怎么做如何做好seo优化
  • 网站建设课程心得体会google图片搜索
  • 景观设计师做交通分析常用网站直通车怎么开
  • 哈尔滨做网站的厦门seo推广
  • 青岛做网站公司有哪些软文推广怎么写
  • 公司网站建设前期方案石家庄手机端seo
  • 免费图片素材网站有哪些免费发帖的网站
  • 面包屑导航的网站江西seo推广软件
  • 南京网站优化多少钱天津百度推广
  • 北仑网站建设培训学校搜索排名
  • 网站制作与免费网站建设中山seo
  • 沈阳 网站开发制作怎么做产品推广和宣传
  • 如何看一个网站做的如何建站网站关键词优化
  • 怎么给自己的品牌做网站搜索引擎优化原理
  • 日本做国际外贸常用的网站国际婚恋网站排名