核心事件ApplicationContext中的事件处理是通过ApplicationEvent类和ApplicationListener接口提供的。如果一个bean将实现ApplicationListener接口,则只要ApplicationEvent发布到ApplicationContext,该bean就会收到通知。本质上,这是标准的观察者设计模式。从Spring4.2开始,事件基础设施得到了显着改进,提供了基于注释的模型和发布任意事件的能力(即,不一定是从ApplicationEvent扩展的对象)。当发布这样的对象时,我们将其包装在一个事件中。下表列出了Spring提供的标准事件:EventExplanationContextRefreshedEvent在ApplicationContext初始化或刷新时发布(例如,通过使用ConfigurableApplicationContext接口上的refresh()方法)。这里的“初始化”意味着所有的bean都被加载,后处理器bean被检测和激活,单例被预实例化,ApplicationContext对象就可以使用了。只要上下文未关闭,就可以多次触发刷新,前提是所选的ApplicationContext实际上支持此类“热”刷新。当使用ConfigurableApplicationContext接口上的start()方法启动ApplicationContext时,将发布ContextStartedEvent。在这里,“已启动”意味着所有生命周期bean都收到一个明确的启动信号。通常,此信号用于在显式停止后重新启动beans,但也可用于启动未配置为自动启动的组件(例如,在初始化时未启动的组件)。当使用ConfigurableApplicationContext接口上的stop()方法停止ApplicationContext时,将发布ContextStoppedEvent。在这里,“停止”意味着所有生命周期bean都收到一个明确的停止信号。可以使用start()调用重新启动已停止的上下文。当使用ConfigurableApplicationContext接口上的close()方法或通过JVM关闭挂钩关闭ApplicationContext时,将发布ContextClosedEvent。在这里,“关闭”意味着所有单例bean都将被销毁。一旦上下文关闭,它就达到了生命周期的终点,无法刷新或重新启动。RequestHandledEvent一个特定于Web的事件,它告诉所有bean已为HTTP请求提供服务。此事件在请求完成后发布。此事件仅适用于使用Spring的DispatcherServlet的Web应用程序。添加特定于servlet的上下文信息的ServletRequestHandledEventRequestHandledEvent的子类。以上事件发布时:ContextRefreshedEventpublicabstractclassAbstractApplicationContextextendsDefaultResourceLoaderimplementsConfigurableApplicationContext{publicvoidrefresh(){//...finishRefresh();}}ContextStartedEventpublicabstractclassAbstractApplicationContextextendsDefaultResourceLoaderimplementsConfigurableApplicationContext{publicvoidrefresh(){//...finishRefresh();}protectedvoidfinishRefresh(){//初始化LifecycleProcessor(DefaultLifecycleProcessor)initLifecycleProcessor();getLifecycleProcessor().onRefresh();}publicvoidstart(){getLifecycleProcessor().start();发布事件(新的ContextStartedEvent(这个));}}publicclassDefaultLifecycleProcessorimplementsLifecycleProcessor,BeanFactoryAware{publicvoidstart(){startBeans(false);这个。运行=真;}}ContextStoppedEvent该事件与上面的started是对应的publicabstractclassAbstractApplicationContextextendsDefaultResourceLoaderi实施ConfigurableApplicationContext{publicvoidstop(){getLifecycleProcessor().stop();发布事件(新的ContextStoppedEvent(这个));}}publicclassDefaultLifecycleProcessorimplementsLifecycleProcessor,BeanFactoryAware{publicvoidstop(){stopBeans();这个。运行=假;}}ContextClosedEventpublicabstractclassAbstractApplicationContextextendsDefaultResourceLoaderimplementsConfigurableApplicationContext{publicvoidclose(){synchronized(this.startupShutdownMonitor){doClose();}}protectedvoiddoClose(){publishEvent(newContextClosedEvent(this));}}ServletRequestHandledEventpublicabstractclassFrameworkServlet{protectedfinalvoidprocessRequest(HttpServletRequestrequest,HttpServletResponseresponse){publishRequestHandledEvent(request,response,startTime,failureCause);}privatevoidpublishRequestHandledEvent(HttpServletRequest请求,HttpServletResponse响应,longstartTime,@NullableThrowablefailureCause){if(this.publishEvents&&this.webApplicationContext!=null){//无论我们是否成功,都发布一个事件。longprocessingTime=System.currentTimeMillis()-开始时间;this.webApplicationContext.publishEvent(newServletRequestHandledEvent(this,request.getRequestURI(),request.getRemoteAddr(),request.getMethod(),getServletConfig().getServletName(),WebUtils.getSessionId(请求),getUsernameForRequest(请求),processingTime,failureCause,response.getStatus()));}}}你还可以创建和发布自己的自定义事件以下示例显示了一个扩展Spring的ApplicationEvent基类的简单类:publicclassBlockedListEventextendsApplicationEvent{privatefinalStringaddress;私有最终字符串内容;publicBlockedListEvent(Objectsource,Stringaddress,Stringcontent){super(source);this.address=地址;this.content=内容;}}要发布自定义ApplicationEvent,需要调用ApplicationEventPublisher的publishEvent()方法。通常,这是通过创建一个实现ApplicationEventPublisherAware的类并将其注册为Springbean来完成的。下面的例子展示了这样一个类:publicclassEmailServiceimplementsApplicationEventPublisherAware{privateListblockedList;私有ApplicationEventPublisher发布者;publicvoidsetBlockedList(ListblockedList){this.blockedList=blockedList;}publicvoidsetApplicationEventPublisherAppPublisher(){this.publisher=publisher;}publicvoidsendEmail(Stringaddress,Stringcontent){if(blockedList.contains(address)){publisher.publishEvent(newBlockedListEvent(this,address,content));返回;在配置期间,Spring容器检测到EmailService实现了ApplicationEventPublisherAware并自动调用setApplicationEventPublisher()。其实传入的参数就是Spring容器本身。通过ApplicationEventPublisher接口与应用上下文交互。要接收自定义ApplicationEvents,请创建一个实现ApplicationListener的类并将其注册为Springbean。下面的例子展示了这样一个类:publicclassBlockedListNotifierimplementsApplicationListener{privateStringnotificationAddress;publicvoidsetNotificationAddress(StringnotificationAddress){this.notificationAddress=notificationAddress;}publicvoidonApplicationEvent(BlockedListEvent}eventApplicationListener通常参数化为自定义事件的类型。这意味着onApplicationEvent()方法可以保持类型安全,避免任何向下转换的需要。您可以注册任意数量的事件侦听器,但是请注意,默认情况下,事件侦听器同步接收事件。这意味着publishEvent()方法会阻塞,直到所有侦听器完成对事件的处理。这种同步和单线程方法的一个优点是,当侦听器接收到事件时,它如果可用,将在发布者的事务上下文中运行。BlockedListNotifier可以重写为:publicclassBlockedListNotifier{privateStringnotificationAddress;publicvoidsetNotificationAddress(StringnotificationAddress){this.notificationAddress=notificationAddress;}@EventListenerpublicvoidprocessBlockedListEvent(@BlockedListEvent}Listenevent同时监听多个事件){}{ContextStartedEvent.class,ContextRefreshedEvent.class})publicvoidhandleContextStart(){}异步事件如果你想让特定的监听器处理事件异步地,您可以重用常规的@Async支持。如下例所示:@EventListener@AsyncpublicvoidprocessBlockedListEvent(BlockedListEventevent){}使用异步事件时,请注意以下限制:如果异步事件侦听器抛出异常,则不会将异常传播给调用者。异步事件侦听器方法无法通过返回值发布后续事件。如果处理后需要发布另一个事件,请注入ApplicationEventPublisher以手动发布事件。事件监听顺序如果需要在调用另一个监听器之前先调用一个监听器,可以在方法声明中添加@Order注解,如下例所示:@EventListener@Order(1)publicvoidprocessBlockedListEvent(BlockedListEventevent){}通用事件您还可以使用泛型来进一步定义事件的结构。考虑使用EntityCreatedEvent,其中T是实际创建的实体的类型。例如,您可以创建以下侦听器定义以仅接收Person的EntityCreatedEvent:@EventListenerpublicvoidonPersonCreated(EntityCreatedEventevent){}由于类型擦除,只有在事件侦听器过滤器的通用参数(That也就是说,它仅在PersonCreatedEvent类扩展EntityCreatedEvent{...}时有效。事件触发原理式1:ApplicationEventPublisherAbstractApplicationContext实现了ApplicationEventPublisher接口,那么只要ApplicationContext继承自AbstractApplicationContext都可以直接发布事件:publicabstractclassAbstractApplicationContextapplication{protectedvoidpublishEventevent,ApplicationReventable;if(eventinstanceofApplicationEvent){applicationEvent=(ApplicationEvent)事件;}else{applicationEvent=newPayloadApplicationEvent<>(this,event);if(eventType==null){eventType=((PayloadApplicationEvent>)applicationEvent).getResolvableType();}}if(this.earlyApplicationEvents!=null){this.earlyApplicationEvents.add(applicationEvent);}else{getApplicationEventMulticaster().multicastEvent(applicationEvent,eventType);}if(this.parent!=null){if(this.parentinstanceofAbstractApplicationContext){((AbstractApplicationContext)this.parent).publishEvent(event,eventType);}else{this.parent.publishEvent(事件);}}}}方法二:@EventListener注解该注解由EventListenerMethodProcessor处理器处理公共类EventListEnerMethodProcessor实现smartInitializingsingleton,applicationContextAware,beanfactorypostprocestor{publicvoidpostprocessBeanFactory(configurablistablebeanfactorybeanfactory){/////,错误的);}publicvoidafterSingletonsInstantiated(){String[]beanNames=beanFactory.getBeanNamesForType(Object.class);for(StringbeanName:beanNames){processBean(beanName,类型);}}privatevoidprocessBean(finalStringbeanName,finalClass>targetType){MapannotatedMethods=null;try{//获取bean中用@EventListener注解注解的方法annotatedMethods=MethodIntrospector.selectMethods(targetType,(MethodIntrospector.MetadataLookup)method->AnnotatedElementUtils.findMergedAnnotation(method,EventListener.class));}//遍历所有找到的@EventListener注解方法for(Methodmethod:annotatedMethods.keySet()){//遍历所有EventListenerFactoryfor(EventListenerFactoryfactory:factories){//判断当前事件监听工厂是否支持当前方法if(factory.supportsMethod(method)){MethodmethodToUse=AopUtils.selectInvocableMethod(method,context.getType(beanName));//创建对应的事件监听器ApplicationListener>applicationListener=factory.createApplicationListener(beanName,targetType,methodToUse);if(applicationListenerinstanceofApplicationListenerMethodAdapter){((ApplicationListenerMethodAdapter)applicationListener).init(context,this.evaluator);}context.addApplicationListener(applicationListener);休息;}}}}