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

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); 	}
iPhone13正式在巴西生产,iPhone12沦为白菜机刷新爱疯纪录截至4月28日,虽然绝大多数苹果产品在中国组装,但苹果的代工制造商富士康也在其他几个国家组装苹果iPhone。现在,富士康已经开始在巴西生产iPhone13,但iPhone13mi租赁只需49美元!苹果正式推出自助维修服务去年,苹果宣布了其自助维修计划,该计划为iPhone12和13系列以及更新的iPhoneSE2022带来了200多种原装苹果零件和维修工具。该计划现已在美国推出,因此美国的用户可以广东对符合条件的新能源汽车消费者补贴8000元辆中新财经4月29日电29日,广东省发改委发布广东省新能源汽车购置补贴活动公告,公告显示,个人消费者在省内购买广东省汽车以旧换新专项行动推广车型范围内的新能源汽车新车,并在省内完成机谷歌拍摄俄罗斯军事基地,俄罗斯的秘密被看光?我们的秘密呢?前几天,谷歌用卫星拍摄了俄罗斯的军事基地,精度达到50厘米,飞机,坦克,导弹一览无余,在世界引起了轩然大波!到底怎么回事呢?2022年4月18日,谷歌公司突然之间在其搜索平台上公开比亚迪一周惊现3起员工跳楼事件,有死者遗书曝光,警方在正调查去年11月员工猝死事件过去没多久,新能源汽车巨头比亚迪再次陷入舆论漩涡。据百姓关注九派新闻报道,湖南长沙,比亚迪员工称在雨花区公司职工宿舍一周内连续发生了跳楼事件。据该比亚迪员工爆linux之mktemp命令创建临时文件供shell脚本使用补充说明mktemp命令被用来创建临时文件供shell脚本使用。命令语法mktemp(选项)(参数)命令选项q执行时若发生错误,不会显示任何信息u暂基因变异次数揭开动物寿命奥秘参考消息网4月27日报道据英国广播公司网站4月18日报道,研究人员发现,从老虎到人类的多种哺乳动物从出生到死亡经历的基因变异次数大致相同。这项对16个物种进行的研究表明,寿命短的动刘强东性侵案已经沉默了两年多,为什么还没结束?刘强东会输掉这个案子吗?前天,刘强东案件在美国召开听证会,前面说那个状告刘强东性侵的女大学生会亲自出庭,后面又说听证会取消了,搞得中国网民啊,非常惊讶。之前大家都以为这个案子早就结卖一辆亏一万!多家车企紧急停售,微型电动车生意不好做本文来源时代财经作者张旭继欧拉白猫黑猫之后,又一款A00级新能源车型停止接单。日前,长安新能源发布公告称,近期受上游原材料短缺,以及整车和零部件产能限制等因素影响,奔奔EStar国三轮问询回复后,帕瓦股份5月6日迎来科创板IPO上会4月27日,资本邦了解到,上海证券交易所科创板上市委员会定2022年5月6日上午9时召开2022年第36次上市委员会审议会议。届时将审议浙江帕瓦新能源股份有限公司科创板IPO审核。截至今年5月份,这三款千元机依然香到爆,德才兼备的代表很多人认为便宜无好货,但其实并不全是,性价比好物可遇不可求,这三款千元机能刷新你的印象,不仅性能过硬,并且各有优势,预算不足的朋友们不妨了解一下。iPhoneXSMaxiPhone
仅次于苹果三星,vivo收入Q1排名第三谁知道今年智能手机格局因为华为的原因将发生巨变,但无论怎么变化三星苹果的地位目前还是无人可以撼动的,三星的地位在于全球出货量第一,苹果的地位在于全球收入第一。5月31日知名的数据调不用再担心新能源汽车的弊端了,这三款超长续航颜值还高这几年以来,新能源汽车来势汹汹,抢占了不少燃油车的市场。主要是因为现在燃油车的数量太多,燃油车的使用会有大量的尾气排放,加重空气污染,而新能源汽车就能很好地缓解这个问题。为了减少对小米汽车新动向雷军考察五菱宏光MINI或将合作打造车界红米日前,小米创始人雷军现身上汽通用五菱柳州生产基地,参观了目前市场上最畅销的电动汽车五菱宏光MINIEV。据悉,雷军此行参观了上汽通用五菱新能源车生产车间,并与上汽通用五菱总经理沈阳618苏宁Super会员有多香超大优惠,开卡续费倒赚41元如今,会员意味着能享受诸多特别福利,传统电商平台的会员是能以更低的价格买到产品,而当苏宁易购的会员就不一样,不仅能享受更给力的直降优惠,而且还有白嫖省钱领红包的机会,幸福指数更高。你的手机用多久才更换手机这个东西更新换代太快了,我不明白为什么这么多人都急着更换能用的手机。什么果粉,花粉,米粉,只要一上新,马上就得更换,买不到甚至加价找黄牛也得弄过来。一部手机好几千块,基本上手机小米公布最新快充技术八分钟即可为手机充满电来源环球网环球网科技综合报道据悉,雷军5月31日在其微博上发文称,小米首发200W有线快充以及120W无线快充,200W有线8分钟充满,120W无线15分钟充满,打破两项手机充电纪停用华为,瑞典代价如何?爱立信再度发声,中瑞关系走向何方?近日,爱立信对于瑞典政府将华为等中国电信供应商排除在5G网络建设之外的行为再次公开发声,认为瑞典政府的行为严重削弱了爱立信在中国市场的竞争力,并将为爱立信之后在华市场份额和发展前景抢占六一儿童节!苏宁易购注册六一宝宝节日商标走自己的路,让别人无路可走。大约说的就是苏宁易购这波操作。苏宁易购今年618大促期间,不仅着力将6月1日打造成为六一宝宝节,而且已经提交了六一宝宝节的商标申请,隶属第35类,广告销想买个蓝牙无线耳机,求条友们推荐下品牌型号,价位500元左右哪种比较好?500多块钱的蓝牙耳机我倒是没买过,但我用的是JEET蓝牙耳机,最多也就300多块钱,而且它带给我的蓝牙耳机就很好,音质超棒,打游戏超爽,通话也流畅,而且它戴在耳朵上很舒服它的知名华为又被质疑?连华为的研发人员也被惹怒了华为作为一家科技企业,一直在质疑声和吐槽中不断砥砺前行,一次次让质疑和吐槽他的人狠狠打脸。可是,让很多人想不到是,华为有一天会因为自己打脸遭到大家的质疑,而这次连华为研发人员也被惹5款高质量的学习类小程序,赶紧收藏起来,或许能辅助你的学习微信的使用也带动了小程序的使用,很多人现在也会选择在微信小程序上学习一些知识和内容,今天我为大家带来几款学习上的小程序,让你的学习通过小程序来变得更简单一些,需要的可以自己点个赞收