Spring入门之事件处理
程序员文章站
2022-05-14 17:54:07
...
面向接口编程简述
面向接口编程,也就是非面向实现。它不能通过抽象类取代接口,因为:接口目的是抽象,抽象类目的是复用
同时还有一个好处: 接口是可以多实现的,类/抽象类只能单继承,所以使用接口可以非常容易扩展新功能(还可以实现所谓的mixin),类/抽象类办不到
Spring事件机制–事件驱动模型/观察者抽象
事件驱动模型也就是我们常说的观察者,或者发布-订阅模型;理解它的几个关键点:
1.首先是一种对象间的一对多的关系;最简单的如交通信号灯,信号灯是目标(一方),行人注视着信号灯(多方);
2.当目标发送改变(发布),观察者(订阅者)就可以接收到改变;
3.观察者如何处理(如行人如何走,是快走/慢走/不走,目标不会管的),目标无需干涉;所以就松散耦合了它们之间的关系。
Spring事件驱动模型/观察者模型的结构图:
Spring的事件
具体代表者是:ApplicationEvent
1、其继承自JDK的EventObject,JDK要求所有事件将继承它,并通过source得到事件源,比如我们的AWT事件体系也是继承自它;
2、系统默认提供了如下ApplicationEvent事件实现:
1.ContextStartedEvent:ApplicationContext启动后触发的事件;通过调用ConfigurableApplicationContext容器对象的start方法可以触发该事件
2.ContextStoppedEvent:ApplicationContext停止后触发的事件;通过调用ConfigurableApplicationContext容器对象的stop方法可以触发该事件
3.ContextRefreshedEvent:ApplicationContext初始化或刷新完成后触发的事件;(容器初始化完成后调用)
4.ContextClosedEvent:ApplicationContext关闭后触发的事件;(如web容器关闭时自动会触发spring容 器的关闭,如果是普通java应用,需要调用ctx.registerShutdownHook();注册虚拟机关闭时的钩子才行)
目标:事件发布者
具体代表者是:ApplicationEventPublisher及ApplicationEventMulticaster
ApplicationContext接口继承了ApplicationEventPublisher,并在 AbstractApplicationContext实现了具体代码,实际执行是委托给ApplicationEventMulticaster(可以 认为是多播):ApplicationContext都继承自AbstractApplicationContext,比如ClassPathXmlApplicationContext、FileSystemXmlApplication Context等,所以ApplicationContext自动拥有事件发布的功能
ApplicationContext自动到本地容器里找一个名字为”executor“的ApplicationEventMulticaster实现,如果 没有自己new一个SimpleApplicationEventMulticaster。
所以我们发送事件只需要通过ApplicationContext.publishEvent即可,没必要再创建自己的实现了。除非有必要。
Spring的监听器
具体代表者是:ApplicationListener;其继承自JDK的EventListener,JDK要求所有监听器将继承它,比如我们的AWT事件体系也是继承自它;其实现代码:
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}
从代码中可以看出,它只提供了一个onApplicationEvent事件处理方法,虽然这样实现起来就很简单,不过有时候还需要提供顺序触发监听器的操作,因此,Spring提供了另一个接口: SmartApplicationListener,它实现了Ordered接口,还可以方便我们去判断支持的事件类型。实现代码如:
public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
//如果实现支持该事件类型 那么返回true
boolean supportsEventType(Class<? extends ApplicationEvent> eventType);
//如果实现支持“目标”类型,那么返回true
boolean supportsSourceType(Class<?> sourceType);
//顺序,即监听器执行的顺序,值越小优先级越高
int getOrder();
}
Spring内置事件处理机制实例
//StartListener define
public class StartListener implements ApplicationListener<ContextStartedEvent> {
@Override
public void onApplicationEvent(ContextStartedEvent arg0) {
System.out.println("application starting...");
}
}
//stopListener define
public class StopedListener implements ApplicationListener<ContextStoppedEvent> {
@Override
public void onApplicationEvent(ContextStoppedEvent arg0) {
System.out.println("context stopped..");
}
}
//beans.xml配置
<!-- 注入事件监听器 -->
<bean id="startEvent" class="org.spring.event.StartListener" />
<bean id="stopEvent" class="org.spring.event.StopedListener" />
//测试主程序
public class TestMain {
public static void main(String[] args){
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
context.start();
System.out.println("running...");
context.stop();
}
}
Spring自定义事件
首先定义一个自定义事件类PersonalEvent类,继承自ApplicationEvent
public class PersonalEvent extends ApplicationEvent {
private static final long serialVersionUID = 1L;
//初始化获取事件源
public PersonalEvent(Object source) {
super(source);
}
}
然后定义事件处理器用于对事件进行相应的处理,该事件处理器继承自ApplicationListener
public class PersonalEventHnadler implements ApplicationListener<PersonalEvent> {
@Override
public void onApplicationEvent(PersonalEvent event) {
System.out.println("event.name->"+event.toString());
}
}
再定义一个发布类用于发布事件,该类继承自ApplicationEventPublisherAware,可以在该类中调用publishEvent方法来发布事件,也可以在主程序中直接调用ApplicationContext容器对象的publishEvent方法来发布事件
public class PersonalEventPublisher implements ApplicationEventPublisherAware {
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
// TODO Auto-generated method stub
this.publisher = applicationEventPublisher;
}
public void publish(){
PersonalEvent personalEvent = new PersonalEvent(this);
publisher.publishEvent(personalEvent);
}
}
主程序测试
public class TestMain {
public static void main(String[] args){
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
PersonalEventPublisher publisher = context.getBean("personalEventPublisher",PersonalEventPublisher.class);
//publisher发布事件
publisher.publish();
//Ioc容器直接发布事件
PersonalEvent personalEvent = new PersonalEvent();
context.publishEvent(personalEvent);
}
}
参考文档
Spring中实现自定义事件
Spring 中的自定义事件
spring事件机制
上一篇: 浅谈android应用之事件分发
下一篇: Qt之事件处理机制