spring的事件及监听和ApplicationContext
ApplicationContext中的事件处理都是通过applicationEvent类和ApplicationListener接口来实现的。在spring发展历史上从spring4.2开始一直到spring5和springBoot新增了注解实现。所以现在分为编程式实现和注解实现。
老版本xml配置实现事件及监听的实现
①自定义事件(继承ApplicationEvent)
1 public class MyEvent extends ApplicationEvent { 2 public RainEvent(Object source) { 3 super(source); 4 } 5 }
②监听器类RainListener1和RainListener2
RainListener1
1 public class RainListener1 implements ApplicationListener<MyEvent>{ 2 3 @Override 4 public void onApplicationEvent(MyEvent event) { 5 System.out.println("唐僧大喊:" + event.getSource() + "赶快收衣服喽!"); 6 } 8 }
RainListener12
1 public class RainListener2 implements ApplicationListener<MyEvent>{ 3 public void onApplicationEvent(MyEventevent) { 4 System.out.println("我们:" + event.getSource() + "太好了不用上课了!"); 5 } 6 }
③xml配置
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 7 http://www.springframework.org/schema/context 8 http://www.springframework.org/schema/context/spring-context-3.2.xsd"> 9 <!-- 把监听器注册到spring容器中 --> 10 <!-- 通过spring容器发布事件后,监听器会调用指定方法进行处理 --> 11 <bean class="com.lut.eventListener.MyListener2"></bean> 12 <bean class="com.lut.eventListener.MyListener1"></bean> 13 </beans>
④main方法实现
1 String path = "com/lut/eventListener/event.xml";2 ApplicationContext container = 3 new ClassPathXmlApplicationContext(path); 4 container.publishEvent(new RainEvent("下雨了!"));
结果(顺序和xml配置顺序相关。):
我们:下雨了!太好了不用上课了!
唐僧大喊:下雨了!赶快收衣服喽!
springBoot下的实现
自定义事件
1 package lut.eventlistener; 2 import org.springframework.context.ApplicationEvent; 3 public class Myevent extends ApplicationEvent { 4 String name ; 5 String age; 6 public Myevent(Object source,String name,String age) { 7 super(source); 8 this.age=age; 9 this.name=name; 10 } 11 public Myevent(Object source) { 12 super(source); 13 } 14 }
2、监听
实现1非注解(implements ApplicationListener<Myevent>)
1 package lut.eventlistener; 2 3 import org.springframework.context.ApplicationListener; 4 import org.springframework.scheduling.annotation.Async; 5 import org.springframework.stereotype.Component; 6 7 @Component 8 public class ProcessListener implements ApplicationListener<Myevent> { 9 @Async 10 @Override 11 public void onApplicationEvent(Myevent event) { 12 try { 13 Thread.sleep(2000); 14 } catch (InterruptedException e) { 15 e.printStackTrace(); 16 } 17 System.out.println("监听到了:"+event.getSource()+event.name+"--"+event.age); 18 } 19 }
注解方式
1 package lut.eventlistener; 2 3 import org.springframework.context.event.EventListener; 4 import org.springframework.stereotype.Component; 5 6 @Component 7 public class AnnListener { 8 @EventListener 9 public void say(Myevent event){ 10 System.out.println("注解监听到了:"+event.getSource()+event.name+"--"+event.age); 11 } 12 }
3、controller方法
package lut.eventlistener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class EventController { @Autowired private ApplicationContext context; @RequestMapping("event") public String getEvent(){ context.publishEvent(new Myevent("相遇了","xiaogang","12")); System.out.println("controller执行到return了"); return "hello"; } }
结果:
非注解结果
监听到了:相遇了xiaogang--12
controller执行到return了
----------------------------------------------------------------------
注解结果:2种监听可同时存在注解打印在非注解打印输出之前
注解监听到了:相遇了xiaogang--12(注解式的输出)
监听到了:相遇了xiaogang--12(非注解式的输出)
controller执行到return了
总结:
ApplicationEvent和ApplicationListener抽象类的接口到spring 5 一直未改变。
ApplicationEvent源码:
package org.springframework.context; import java.util.EventObject; * @author Rod Johnson * @author Juergen Hoeller * @see org.springframework.context.ApplicationListener * @see org.springframework.context.event.EventListener */ public abstract class ApplicationEvent extends EventObject { /** use serialVersionUID from Spring 1.2 for interoperability. */ private static final long serialVersionUID = 7099057708183571937L; /** System time when the event happened. */ private final long timestamp; /** * Create a new {@code ApplicationEvent}. * @param source the object on which the event initially occurred or with * which the event is associated (never {@code null}) */ public ApplicationEvent(Object source) { super(source); this.timestamp = System.currentTimeMillis(); } /** * Return the system time in milliseconds when the event occurred. */ public final long getTimestamp() { return this.timestamp; } }
ApplicationListener源码:
/* * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.context; import java.util.EventListener; /** * Interface to be implemented by application event listeners. * * <p>Based on the standard {@code java.util.EventListener} interface * for the Observer design pattern. * * <p>As of Spring 3.0, an {@code ApplicationListener} can generically declare * the event type that it is interested in. When registered with a Spring * {@code ApplicationContext}, events will be filtered accordingly, with the * listener getting invoked for matching event objects only. * * @author Rod Johnson * @author Juergen Hoeller * @param <E> the specific {@code ApplicationEvent} subclass to listen to * @see org.springframework.context.ApplicationEvent * @see org.springframework.context.event.ApplicationEventMulticaster * @see org.springframework.context.event.EventListener */ @FunctionalInterface public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { /** * Handle an application event. * @param event the event to respond to */ void onApplicationEvent(E event); }