Spring源码一.(6)spring事件学习

一.spring事件三大组件

     1.1.事件

     1.2.事件监听器

     1.3.事件广播器(多播器)

二.事件流程图

      概念:以下图为例,每次发布的一条新闻就可以理解为一个事件,上面的主持人就是事件的发布者,下面的记者就是事件的监听者。

        spring事件是基于观察者设计模式

       

      

      2.1.spring内置事件

          例如spring容器启动完毕,以及销毁等等都会产生内置事件,这里不作介绍

      2.2.自定义事件

          CustomEvent 继承 ApplicationEvent,然后写一个自定义的监听器,放入spring容器中,去监听自定义的事件.

三.对应代码

 3.1.代码示例

package com.shadow.wang.event.custom;

import org.springframework.context.ApplicationEvent;

public class CustomEvent extends ApplicationEvent {

    private String name;

    public String getName() {
        return name;
    }

    public CustomEvent(Object source, String name) {
        super(source);
        this.name = name;
    }

    /**
     * Create a new {@code ApplicationEvent}.
     *
     * @param source the object on which the event initially occurred or with
     *               which the event is associated (never {@code null})
     */
    public CustomEvent(Object source) {
        super(source);
    }
}

package com.shadow.wang.event.custom;

import com.shadow.wang.guess.Student;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class CustomAnnoEventListener {

    @EventListener(CustomEvent.class)
    public void Listen(CustomEvent s){
        System.out.println("CustomAnnoEventListener <===== " + s.getName());
    }
}

package com.shadow.wang.event.custom;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class CustomEventListener implements ApplicationListener<CustomEvent> {

    @Override
    public void onApplicationEvent(CustomEvent event) {
        System.out.println("event = " + event);
        System.out.println(" CustomEventListener listen event ====>" + event.getName() + ", source = "+ event.getSource());
    }
}

package com.shadow.wang.event;

import com.shadow.wang.event.custom.CustomEvent;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.stereotype.Component;

@Configuration
@ComponentScan("com.shadow.wang.event")
public class EventAppConfig {

    @Test
    public void learnEvent(){
        AnnotationConfigApplicationContext
                app = new AnnotationConfigApplicationContext(EventAppConfig.class);
        app.publishEvent(new CustomEvent(this,"生产OOM"));
        System.out.println("main线程执行中......");
        Student bean = app.getBean(Student.class);
        System.out.println("bean = " + bean);
    }

    @Bean
    public ApplicationEventMulticaster applicationEventMulticaster(){
        SimpleApplicationEventMulticaster simpleCaster = new SimpleApplicationEventMulticaster();
        // 支持异步
        simpleCaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
        return simpleCaster;
    }
}

@Component
class Student{
    private String name;

}

   执行结果图:这里可以看到我自定的2个监听器,都监听到了我自定义的 “生产OOM“事件,一种是实现ApplicationListener接口,另外一种是基于注解@LEventListener的实现

3.2.这里通过@Bean方式弄了一个异步广播器放入spring容器中 ,默认情况下spring容器中的广播器是同步的

这里可以观察后,下述的“日志打印,main线程在执行中”跑到了最上面

 

 

四.源码学习

 为啥这二种监听器都有效果?

         它们都被放入到了广播器(多播器)中

它们在执行时机(调用链路)是啥? 这些监听器啥时候放入广播器中的?

        4.1.基于ApplicationListener

        调用ApplicationListeneronApplicationEvent方法,走入自己写的实现类             CustomEventListener#onApplicationEvent

        

  • 4.1.1 通过BeanPostProcessor的初始化后方法添加

              ApplicationListenerDetector#postProcessAfterInitialization

  • 4.1.2.通过spring容器的refresh()里面的注册一个监听器(查缺补漏,防漏lazy情况下的监听器没被注册上去)

                

      4.2.基于注解@EventListener

      调用到了ApplicationListenerMethodAdapteronApplicationEvent方法,最终走了反射this.method.invoke(bean, args)

      在实例化spring容器的reade解析器(AnnotatedBeanDefinitionReader)时,提前准备好了2个类

EventListenerMethodProcessor,DefaultEventListenerFactory来添加监听器到广播器中

注解类型的监听器@EventListener(CustomEvent.class)
执行时机是在那八大BeanPostprocessor执行完之后再去执行的,利用了一个特殊的处理器方法SmartInitializingSingleton的afterSingletonsInstantiated方法添加的

五.小结

spring事件是基于观察者设计模式,它默认情况下是线程同步机制,广播器中设置异步执行后,可支持异步机制。监听器的形式有两种,基于接口和基于注解@EventListener的形式。

 

     

       

 

        

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值