范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Spring事件监听机制源码解析

  Spring事件监听器使用
  1.Spring事件监听体系包括三个组件:事件、事件监听器,事件广播器。
  事件:定义事件类型和事件源,需要继承ApplicationEvent。  package com.ybe.eventLisitener; import org.springframework.context.ApplicationEvent;  public class OrderEvent extends ApplicationEvent {     private String name;     public OrderEvent(Object source,String name) {         super(source);         this.name = name;     }     public String getName() {         return name;     }     public void setName(String name) {         this.name = name;     } }
  事件监听器:用来监听某一类的事件,并且执行具体业务逻辑,需要实现ApplicationListener 接口或者需要用@ListenerEvent(T)注解。好比观察者模式中的观察者。  package com.ybe.eventLisitener; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component;  @Component public class OrderEventListener implements ApplicationListener {     @Override     public void onApplicationEvent(OrderEvent event) {         if(event.getName().equals("下订单")){             System.out.println("下单已完成...");         }     } }package com.ybe.eventLisitener; import org.springframework.context.ApplicationListener; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component;  @Component public class OrderEventListenerByAnnotation  {      @EventListener(OrderEvent.class)     public void onApplicationEvent(OrderEvent event) {         if(event.getName().equals("下订单")){             System.out.println("下单已完成...");         }     } }
  事件多播器:负责广播通知所有监听器,所有的事件监听器都注册在了事件多播器中。好比观察者模式中的被观察者。Spring容器默认生成的是同步事件多播器。可以自定义事件多播器,定义为异步方式。  import org.springframework.context.event.ApplicationEventMulticaster; import org.springframework.context.event.SimpleApplicationEventMulticaster; import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.stereotype.Component;  import java.util.Scanner;  @Configuration @ComponentScan(value = "com.ybe") public class Config {     @Bean     public ApplicationEventMulticaster applicationEventMulticaster(){         SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster();         eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());         return eventMulticaster;     } }Spring事件源码分析1.创建多播器
  创建 AnnotationConfigApplicationContext 的过程中,会执行refresh()中的initApplicationEventMulticaster()方法。该方法先获取bean工厂,然后判断工厂是否包含了beanName 为 applicationEventMulticaster的bean。如果包含了,则获取该bean,赋值给applicationEventMulticaster 属性。如果没有,则创建一个 SimpleApplicationEventMulticaster 对象,并且赋值给 applicationEventMulticaster 。实现了源码如下:  /** 	 * Initialize the ApplicationEventMulticaster. 	 * Uses SimpleApplicationEventMulticaster if none defined in the context. 	 * @see org.springframework.context.event.SimpleApplicationEventMulticaster 	 */ protected void initApplicationEventMulticaster() { 		// 获取当前bean工厂,一般是DefaultListableBeanFactory 		ConfigurableListableBeanFactory beanFactory = getBeanFactory(); 		// 判断容器中是否存在bdName为applicationEventMulticaster的bd,          //也就是说自定义的事件监听多路广播器,必须实现  ApplicationEventMulticaster接口 		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { 			// 如果有,则从bean工厂得到这个bean对象 			this.applicationEventMulticaster = 					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); 			if (logger.isTraceEnabled()) { 				logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); 			} 		} 		else { 			// 如果没有,则默认采用SimpleApplicationEventMulticaster 			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() + "]"); 			} 		} 	}2.注册监听器
  监听器的注册有两种,通过实现 ApplicationListener接口或者添加@EventListener注解。  一.通过接口方式注册。实现接口 ApplicationListener。
  注册的逻辑实现在refresh()中的registerListeners()方法里面。第一步,先获取当前ApplicationContext中已经添加的 applicationListeners(SpringMVC源码中有用到),遍历添加到多播器中。第二步,获取实现了ApplicationListener接口的listenerBeanNames集合,添加至多播器中。第三步,判断是否有早期事件,如果有则发起广播。  protected void registerListeners() {       // Register statically specified listeners first.       // 遍历应用程序中存在的监听器集合,并将对应的监听器添加到监听器的多路广播器中       for (ApplicationListener<?> listener : getApplicationListeners()) {          getApplicationEventMulticaster().addApplicationListener(listener);       }        // Do not initialize FactoryBeans here: We need to leave all regular beans       // uninitialized to let post-processors apply to them!       // 从容器中获取所有实现了ApplicationListener接口的bd的bdName       // 放入ApplicationListenerBeans集合中       String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);       for (String listenerBeanName : listenerBeanNames) {          getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);       }        // Publish early application events now that we finally have a multicaster...       // 此处先发布早期的监听器集合       Set earlyEventsToProcess = this.earlyApplicationEvents;       this.earlyApplicationEvents = null;       if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {          for (ApplicationEvent earlyEvent : earlyEventsToProcess) {             getApplicationEventMulticaster().multicastEvent(earlyEvent);          }       }    }
  思考一下,上面的代码中第二步为啥添加的是listenerBeanName?
  如果监听器是懒加载的话(即有@Lazy 注解)。那么在这个时候创建监听器显然是不对的,这个时候不能创建监听器。所以添加监听器到多播器的具体逻辑放在初始化具体的监听器之后。通过 BeanPostProcessor 的接口实现。具体的实现类是 ApplicationListenerDetector 。这个类是在 refreah()中prepareBeanFactory()方法中添加的。代码如下:  protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { 		// Tell the internal bean factory to use the context"s class loader etc. 		beanFactory.setBeanClassLoader(getClassLoader()); 		if (!shouldIgnoreSpel) { 			beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); 		} 		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));  		// Configure the bean factory with context callbacks. 		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); 		beanFactory.ignoreDependencyInterface(EnvironmentAware.class); 		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); 		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); 		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); 		beanFactory.ignoreDependencyInterface(MessageSourceAware.class); 		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); 		beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);  		// BeanFactory interface not registered as resolvable type in a plain factory. 		// MessageSource registered (and found for autowiring) as a bean. 		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); 		beanFactory.registerResolvableDependency(ResourceLoader.class, this); 		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); 		beanFactory.registerResolvableDependency(ApplicationContext.class, this);  		// Register early post-processor for detecting inner beans as ApplicationListeners.     	// 添加 监听器后置处理器,在初始化具体的实现了 ApplicationListener 接口的Bean之后,进行调用。调用的是     	// postProcessAfterInitialization()方法。 		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));  		// Detect a LoadTimeWeaver and prepare for weaving, if found. 		if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { 			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); 			// Set a temporary ClassLoader for type matching. 			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); 		}  		// Register default environment beans. 		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { 			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); 		} 		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { 			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); 		} 		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { 			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); 		} 		if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) { 			beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup()); 		} 	}二、通过注解的方式注册。@EventListener(T)。
  在创建 AnnotationConfigApplicationContext 的构造方法中,会执行org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object) 方法。这个方法中会添加两个 beanDefs, 代码如下:  if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { 			RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class); 			def.setSource(source); 			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME)); }  if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) { 			RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class); 			def.setSource(source); 			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME)); }
  EventListenerMethodProcessor:事件监听器的BeanFactory后置处理器,在前期会创建 DefaultEventListenerFactory ,后期在创建好Bean之后,根据 EventListener 属性,调用DefaultEventListenerFactory创建具体的 ApplicationListenerMethodAdapter 。
  DefaultEventListenerFactory:监听器的创建工厂,用来创建 ApplicationListenerMethodAdapter 。
  EventListenerMethodProcessor 的类继承图如下:
  在refreash的invokeBeanFactoryPostProcessors()中会调用 org.springframework.context.event.EventListenerMethodProcessor#postProcessBeanFactory方法,获取EventListenerFactory 类型的 Bean。代码如下:  @Override 	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { 		this.beanFactory = beanFactory; 		// 获取或创建 EventListenerFactory 类型的 Bean 		Map beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false); 		List factories = new ArrayList<>(beans.values()); 		AnnotationAwareOrderComparator.sort(factories); 		this.eventListenerFactories = factories; 	}
  在 org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons 方法中,创建完所有的单例Bean 之后,会遍历所有Bean是否实现了 SmartInitializingSingleton 接口。如果实现接口会执行该 Bean 的 afterSingletonsInstantiated() 方法。代码如下:  public void preInstantiateSingletons() throws BeansException { 		if (logger.isTraceEnabled()) { 			logger.trace("Pre-instantiating singletons in " + this); 		}  		// Iterate over a copy to allow for init methods which in turn register new bean definitions. 		// While this may not be part of the regular factory bootstrap, it does otherwise work fine. 		// 将所有BeanDefinition的名字创建一个集合 		List beanNames = new ArrayList<>(this.beanDefinitionNames);  		// Trigger initialization of all non-lazy singleton beans... 		// 触发所有非延迟加载单例bean的初始化,遍历集合的对象 		for (String beanName : beanNames) { 			// 合并父类BeanDefinition  			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); 			// 条件判断,抽象,单例,非懒加载 			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { 				// 判断是否实现了FactoryBean接口 				if (isFactoryBean(beanName)) { 					// 根据&+beanName来获取具体的对象 					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); 					// 进行类型转换 					if (bean instanceof FactoryBean) { 						FactoryBean<?> factory = (FactoryBean<?>) bean; 						// 判断这个FactoryBean是否希望立即初始化 						boolean isEagerInit; 						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { 							isEagerInit = AccessController.doPrivileged( 									(PrivilegedAction) ((SmartFactoryBean<?>) factory)::isEagerInit, 									getAccessControlContext()); 						} 						else { 							isEagerInit = (factory instanceof SmartFactoryBean && 									((SmartFactoryBean<?>) factory).isEagerInit()); 						} 						//  如果希望急切的初始化,则通过beanName获取bean实例 						if (isEagerInit) { 							getBean(beanName); 						} 					} 				} 				else { 					// 如果beanName对应的bean不是FactoryBean,只是普通的bean,通过beanName获取bean实例 					getBean(beanName); 				} 			} 		}  		// Trigger post-initialization callback for all applicable beans... 		// 遍历beanNames,触发所有SmartInitializingSingleton的后初始化回调 		for (String beanName : beanNames) { 			// 获取beanName对应的bean实例 			Object singletonInstance = getSingleton(beanName); 			// 判断singletonInstance是否实现了SmartInitializingSingleton接口 			if (singletonInstance instanceof SmartInitializingSingleton) { 				// 类型转换 				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; 				// 触发SmartInitializingSingleton实现类的afterSingletonsInstantiated方法 				if (System.getSecurityManager() != null) { 					AccessController.doPrivileged((PrivilegedAction) () -> { 						smartSingleton.afterSingletonsInstantiated(); 						return null; 					}, getAccessControlContext()); 				} 				else { 					smartSingleton.afterSingletonsInstantiated(); 				} 			} 		} 	}
  org.springframework.context.event.EventListenerMethodProcessor#afterSingletonsInstantiated 中会调用私有方法 processBean()进行 ApplicationEventAdatper 的创建。代码如下:  /** 	 * 该方法拿到某个bean的名称和它的目标类,再这个范围上检测@EventListener注解方法,生成和注册 ApplicationListenerMethodAdapter 实例 	 * @param beanName 	 * @param targetType 	 */ 	private void processBean(final String beanName, final Class<?> targetType) { 		if (!this.nonAnnotatedClasses.contains(targetType) && 				AnnotationUtils.isCandidateClass(targetType, EventListener.class) && 				!isSpringContainerClass(targetType)) {  			Map annotatedMethods = null; 			try { 				// 检测当前类targetType上使用了注解@EventListener的方法 				annotatedMethods = MethodIntrospector.selectMethods(targetType, 						(MethodIntrospector.MetadataLookup) method -> 								AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class)); 			} 			catch (Throwable ex) { 				// An unresolvable type in a method signature, probably from a lazy bean - let"s ignore it. 				if (logger.isDebugEnabled()) { 					logger.debug("Could not resolve methods for bean with name "" + beanName + """, ex); 				} 			}  			if (CollectionUtils.isEmpty(annotatedMethods)) { 				// 如果当前类targetType中没有任何使用了注解@EventListener的方法,则将该类保存到缓存nonAnnotatedClasses,从而 				// 避免当前处理方法重入该类,避免二次处理 				this.nonAnnotatedClasses.add(targetType); 				if (logger.isTraceEnabled()) { 					logger.trace("No @EventListener annotations found on bean class: " + targetType.getName()); 				} 			} 			else { 				// Non-empty set of methods 				// 如果当前类targetType中有些方法使用了注解@EventListener,那么根据方法上的信息对应的创建和注册ApplicationListener实例 				ConfigurableApplicationContext context = this.applicationContext; 				Assert.state(context != null, "No ApplicationContext set"); 				// 此处使用了this.eventListenerFactories,这些EventListenerFactory是在该类postProcessBeanFactory方法调用时被记录的 				List factories = this.eventListenerFactories; 				Assert.state(factories != null, "EventListenerFactory List not initialized"); 				for (Method method : annotatedMethods.keySet()) { 					for (EventListenerFactory factory : factories) { 						if (factory.supportsMethod(method)) { 							Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName)); 							// 如果当前EventListenerFactory支持处理该@EventListener注解的方法,则使用它创建 ApplicationListenerMethodAdapter 							ApplicationListener<?> applicationListener = 									factory.createApplicationListener(beanName, targetType, methodToUse); 							if (applicationListener instanceof ApplicationListenerMethodAdapter) { 								((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator); 							} 							// 将创建的ApplicationListener加入到容器中 							context.addApplicationListener(applicationListener); 							break; 						} 					} 				} 				if (logger.isDebugEnabled()) { 					logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean "" + 							beanName + "": " + annotatedMethods); 				} 			} 		} 	}3.多播器广播事件
  可以通过调用 org.springframework.context.support.AbstractApplicationContext#publishEvent(java.lang.Object, org.springframework.core.ResolvableType) 方法进行事件的调用。代码如下:  /** 	 * 将给定事件发布到所有监听器 	 */ 	protected void publishEvent(Object event, @Nullable ResolvableType eventType) { 		// 如果event为null,抛出异常 		Assert.notNull(event, "Event must not be null");  		// Decorate event as an ApplicationEvent if necessary 		// 装饰事件作为一个应用事件,如果有必要 		ApplicationEvent applicationEvent; 		// 如果event是ApplicationEvent的实例 		if (event instanceof ApplicationEvent) { 			// 将event强转为ApplicationEvent对象 			applicationEvent = (ApplicationEvent) event; 		} 		else { 			// PayloadApplicationEvent:携带任意有效负载的ApplicationEvent。 			// 创建一个新的PayloadApplicationEvent 			applicationEvent = new PayloadApplicationEvent<>(this, event); 			// 如果eventType为 null 			if (eventType == null) { 				// 将applicationEvent转换为PayloadApplicationEvent 象,引用其ResolvableType对象 				eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType(); 			} 		}  		// Multicast right now if possible - or lazily once the multicaster is initialized 		// 如果可能的话,现在就进行组播——或者在组播初始化后延迟 		// earlyApplicationEvents:在多播程序设置之前发布的ApplicationEvent 		// 如果earlyApplicationEvents不为 null,这种情况只在上下文的多播器还没有初始化的情况下才会成立,会将applicationEvent 		// 添加到earlyApplicationEvents保存起来,待多博器初始化后才继续进行多播到适当的监听器 		if (this.earlyApplicationEvents != null) { 			//将applicationEvent添加到 earlyApplicationEvents 			this.earlyApplicationEvents.add(applicationEvent); 		} 		else { 			// 多播applicationEvent到适当的监听器 			getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); 		}  		// Publish event via parent context as well... 		// 通过父上下文发布事件 		// 如果parent不为null 		if (this.parent != null) { 			// 如果parent是AbstractApplicationContext的实例 			if (this.parent instanceof AbstractApplicationContext) { 				// 将event多播到所有适合的监听器。如果event不是ApplicationEvent实例,会将其封装成PayloadApplicationEvent对象再进行多播 				((AbstractApplicationContext) this.parent).publishEvent(event, eventType); 			} 			else { 				// 通知与event事件应用程序注册的所有匹配的监听器 				this.parent.publishEvent(event); 			} 		} 	}
  SimpleApplicationEventMulticaster 中的 multicasEvent,invokeListener,doInvokeListener 三个方法代码如下:  /** 	 * 将给定事件发布到所有监听器 	 */ 	protected void publishEvent(Object event, @Nullable ResolvableType eventType) { 		// 如果event为null,抛出异常 		Assert.notNull(event, "Event must not be null");  		// Decorate event as an ApplicationEvent if necessary 		// 装饰事件作为一个应用事件,如果有必要 		ApplicationEvent applicationEvent; 		// 如果event是ApplicationEvent的实例 		if (event instanceof ApplicationEvent) { 			// 将event强转为ApplicationEvent对象 			applicationEvent = (ApplicationEvent) event; 		} 		else { 			// PayloadApplicationEvent:携带任意有效负载的ApplicationEvent。 			// 创建一个新的PayloadApplicationEvent 			applicationEvent = new PayloadApplicationEvent<>(this, event); 			// 如果eventType为 null 			if (eventType == null) { 				// 将applicationEvent转换为PayloadApplicationEvent 象,引用其ResolvableType对象 				eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType(); 			} 		}  		// Multicast right now if possible - or lazily once the multicaster is initialized 		// 如果可能的话,现在就进行组播——或者在组播初始化后延迟 		// earlyApplicationEvents:在多播程序设置之前发布的ApplicationEvent 		// 如果earlyApplicationEvents不为 null,这种情况只在上下文的多播器还没有初始化的情况下才会成立,会将applicationEvent 		// 添加到earlyApplicationEvents保存起来,待多博器初始化后才继续进行多播到适当的监听器 		if (this.earlyApplicationEvents != null) { 			//将applicationEvent添加到 earlyApplicationEvents 			this.earlyApplicationEvents.add(applicationEvent); 		} 		else { 			// 多播applicationEvent到适当的监听器 			getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); 		}  		// Publish event via parent context as well... 		// 通过父上下文发布事件 		// 如果parent不为null 		if (this.parent != null) { 			// 如果parent是AbstractApplicationContext的实例 			if (this.parent instanceof AbstractApplicationContext) { 				// 将event多播到所有适合的监听器。如果event不是ApplicationEvent实例,会将其封装成PayloadApplicationEvent对象再进行多播 				((AbstractApplicationContext) this.parent).publishEvent(event, eventType); 			} 			else { 				// 通知与event事件应用程序注册的所有匹配的监听器 				this.parent.publishEvent(event); 			} 		} 	}protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) { 		// 获取此多播器的当前错误处理程序 		ErrorHandler errorHandler = getErrorHandler(); 		// 如果errorHandler不为null 		if (errorHandler != null) { 			try { 				// 回调listener的onApplicationEvent方法,传入event 				doInvokeListener(listener, event); 			} 			catch (Throwable err) { 				// 交给errorHandler接收处理err 				errorHandler.handleError(err); 			} 		} 		else { 			// 回调listener的onApplicationEvent方法,传入event 			doInvokeListener(listener, event); 		} 	}/** 	 * 回调listener的onApplicationEvent方法,传入 event 	 * @param listener 	 * @param event 	 */ 	@SuppressWarnings({"rawtypes", "unchecked"}) 	private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) { 		try { 			//回调listener的onApplicationEvent方法,传入	        			event:contextrefreshListener:onapplicaitonEvent:FrameworkServlet.this.onApplicationEvent() 			listener.onApplicationEvent(event); 		} 		catch (ClassCastException ex) { 			//获取异常信息 			String msg = ex.getMessage(); 			if (msg == null || matchesClassCastMessage(msg, event.getClass())) { 				// Possibly a lambda-defined listener which we could not resolve the generic event type for 				// -> let"s suppress the exception and just log a debug message. 				Log logger = LogFactory.getLog(getClass()); 				if (logger.isTraceEnabled()) { 					logger.trace("Non-matching event type for listener: " + listener, ex); 				} 			} 			else { 				//抛出异常 				throw ex; 			} 		} 	}SpringMVC中事件使用
  SpringMVC中就是通过Spring的事件机制进行九大组件的初始化。  1.ContextRefreshListener监听器的定义
  监听器定义在FrameworkServlet类中,作为内部类。代码如下:  private class ContextRefreshListener implements ApplicationListener {  		@Override 		public void onApplicationEvent(ContextRefreshedEvent event) { 			FrameworkServlet.this.onApplicationEvent(event); 		} 	}
  监听器的添加在org.springframework.web.servlet.FrameworkServlet#configureAndRefreshWebApplicationContext 中进行。通过SourceFilteringListener进行包装。添加代码如下:  // 添加监听器sourceFilteringListener到wac中,实际监听的是ContextRefreshListener所监听的事件,监听ContextRefreshedEvent事件, 		// 当接收到消息之后会调用onApplicationEvent方法,调用onRefresh方法,并将refreshEventReceived标志设置为true,表示已经refresh过 		wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));2.多播器添加已经定义的ContextRefreshListener事件监听器
  在refresh中的registerListeners方法进行添加,代码如下:  // Register statically specified listeners first. 		// 遍历应用程序中存在的监听器集合,并将对应的监听器添加到监听器的多路广播器中 		for (ApplicationListener<?> listener : getApplicationListeners()) { 			getApplicationEventMulticaster().addApplicationListener(listener); 		}3.ContextRefreshListener事件监听器的触发
  在refresh中的finishRefresh()方法中,会调用publishEvnet(new ContextRefreshedEvent(this))发布事件。进行多播器广播,代码如下  // 多播applicationEvent到适当的监听器 getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
  最终会调到FrameworkServlet.this.onApplicationEvent(event)。  public void onApplicationEvent(ContextRefreshedEvent event) { 		// 标记 refreshEventReceived 为true 		this.refreshEventReceived = true; 		synchronized (this.onRefreshMonitor) { 			// 处理事件中的 ApplicationContext 对象,空实现,子类DispatcherServlet会实现 			onRefresh(event.getApplicationContext()); 		} 	}@Override 	protected void onRefresh(ApplicationContext context) { 		initStrategies(context); 	}protected void initStrategies(ApplicationContext context) { 		// 初始化 MultipartResolver:主要用来处理文件上传.如果定义过当前类型的bean对象,那么直接获取,如果没有的话,可以为null 		initMultipartResolver(context); 		// 初始化 LocaleResolver:主要用来处理国际化配置,基于URL参数的配置(AcceptHeaderLocaleResolver),基于session的配置(SessionLocaleResolver),基于cookie的配置(CookieLocaleResolver) 		initLocaleResolver(context); 		// 初始化 ThemeResolver:主要用来设置主题Theme 		initThemeResolver(context); 		// 初始化 HandlerMapping:映射器,用来将对应的request跟controller进行对应 		initHandlerMappings(context); 		// 初始化 HandlerAdapter:处理适配器,主要包含Http请求处理器适配器,简单控制器处理器适配器,注解方法处理器适配器 		initHandlerAdapters(context); 		// 初始化 HandlerExceptionResolver:基于HandlerExceptionResolver接口的异常处理 		initHandlerExceptionResolvers(context); 		// 初始化 RequestToViewNameTranslator:当controller处理器方法没有返回一个View对象或逻辑视图名称,并且在该方法中没有直接往response的输出流里面写数据的时候,spring将会采用约定好的方式提供一个逻辑视图名称 		initRequestToViewNameTranslator(context); 		// 初始化 ViewResolver: 将ModelAndView选择合适的视图进行渲染的处理器 		initViewResolvers(context); 		// 初始化 FlashMapManager: 提供请求存储属性,可供其他请求使用 		initFlashMapManager(context); 	}
三星GalaxyS23Ultra概念图极限全面屏设计很耀眼,绝绝子在手机市场中,三星手机是一个大家都耳熟能详的手机厂商,是一个综合实力非常雄厚的手机厂商,近些年三星手机通过持续的创新和探索,为行业带来了很多设计优秀的产品,比三星GalaxyS8三10类工程项目的垫资金额与利润差距垫资施工已经成为建筑市场的常态,建筑行业很多时候难的不是拿不到项目,而是拿不到钱,与营业额一同增长的不是净利润,而是应收账款。垫资的多少直接影响着工程企业的现金流是否能良性运转,同难怪小牧童能走进五行山,你看他真身是谁?孙悟空成佛后才懂作为中国古典文学的经典之作,西游记可谓是家喻户晓。随着杨洁将86版的西游记搬上荧屏之后,六小龄童扮演的孙悟空更是深入人心,风靡了天南地北。时至今日,依旧出现了许多夹杂有西游元素的电苗圃和张国立罗晋传过绯闻,嫁大自己19岁百亿富豪收获幸福爱情是不按逻辑发展的,所以必须时时注意它的变化。爱情更不是永恒的,所以必须不断地追求。柏杨娱乐圈就是一个圈,可能某位女演员的前男友,就是现在当红小花的现男友,不少人说,在娱乐圈中真中斯建交60周年重点工程通过竣工验收当地时间6月10日,由中铁二十五局集团承建的援斯里兰卡国家医院门诊楼项目顺利通过竣工验收,综合评价等级为优良,为斯里兰卡最大的公立医院移交运营打下坚实基础。据悉,该项目是庆祝中斯建南方三口之家周末午餐晒圈火了,不剩菜不浪费,网友不要假精致转眼又到了周末,一家三口都在家,平时周末都会睡到自然醒,但是入夏后,天气炎热,很早就醒了,看着今天又轮到采核酸的日子,就起来赶早去采了核算,顺道去菜市场将菜买回来了。周末在家,不妨芯片禁令真能卡我们脖子?过去20年经验证明这是帮了我们一个大忙6月10日早间,我国最大的芯片制造商中芯国际公告称接到胜诉裁决,加利福尼亚中期法院驳回了原告对中芯国际有关违反某1934年证券交易法的民事起诉,原告不得再以同一理由起诉或对诉状进行技术论文基于激光雷达与单目相机融合的人体多目标室内定位系统欢迎引用1熊亦威,李慧诚,周朝,杨爱英,冯立辉,乔耀军。sss基于激光雷达与单目相机融合的人体多目标室内定位系统J。自动化与仪器仪表,2022,No。271(05)1115。DOI经络穴位,一日一学血海,祛瘀血生新血,调经统血的人体大穴血海穴命名血海的血指本穴气血物质受热变成的红色液体。海代指本穴气血容量很多。本穴是足太阴脾经上的一个要穴,脾可化生气血,气血经脾经汇聚到本穴,使此处气血极为旺盛,因而得名。本穴也因中国镁资源统治全球95市场,一年涨价7倍后,减产卡住欧美脖子这次该轮到欧美国家着急了吧?中国是镁金属的主要出口国,在全球市场上的比重更是达到95。2021年,中国镁企业因为疫情的因素,产量受到影响,造成同年9月份的出口量降低23。3,国际镁原神新的五星火枪要来了!须弥新怪物一览,菲谢尔皮肤获取方式旅行者们可算有须弥新角色的情报了!首先已经有推主在游戏数据中发现了一位名为妮露的新角色,和刻晴一样是少女体型,定位五星火枪,不出意外3。0就会实装,由于目前游戏内前台火C太多了,所
69岁刘晓庆仍不服老,涂大红唇妆容精致似芭比,豪宅内唱歌上气不接下气近日,演员刘晓庆在自己的社交媒体平台上晒出了一段自己宅家唱歌的视频,并配文表示让网友猜猜哪部分是她真唱的,哪是她对嘴的,在视频中亲自演唱了一首小河淌水,引起了不少网友的关注和热议。男篮要小心,一支神秘队伍组建完成冲击亚运会伙伴们中午好,又到了午休时间,咱们大家来小编这里聊聊天。今天中午小编跟大家聊聊篮球。今年在我们国家还有一项大型赛事那就是杭州亚运会,亚运会比赛篮球项目也是非常收关注的,我们国家男女辽篮老将老而弥坚,如今再捐善款,悍将历经波折,最终黯然离队辽篮的李晓旭,是队友们公认的二哥。但是辽迷们则昵称其为篮板魔兽。他在辽宁男篮的一众球员中,一直都是极有担当的大师兄!他从辽少辽青一路走来,一直都在为辽篮效力!他体验过辽篮的痛,见感首都机场迎冬奥人员及枪支出境高峰!光子弹就超11万发2月20日北京冬奥会圆满闭幕,首都国际机场口岸今明两日将持续迎来出境高峰,预计将有超8000名冬奥人员集中出境,约占参加冬奥会人员总数的50。记者从北京边检总站获悉,截至2月21日浏阳焰火再放鸟巢,致敬双奥之城2月20日晚,浏阳烟花在鸟巢上方精彩绽放,写出复杂的ONEWORLDONEFAMILY和天下一家的中英文字幕。编者按回望过往的奋斗路,眺望前方的奋进路,即日起,本报推出奋进新征程建京城四美之一景甜,一个背景强大的人物,到底是谁呢?第一次见到景甜的时候是在2011年,正在与孙红雷在拍摄战国。那时候的景甜算刚出道,一脸青春少女的气息,正如她的名字一样,外形给人甜甜的感觉。她的甜甜美美的形象,曾与白冰韩雪戚薇号称黄晓明和蒋欣被传出恋情!女方火速辟谣是兄弟娱乐圈的感情向来在大众眼中都是不靠谱的,他们常常会发生这样或那样的变故。在他们这里,似乎没有长久的情感,而黄晓明和杨颖他们两人所举行的世纪婚礼似乎还历历在目,突然间他们就一别两宽了没有代表作品,却能压轴出场的明星,究竟有谁?世界上有那么多人,可娱乐圈总有这么几个人要说娱乐圈,可谓是鱼龙混杂,命运随机会,谁飞升谁入海,都是一部戏一个综艺的事,有很多人是样样精通也没关注度,没有观众缘,可偏偏有这么几个人,P2E区块链游戏赚钱1hr什么是PlaytoEarn?Plantoearn的商业模式在传统游戏由来已久,魔兽世界阴阳师等游戏均有一批玩家通过出售装备或者装备赚钱。而在区块链游戏中,将这种模式进行了升级2022北京冬奥会闭幕式主持人是他?北京时间2022年2月20日晚8点开始冬奥会闭幕式,闭幕式除了吸引人的有我们喜爱的运动员,还有在闭幕式上的主持人!他就是康辉!在冬奥会的闭幕式上,央视主播康辉以闭幕式主持人的身份出格局北京冬奥会的成功,远不止奖牌突破那么简单1937年9月2日,现代奥林匹克之父顾拜旦男爵仙逝之时,他一定不曾想到,百年之后,一个东方大国竟能充分利用现代科技手段,将夏季和冬季奥运会举办的如此美轮美奂,绚丽多彩。纵观百年奥运