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

网络品牌传播推广策略广东网络seo推广

网络品牌传播推广策略,广东网络seo推广,茶叶企业网站源码,淘宝客建站需要多少钱spring事件监听机制离不开容器IOC特性提供的支持,比如容器会自动创建事件发布器,自动识别用户注册的监听器并进行管理,在特定的事件发布后会找到对应的事件监听器并对其监听方法进行回调。Spring帮助用户屏蔽了关于事件监听机制背后的很多细节…

spring事件监听机制离不开容器IOC特性提供的支持,比如容器会自动创建事件发布器,自动识别用户注册的监听器并进行管理,在特定的事件发布后会找到对应的事件监听器并对其监听方法进行回调。Spring帮助用户屏蔽了关于事件监听机制背后的很多细节,使用户可以专注于业务层面进行自定义事件开发。然而我们对内部的实现还是有一些疑问,比如

• 事件发布器ApplicationEventMulticaster是何时被初始化的,初始化过程中都做了什么?
• 注册事件监听器的过程是怎样的,容器怎么识别出它们并进行管理?
• 容器发布事件的流程是怎样的?它如何根据发布的事件找到对应的事件监听器,事件和由该事件触发的监听器之间的匹配规则是怎样的?

初始化事件发布器流程

真正的事件发布器是ApplicationEventMulticaster,它定义在AbstractApplicationContext中,并在ApplicationContext容器启动的时候进行初始化。在容器启动的refrsh()方法中可以找到初始化事件发布器的入口方法,如下图所示:
在这里插入图片描述

/*** Initialize the ApplicationEventMulticaster.* Uses SimpleApplicationEventMulticaster if none defined in the context.* @see org.springframework.context.event.SimpleApplicationEventMulticaster*/protected void initApplicationEventMulticaster() {ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {this.applicationEventMulticaster =beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);if (logger.isTraceEnabled()) {logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");}}else {this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);if (logger.isTraceEnabled()) {logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");}}}

这里会根据核心容器beanFactory中是否有id为applicationEventMulticaster的bean分两种情况

(1)容器中已有id为applicationEventMulticaster的bean:直接从容器缓存获取或是创建该bean实例,并交由成员变量applicationEventMulticaster保存。当用户自定义了事件发布器并向容器注册时会执行该流程。
(2)容器中不存在applicationEventMulticaster的bean:这是容器默认的执行流程,会创建一个SimpleApplicationEventMulticaster,其仅在实现事件发布器基本功能(管理事件监听器以及发布容器事件)的前提下,增加了可以设置任务执行器Executor和错误处理器ErrorHandler的功能,当设置Executor为线程池时,则会以异步的方式对事件监听器进行回调,而ErrorHandler允许我们在回调方法执行错误时进行自定义处理。默认情况下,这两个变量都为null。

在这里插入图片描述
之后会调用beanFactory.registerSingleton方法将创建的SimpleApplicationEventMulticaster实例注册为容器的单实例bean。
初始化事件发布器总结一句话:由容器实例化用户自定义的事件发布器或者由容器帮我们创建一个简单的事件发布器并交由容器管理。

注册事件监听器流程

注册事件监听器的流程在初始化事件发布器之后,如下图所示:

在这里插入图片描述

/*** Add beans that implement ApplicationListener as listeners.* Doesn't affect other listeners, which can be added without being beans.*/protected void registerListeners() {// 首先注册静态指定的监听器。for (ApplicationListener<?> listener : getApplicationListeners()) {getApplicationEventMulticaster().addApplicationListener(listener);}// 不要在这里初始化FactoryBeans:我们需要保留所有常规Bean// 未初始化以允许后处理器应用于它们!String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);for (String listenerBeanName : listenerBeanNames) {getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);}// 发布早期应用程序事件Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;this.earlyApplicationEvents = null;if (earlyEventsToProcess != null) {for (ApplicationEvent earlyEvent : earlyEventsToProcess) {getApplicationEventMulticaster().multicastEvent(earlyEvent);}}}

容器事件发布流程

org.springframework.context.support.AbstractApplicationContext#publishEvent(java.lang.Object, ResolvableType)

将给定事件发布给所有侦听器
在这里插入图片描述
前面说,在启动的时候如果没有一个beanName叫做applicationEventMulticaster的ApplicationEventMulticaster,那使用的就是SimpleApplicationEventMulticaster,该组件会在容器启动时被自动创建,并以单例的形式存在,管理了所有的事件监听器,并提供针对所有容器内事件的发布功能。

org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(ApplicationEvent, ResolvableType)

@Override 
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { //获取事件类型 ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); //获取事件发布器内的任务执行器,默认该方法返回null Executor executor = getTaskExecutor(); //遍历所有和事件匹配的事件监听器 for (ApplicationListener<?> listener : getApplicationListeners(event, type)) { if (executor != null) { //异步回调监听方法 executor.execute(() -> invokeListener(listener, event)); } else { //同步回调监听方法 invokeListener(listener, event); } } 
}

如何根据事件类型找到匹配的所有事件监听器?

org.springframework.context.event.AbstractApplicationEventMulticaster#getApplicationListeners(ApplicationEvent, ResolvableType)

/*** Return a Collection of ApplicationListeners matching the given* event type. Non-matching listeners get excluded early.* @param event the event to be propagated. Allows for excluding* non-matching listeners early, based on cached matching information.* @param eventType the event type* @return a Collection of ApplicationListeners* @see org.springframework.context.ApplicationListener*/protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {// 获取事件中的事件源对象Object source = event.getSource();// 获取事件源类型Class<?> sourceType = (source != null ? source.getClass() : null);// 以事件类型和事件源类型为参数构建一个cacheKey ,用于从缓存map中获取与之匹配的监听器列表ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);// 根据cacheKey从缓存中获取CachedListenerRetrieverListenerRetriever retriever = this.retrieverCache.get(cacheKey);if (retriever != null) {return retriever.getApplicationListeners();}if (this.beanClassLoader == null ||(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {// Fully synchronized building and caching of a ListenerRetrieversynchronized (this.retrievalMutex) {retriever = this.retrieverCache.get(cacheKey);if (retriever != null) {return retriever.getApplicationListeners();}retriever = new ListenerRetriever(true);// 不存在就检索给定事件和源类型的应用程序侦听器,并放到缓存Collection<ApplicationListener<?>> listeners =retrieveApplicationListeners(eventType, sourceType, retriever);this.retrieverCache.put(cacheKey, retriever);return listeners;}}else {// No ListenerRetriever caching -> no synchronization necessaryreturn retrieveApplicationListeners(eventType, sourceType, null);}}

如果事件时第一次发布,会遍历所有的事件监听器,并根据事件类型和事件源类型进行匹配:

org.springframework.context.event.AbstractApplicationEventMulticaster#retrieveApplicationListeners

/*** Actually retrieve the application listeners for the given event and source type.* @param eventType the event type* @param sourceType the event source type* @param retriever the ListenerRetriever, if supposed to populate one (for caching purposes)* @return the pre-filtered list of application listeners for the given event and source type*/private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable ListenerRetriever retriever) {// 存放监听器的列表List<ApplicationListener<?>> allListeners = new ArrayList<>();Set<ApplicationListener<?>> listeners;Set<String> listenerBeans;synchronized (this.retrievalMutex) {listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);}// 添加以编程方式注册的侦听器,// 包括来自ApplicationListenerDetector的侦听器(单例bean和内部bean)。for (ApplicationListener<?> listener : listeners) {if (supportsEvent(listener, eventType, sourceType)) {if (retriever != null) {retriever.applicationListeners.add(listener);}allListeners.add(listener);}}// 按bean名称添加侦听器,这可能与上面通过编程注册的侦听器重叠,// 但这里可能有额外的元数据。if (!listenerBeans.isEmpty()) {ConfigurableBeanFactory beanFactory = getBeanFactory();for (String listenerBeanName : listenerBeans) {try {if (supportsEvent(beanFactory, listenerBeanName, eventType)) {ApplicationListener<?> listener =beanFactory.getBean(listenerBeanName, ApplicationListener.class);if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {if (retriever != null) {if (beanFactory.isSingleton(listenerBeanName)) {retriever.applicationListeners.add(listener);}else {retriever.applicationListenerBeans.add(listenerBeanName);}}allListeners.add(listener);}}else {// 删除最初来自ApplicationListenerDetector的不匹配侦听器,// 可能会被上面额外的BeanDefinition元数据(例如工厂方法泛型)排除。Object listener = beanFactory.getSingleton(listenerBeanName);if (retriever != null) {retriever.applicationListeners.remove(listener);}allListeners.remove(listener);}}catch (NoSuchBeanDefinitionException ex) {// 单一侦听器实例(没有支持bean定义)消失-可能在销毁阶段中期}}}//对匹配的监听器列表进行排序AnnotationAwareOrderComparator.sort(allListeners);if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {retriever.applicationListeners.clear();retriever.applicationListeners.addAll(allListeners);}return allListeners;}

容器事件发布的整个流程,可以总结如下
在这里插入图片描述

http://www.yayakq.cn/news/77096/

相关文章:

  • 网站建设的优势263企业邮箱入口注册
  • 沈阳做网站的企业手机网站建设提升用户体验的三个点
  • 怀化网站建设企业浦东新区办营业执照哪里办
  • 打鱼在线游戏网站建设网站机房建设目的
  • 单页面网站可以做自适应网站吗建网站程序工具
  • 有专门做ppt的网站天辰工程信息网官网
  • 文山专业网站建设淘宝客网站免费模板下载
  • 企业建站个人建站源码wordpress导航菜单动画
  • 外贸网站建设流程图推广app网站
  • 网络建设企业网站过年做哪个网站能致富
  • 域名备案需要网站吗旅行网站建设
  • 程序员怎么做自己的网站摄影网站建设流程
  • 公司官方网站怎么做烟台论坛建站模板
  • html5网站模板网站下拉菜单怎么做
  • 成都网站建设策划办公系统
  • 百色做网站360云盘做服务器建设网站
  • 中国校园网站做的比较好的学校jsp页面模板
  • 机关单位网站管理部门应建立怎么建设网站百度搜索的到
  • 自己建设影视网站js网站页面效果代码
  • 东莞企业网站建设开发公司百度云域名怎么做网站
  • 巨腾网站建设门户网站建设说明书
  • 如何建设网站视频教程装修注意事项及细节
  • 中国郑州建设信息网站wordpress文章批量编辑器
  • 阳江 网站开发自己电脑做网站域名备案
  • 网站开发与维护的相关大学做网站被抓
  • 网站做业务赚钱吗博兴网站建设招聘
  • 曲周企业做网站推广郑州比较厉害的设计公司
  • 网站运营工作是干什么的汕头网站模板价格
  • 网站建设项目需求营销型网站建设市场分析
  • dw做的网站怎么上传图片wordpress上传至哪个目录下