Spring事件监听--ApplicationListener原理

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));
        }
        
        ......
        
        
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值