1,前言
学习雷老师的Spring注解版所做的笔记
若有不当之处,请您指出,您的指点是我的荣幸
2,ApplicationListener
2.1,示例
MyApplicationListener类
//这里除了实现ApplicationListener接口外,还可以在方法上使用@EventListener注解,效果是相同的
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
//这个ApplicationEvent就是我们要监听的事件
//当容器中发布此事件以后,方法会触发
//在该方法名处打上断点,先正常运行,然后再debug运行
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("收到事件"+event);
}
}
MyBeanFactoryPostProcessor类
这个类其实与主题无关,只是为了看一下容器中的bean
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("MyBeanFactoryPostProcessor-》BeanFactoryPostProcessor...");
//容器中有多少个bean
int count = beanFactory.getBeanDefinitionCount();
//拿到容器中的bean
String[] names = beanFactory.getBeanDefinitionNames();
System.out.println("当前beanFactory中有"+count+"个Bean");
System.out.println(Arrays.asList(names));
}
}
配置类
@ComponentScan("com.cb414.ext")
@Configuration
public class ExtConfig {
@Bean
public Blue blue(){
return new Blue();
}
}
Blue
public class Blue {
public Blue(){
System.out.println("blue..constructor");
}
public void init(){
System.out.println("blue..init...");
}
public void destory(){
System.out.println("blue...destory...");
}
}
测试类
public class IOCTestExt {
@Test
public void test01(){
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(ExtConfig.class);
//发布一个自己的事件
annotationConfigApplicationContext.publishEvent(new ApplicationEvent(new String("我发布的事件")) {
});
annotationConfigApplicationContext.close();
}
}
运行结果
MyBeanFactoryPostProcessor-》BeanFactoryPostProcessor...
当前beanFactory中有10个Bean
[org.springframework.context.annotation.internalConfigurationAnnotationProcessor,
org.springframework.context.annotation.internalAutowiredAnnotationProcessor,
org.springframework.context.annotation.internalRequiredAnnotationProcessor,
org.springframework.context.annotation.internalCommonAnnotationProcessor,
org.springframework.context.event.internalEventListenerProcessor,
org.springframework.
context.event.internalEventListenerFactory,
extConfig,
myApplicationListener,
myBeanFactoryPostProcessor,
blue]
blue..constructor
收到事件org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@6d86b085: startup date [Sat Aug 01 11:04:11 GMT+08:00 2020]; root of context hierarchy]
收到事件com.cb414.IOCTestExt$1[source=我发布的事件]
八月 01, 2020 11:04:12 上午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6d86b085: startup date [Sat Aug 01 11:04:11 GMT+08:00 2020]; root of context hierarchy
收到事件org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@6d86b085: startup date [Sat Aug 01 11:04:11 GMT+08:00 2020]; root of context hierarchy]
2.2,原理
debug运行,会来到refresh()
其实debug运行会直接来到finishRefresh()
,但是上面还有两个方法需要关注。
2.2.1,refresh()
重点关注这三个调用的方法
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
......
try {
......
// Initialize event multicaster for this context.
//初始化事件派发器
initApplicationEventMulticaster();
......
// Check for listener beans and register them.
//注册监听器
registerListeners();
......
// Last step: publish corresponding event.
//完成刷新
finishRefresh();
}
catch (BeansException ex) {
......
}
finally {
......
}
}
}
2.2.2,initApplicationEventMulticaster()
先来研究initApplicationEventMulticaster()
做了什么
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//注:APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
//会先判断容器是否有applicationEventMulticaster这个bean
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
//如果没有
else {
//创建一个SimpleApplicationEventMulticaster
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
//并把这个创建好的对象注册到容器之中
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
......
}
}
}
//简而言之:initApplicationEventMulticaster()就是为了初始化一个容器事件派发器(多播器)
看完之后,继续研究一下registerListeners()
又做了什么
2.2.3,registerListeners()
//派发器又是怎么拿到监听器的呢?
protected void registerListeners() {
// Register statically specified listeners first.
//拿到容器中的所有监听器
for (ApplicationListener<?> listener : getApplicationListeners()) {
//将监听器注册到容器事件派发器之中
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
//如果第一次,没拿到的话,就会在这里从容器中根据类型(ApplicationListener.class)拿到那些监听器
//所以我们也可以自定义一个类,让它实现ApplicationListener,成为监听器
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
//遍历
for (String listenerBeanName : listenerBeanNames) {
//将监听器加到事件派发器之中
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
......
}
//registerListeners()则是为了注册所有的监听器,方便容器事件派发器的事件派发
接下来就是研究finishRefresh()
2.2.4,finishRefresh()
protected void finishRefresh() {
...
// Publish the final event.
//这里是在发布一个容器刷新完成的事件
publishEvent(new ContextRefreshedEvent(this));
...
}
//=========================华丽的分割线====================================
//继续点击查看publishEvent(new ContextRefreshedEvent(this))
public void publishEvent(ApplicationEvent event) {
publishEvent(event, null);
}
//=========================华丽的分割线====================================
//然后会来到
//publishEvent(event, null)
protected void publishEvent(Object event, ResolvableType eventType) {
......
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
//获得事件派发器,并派发事件
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
......
}
那么它又是怎么派发事件的?
2.2.5,multicastEvent()
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
//拿到所有的ApplicationListener
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
//如果能使用Executor的话,就是用异步线程的方式派发事件
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
//如果没有的话
else {
//同步的方式执行监听器的方法
invokeListener(listener, event);
}
}
}
那么又是怎么执行监听器的方法的?
继续查看invokeListener()
2.2.6,invokeListener()
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
//关注这里
doInvokeListener(listener, event);
}
}
//=========================华丽的分割线====================================
//看看doInvokeListener(listener, event)做了什么
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
//调用监听器的onApplicationEvent()
//这也就解释了我们自定义的ApplicationListener中的onApplicationEvent()是怎么执行的了
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
......
}
}
走到这一步,容器发布刷新完成的事件就完成了
接下来就轮到我们自定义的监听器的onApplicationEvent()
了
而自定义的监听器之后,有
annotationConfigApplicationContext.close();
接下来就研究下close做了什么?
2.2.7,close()
public void close() {
synchronized (this.startupShutdownMonitor) {
doClose();
......
}
}
//doclose()
protected void doClose() {
if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (logger.isInfoEnabled()) {
logger.info("Closing " + this);
}
LiveBeansView.unregisterApplicationContext(this);
try {
// Publish shutdown event.
//这里发布容器关闭的事件
publishEvent(new ContextClosedEvent(this));
}
......
}
}