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); }