spring事件驱动模型--观察者模式
观察者模式的本质是"对象之间定义一个一对多的依赖,这样,当一个对象的状态发生改变,其所有监听者得到通知
Spring通过ApplicationEvent类和ApplicationListener的接口提供ApplicationContext的事件处理。如果一个bean实现了ApplicationListener的接口并被部署到,如果容器内发生了ApplicationEvent,这个监听bean将收到它
Spring自带了内置事件ContextStartedEvent,ContextRefreshedEvent, ContextStoppedEvent等,你也可以创建自己的自定义事件。
使用观察者模式,有三个类是必须的:

1:事件广播器的初始化
用户可以在配置文件中自定义的事件广播器,编号必须为 applicationEventMulticaster,只要实现ApplicationEventMulticaster就可以了,Spring会将其注册成容器的事件广播器,
如果没有找到配置的外部事件广播器,Spring自动使用 SimpleApplicationEventMulticaster作为事件广播器。

2: 注册事件监听器:
定义实现 ApplicationListener 接口的bean, 通过调用registerListeners()方法, 使用 ListableBeanFactory 的getBeanNamesForType方法,从BeanDefinitionRegistry中找出所有实现 ApplicationListener 的Bean,将它们注册为容器的事件监听器,实际的操作就是将其添加到事件广播器所提供的监听器注册表中。

3: 发布事件
在AbstractApplicationContext的 publishEvent 方法中, Spring委托ApplicationEventMulticaster将事件通知给所有的事件监听器


以下是一个简单的Demo
1:定义一个ApplicationEvent
public class MessageEvent extends ApplicationEvent { private static final long serialVersionUID = -1184214144591672917L; public MessageEvent(Object source) { super(source); System.out.println("source=" + source); } @Override public String toString() { System.out.println("MessageEvent toString()"); return super.toString(); } }
2: 建立事件处理类, 需要实现ApplicationListener接口
public class ResponseHandler implements ApplicationListener<MessageEvent> { @Override public void onApplicationEvent(MessageEvent event) { System.out.println("[ResponseHandler]event=" + event); } }
3:在配置文件中配置ResponseHandler,使用默认的 SimpleApplicationEventMulticaster,
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool.xsd"> <bean id="responseHandler" class="com.mountain.springdemo.entity.ResponseHandler" /> <task:executor id="pool" pool-size="10" /> <bean id="applicationEventMulticaster" class="org.springframework.context.event.SimpleApplicationEventMulticaster"> <property name="taskExecutor" ref="pool" /> </bean>
运行如下结果如下:
public static void main(String[] args) {
AbstractApplicationContext appContext = new ClassPathXmlApplicationContext("/applicationContext.xml");
appContext.publishEvent(new MessageEvent("okkkkk"));
System.out.println("END...");
}
配置文件中配置了Executor , 并且指定了线程池大小,会生成一个默认的Executor(ThreadPoolTaskExecutor ), 从输出结果可以看出,明显是异步执行。
source=okkkkk 2018-08-04 20:11:15,529 [main] DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Returning cached instance of singleton bean 'responseHandler' END... MessageEvent... [ResponseHandler]event=com.mountain.spring.MessageEvent[source=okkkkk]
以上代码中我直接使用了ApplicationContext对象, 不过可以通过实现ApplicationContextAware接口来得到ApplicationContext对象
public class MyApplicationContextAware implements ApplicationContextAware { private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } public void publishEvent(MessageEvent event){ System.out.println("[MyApplicationContextAware->publishEvent]"); applicationContext.publishEvent(event); } }
通过获取 MyApplicationContextAware来得到ApplicationContext,完成事件发布操作。
参考: https://www.cnblogs.com/fingerboy/p/6393644.html

浙公网安备 33010602011771号