ContextStartedEvent ContextRefreshedEvent ContextStoppedEvent ContextClosedEvent
ApplicationEvent
即可完成一个自定义的Spring事件 /** * 自定义事件,继承ApplicationEvent */ @Data public class FirstEventextends ApplicationEvent{ /** * 需要携带的消息,可以是任意类型的数据,相当于传递数据 */ private String message; /** * 构造方法 * @param source 事件发生的类 * @param message 携带的消息 */ public FirstEvent(Object source,String message){ super(source); this.message=message; } }
ApplicationListener @EventListener
创建监听器需要两个条件:
/** * 自定义一个监听器,实现ApplicationListener,指定的泛型就是需要监听的事件 * 监听ContextRefreshedEvent,当容器完成刷新的时候该监听器就会监听到并执行onApplicationEvent方法 */ @Component public class FirstListenerimplements ApplicationListener<ContextRefreshedEvent>{ /** * 重载方法,被监听的事件触发了就会调用这个方法 * @param event 触发事件的对象 */ @Override public void onApplicationEvent(ContextRefreshedEvent event){ System.out.println("容器刷新的监听器启动了........"); System.out.println(event.getSource()+"---->"+event.getTimestamp()+"----"+event.getApplicationContext()); System.out.println("........................................."); } }
此时只要启动容器,自定义的监听器就会起作用,当然我们监听的是Spring内置的事件,在容器启动的时候Spring会使用事件发布器发布事件,此时才是真正的触发事件,我们自定义的事件并不能被监听,除非被事件发布器发布。
classes
:Class数组,指定需要监听的事件 condition
:指定条件,默认监听 /** * 注解方式实现事件监听器 */ @Component public class CustomEventListener{ /** * 使用@EventListener监听事件 * @param event 传入的事件源 */ @EventListener(classes = {ApplicationEvent.class}) public void handlerContextRefreshEvent(ApplicationEvent event){ if (event instanceof ContextRefreshedEvent) { ContextRefreshedEvent e=(ContextRefreshedEvent)event; System.out.println("ContextRefreshedEvent启动了........"); System.out.println(event.getSource() + "---->" + event.getTimestamp() + "----" + e.getApplicationContext()); System.out.println("........................................."); }else if(event instanceof ContextStartedEvent){ ContextStartedEvent e=(ContextStartedEvent)event; System.out.println("ContextStartedEvent启动了........"); System.out.println(event.getSource() + "---->" + event.getTimestamp() + "----" + e.getApplicationContext()); System.out.println("........................................."); }else if(event instanceof ContextStoppedEvent){ ContextStoppedEvent e=(ContextStoppedEvent)event; System.out.println("ContextStoppedEvent启动了........"); System.out.println(event.getSource() + "---->" + event.getTimestamp() + "----" + e.getApplicationContext()); System.out.println("........................................."); }else if(event instanceof ContextClosedEvent){ ContextClosedEvent e=(ContextClosedEvent)event; System.out.println("ContextClosedEvent启动了........"); System.out.println(event.getSource() + "---->" + event.getTimestamp() + "----" + e.getApplicationContext()); System.out.println("........................................."); } } /** * 可以不指定classes,默认监听的是方法参数中的事件 * @param event 事件源 */ @EventListener public void handleFirstEvent(FirstEvent event){ System.out.println("firstEvent事件启动了,。。。。。。。。。"); System.out.println(event.getSource()+"---->"+event.getMessage()); } }
ApplicationEventPublisher
,我们可以自定义自己的类,当然也可以使用spring现成的类
在容器启动刷新的时候已经注入了 ApplicationEventPublisher
的实现,我们可以直接注入使用。如下:
/** * 自定义的事件发布器 */ @Component public class CustomPublisher{ /** * 直接注入ApplicationEventPublisher */ @Autowired private ApplicationEventPublisher applicationEventPublisher; /** * 发布事件 * @param event 指定的事件 */ public void publishEvent(ApplicationEvent event){ applicationEventPublisher.publishEvent(event); } }
测试
@Test public void test1(){ CustomPublisher customPublisher = applicationContext.getBean(CustomPublisher.class); customPublisher.publishEvent(new FirstEvent(this,"启动自定义事件")); }
/** * 自定义的事件发布器,实现ApplicationEventPublisherAware接口 */ @Component public class CustomPublisherimplements ApplicationEventPublisherAware{ private ApplicationEventPublisher applicationEventPublisher; /** * 发布事件 * @param event 指定的事件 */ public void publishEvent(ApplicationEvent event){ applicationEventPublisher.publishEvent(event); } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher){ this.applicationEventPublisher=applicationEventPublisher; } }
ApplicationEventMulticaster
】? AbstractApplicationEventMulticaster
、 SimpleApplicationEventMulticaster
org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType)
这个方法中,如下: @Override public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType){ ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); //遍历事件监听器 for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { //判断是否设置了Executor,如果存在,那么就异步执行 Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(() -> invokeListener(listener, event)); } else { //否则的话,同步执行,调用invokeListener invokeListener(listener, event); } } } /****************************************invokeListener******************************/ protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event){ //如果有异常处理器,就try-catch执行 ErrorHandler errorHandler = getErrorHandler(); if (errorHandler != null) { try { doInvokeListener(listener, event); } catch (Throwable err) { //如果有异常了,执行异常处理器的handleError方法 errorHandler.handleError(err); } } else { //没有异常处理器直接执行 doInvokeListener(listener, event); } } /*******************************doInvokeListener****************************/ private void doInvokeListener(ApplicationListener listener, ApplicationEvent event){ try { //此时真正调用监听器中的方法 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.isDebugEnabled()) { logger.debug("Non-matching event type for listener: " + listener, ex); } } else { throw ex; } } }
Spring中可以使用 @Async
注解标注方法异步执行,不过需要在配置类上开启异步功能,使用 @EnableAsync
注解,如下:
@Configuration @ComponentScan(value = {"cn.tedu.demo"}) @EnableAsync public class FirstConfig{ }
此时可以在监听方法上标注 @Async
注解,使得事件异步执行
/** * 注解方式实现事件监听器 */ @Component public class CustomEventListener{ /** * 可以不指定classes,默认监听的是方法参数中的事件 * @Async : 指定这个方法异步执行 * @param event 事件源 */ @EventListener @Async public void handleFirstEvent(FirstEvent event){ System.out.println("firstEvent事件启动了,。。。。。。。。。"); System.out.println(event.getSource()+"---->"+event.getMessage()); } }
SimpleApplicationEventMulticaster
,我们可以自己注入一个多播器直接使用即可。 源码如下:
protected void initApplicationEventMulticaster(){ ConfigurableListableBeanFactory beanFactory = getBeanFactory(); //判断ioc容器中是否存在id为applicationEventMulticaster事件多播器 if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { //直接使用ioc容器中的 this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isTraceEnabled()) { logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { //新建一个,不过没有设置TaskExector 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() + "]"); } } }
从源码中【 org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType)
】我们可以看出监听器的执行是先判断多播器中是否存在 Executor
,如果存在,那么就单独开启一个线程执行,否则就同步执行,我们在初始化多播器的时候,可以为其设置一个 Executor
,那么就可以异步执行了。
@Override public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType){ ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(() -> invokeListener(listener, event)); } else { invokeListener(listener, event); } } }
实现:在配置类注入一个多播器即可,bean的id一定要是 applicationEventMulticaster
,同时为其设置一个 executor
/** * 自定义一个事件多播器,用来管理监听器和执行监听器 * @return */ @Bean(name = "applicationEventMulticaster") public ApplicationEventMulticaster applicationEventMulticaster(){ //事件多播器 SimpleApplicationEventMulticaster simpleApplicationEventMulticaster=new SimpleApplicationEventMulticaster(); //设置executor SimpleAsyncTaskExecutor executor=new SimpleAsyncTaskExecutor(); simpleApplicationEventMulticaster.setTaskExecutor(executor); //设置一个事件异常处理器,当监听器执行出现错误了会进行补救 simpleApplicationEventMulticaster.setErrorHandler(t->{ //这里可以针对不同的异常进行处理,在监听器中trycatch,不同执行抛出不同异常即可分类处理 System.out.println("监听事件执行报错了"); System.out.println(t.getMessage()); }); return simpleApplicationEventMulticaster; }
refresh
方法中: initApplicationEventMulticaster()
:初始化事件多播器 registerListeners();
:注册事件监听器 finishRefresh()
方法中调用 publishEvent(new ContextRefreshedEvent(this))
方法发布容器刷新事件。