说到事件监听,想到的肯定是观察者模式。但是这儿主要说下spring中的监听是怎么样的流程。
这就不得不说到spring容器的refresh方法,容器启动过程中,listener相关的主要是这个三个方法:initApplicationEventMulticaster方法初始化事件多播器,后续的事件发布都是由多播器来发布的;registerListeners注册监听器到前面初始化好的多播器上面去;
finishRefresh容器启动完成最后刷新,发布ContextRefreshedEvent事件。
1.初始化多播器:获取bean工厂对象ConfigurableListableBeanFactory,判断容器中是否有applicationEventMulticaster多播器,如果没有则创建一个一个简单事件多播器SimpleApplicationEventMulticaster并注册到容器中,后续使用
2.注册监听器到多播器上并发布早期事件:首先获取容器中已有的监听器(成品对象),注册到多播器;然后获取bean定义中的监听器,也就是我们自己定义的监听器;同样也注册到多播器上去;最后如果有早期事件就去发布早期事件,multicastEvent方法
发布事件:multicastEvent方法----->invokeListener方法---->doInvokeListener方法调用监听器的onApplicationEvent
3.执行finishRefresh方法发布ContextRefreshedEvent事件,标志的容器已经启动完成。
监听器的流程完了,我们现在来看下使用
首先实现一个自己的监听器
package com.nijunyang.spring.listener; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; /** * Description: * Created by nijunyang on 2020/2/20 21:53 */ @Component public class MyListener implements ApplicationListener<ApplicationEvent> { @Override public void onApplicationEvent(ApplicationEvent event) { System.out.println("收到事件:" + event.toString()); } }
新建一个自己的事件:
package com.nijunyang.spring.listener; import org.springframework.context.ApplicationEvent; /** * Description: * Created by nijunyang on 2020/2/20 22:05 */ public class MyApplicationEvent extends ApplicationEvent { /** * Create a new ApplicationEvent. * * @param source the object on which the event initially occurred (never {@code null}) */ public MyApplicationEvent(Object source) { super(source); } }
配置类:指定要扫描的包
package com.nijunyang.spring; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; /** * @author: create by nijunyang * @date:2019/10/6 */ @Configuration @ComponentScan(basePackages = "com.nijunyang.spring.*") public class MainConfig { }
测试代码:在容器创建完之后发布自己的事件。
package com.nijunyang.spring; import com.nijunyang.spring.listener.MyApplicationEvent; import com.nijunyang.spring.model.Student; import org.springframework.boot.SpringApplication; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Application { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class); context.publishEvent(new MyApplicationEvent("想涨工资")); } }
执行代码会发现我们的监听器会监听到两个事件,因为我们监听器监听的事件是ApplicationEvent,上面说到容器启动的时候,最后会执行finishRefresh方法发布ContextRefreshedEvent事件,容器启动完成之后,我们自己手动发布了一个我们自己的事件,因此会监听到两个事件。
修改我们的监听器,只监听我们自己的事件:
package com.nijunyang.spring.listener; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; /** * Description: * Created by nijunyang on 2020/2/20 21:53 */ @Component public class MyListener implements ApplicationListener<MyApplicationEvent> { @Override public void onApplicationEvent(MyApplicationEvent event) { System.out.println("收到事件:" + event.toString()); } }
再次执行代码,发现现在就只能监听我们自己的事件了
通过spring的监听器,我们不仅可以实现自己相关的业务,还可以通过这个机制将我们自己的组件和spring进行整合,比如阿里的nacos就是通过ApplicationListener与spring整合的