Spring 事件
spring 内置事件
| Event | 说明 |
|---|---|
| ContextRefreshedEvent | 当容器被实例化或refreshed时发布.如调用refresh()方法, 此处的实例化是指所有的bean都已被加载,后置处理器都被激活,所有单例bean都已被实例化, 所有的容器对象都已准备好可使用. 如果容器支持热重载,则refresh可以被触发多次(XmlWebApplicatonContext支持热刷新,而GenericApplicationContext则不支持) |
| ContextStartedEvent | 当容器启动时发布,即调用start()方法, 已启用意味着所有的Lifecycle bean都已显式接收到了start信号 |
| ContextStoppedEvent | 当容器停止时发布,即调用stop()方法, 即所有的Lifecycle bean都已显式接收到了stop信号 , 关闭的容器可以通过start()方法重启 |
| ContextClosedEvent | 当容器关闭时发布,即调用close方法, 关闭意味着所有的单例bean都已被销毁.关闭的容器不能被重启或refresh |
| RequestHandledEvent | 这只在使用spring的DispatcherServlet时有效,当一个请求被处理完成时发布 |
自定义事件
事件类需要继承ApplicationEvent,代码如下:
public class OrderEvent extends ApplicationEvent {
private String name;
public OrderEvent(Object source, String name) {
super(source);
this.name = name;
}
public String getName() {
return name;
}
}
事件监听器-基于接口
@Component
public class HelloEventListener implements ApplicationListener<OrderEvent> {
@Override
public void onApplicationEvent(OrderEvent event) {
if(event.getName().equals("减库存")){
System.out.println("减库存.......");
}
}
}
事件监听器-基于注解
@Component
public class OrderEventListener {
@EventListener(OrderEvent.class)
public void onApplicationEvent(OrderEvent event) {
if(event.getName().equals("减库存")){
System.out.println("减库存.......");
}
}
}
两种方式只是在实现的方式上不同。
事件发布
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class);
ctx.publishEvent(new HelloEvent(this,"xxx"));
}
问题:怎么样可以在所有Bean创建完后做扩展代码?
当Spring容器被实例化或refreshed时发布,会发布ContextRefreshedEvent事件。
只需要监听ContextRefreshedEvent事件,即在所有Bean创建后做扩展代码。
@Component
@Lazy
public class ContextRefreshedEventListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
@EventListener(ContextRefreshedEvent.class)
public void onApplicationEvent(ContextRefreshedEvent event) {
if(event.getApplicationContext().getParent() == null)//root application context 没有parent,他就是老大.
{
//Thread.sleep(5000);
//需要执行的逻辑代码,当spring容器初始化完成后就会执行该方法。
System.out.println("\n\n\n\n\n______________\n\n\n加载了\n\n_________\n\n");
}
}
}
源码
spring的事件监听有三个部分组成:
- 事件(ApplicationEvent) 负责对应相应监听器 事件源发生某事件是特定事件监听器被触发的原因。
- 监听器(ApplicationListener) 对应于观察者模式中的观察者。监听器监听特定事件,并在内部定义了事件发生后的响应逻辑。
- 事件发布器(ApplicationEventMulticaster) 对应于观察者模式中的被观察者/主题, 负责通知观察者 对外提供发布事件和增删事件监听器的接口,维护事件和事件监听器之间的映射关系,并在事件发生时负责通知相关监听器。
spring的事件主要是在ApplicationContext接口的抽象实现类AbstractApplicationContext中完成搭建。
ApplicationContext接口的抽象实现类AbstractApplicationContext中完成。
AbstractApplicationContext在refresh()这个容器启动方法中搭建了事件的基础设施,其中AbstractApplicationContext的refresh方法实现如下:
初始化多播器
用户可以在配置文件中为容器定义一个自定义的事件广播器,只要实现ApplicationEventMulticaster就可以了,Spring会通过 反射的机制将其注册成容器的事件广播器,如果没有找到配置的外部事件广播器,Spring自动使用 SimpleApplicationEventMulticaster作为事件广播器。
注册监听器
Spring根据反射机制,使用ListableBeanFactory的getBeansOfType方法,从BeanDefinitionRegistry中找出所有实现 org.springframework.context.ApplicationListener的Bean,将它们注册为容器的事件监听器,实际的操作就是将其添加到事件广播器所提供的监听器注册表中。
发布事件
进入到具体的实现SimpleApplicationEventMulticaster