从源码Debug深入spring事件机制,基于观察者模式仿写spring事件监听骨架

1.测试案例

定义一个事件

package com.example.demo.event;
import org.springframework.context.ApplicationEvent;

public class MyEvent extends ApplicationEvent {
    public MyEvent(Object source) {
        super(source);
    }
}

定义两个listener

package com.example.demo.event;

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

@Component
public class Listener1 implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent event) {
        String source = (String) event.getSource();
        System.out.println(this.getClass().getName() + ":" + source);
    }
}
package com.example.demo.event;

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

@Component
public class Listener2 implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent event) {
        String source = (String) event.getSource();
        System.out.println(this.getClass().getName() + ":" + source);
    }
}

注入spring容器里的ApplicationEventPublisher对象,发布事件

package com.example.demo;


import com.example.demo.event.MyEvent;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

@RunWith(SpringRunner.class)
@SpringBootTest
public class EventPublisherTest {

    @Resource
    private ApplicationEventPublisher eventPublisher;

    @Test
    public void test() {
        eventPublisher.publishEvent(new MyEvent("xxx"));
    }
}

2.DEBUG源码分析

eventPublisher.publishEvent(new MyEvent("xxx"));进去很容易就能找到,可以发现SimpleApplicationEventMulticaster这个事件发布对象持有所有listenter对象及MyEvent对象,
事件发布过程其实就是遍历拿到每个listener对象并调用它自己的onApplicationEvent()方法

SimpleApplicationEventMulticaster类的主要方法:

  • addApplicationListener(ApplicationListener<?> listener) :
  • addApplicationListenerBean(String listenerBeanName):
  • removeApplicationListener(ApplicationListener<?> listener):
  • removeApplicationListenerBean(String listenerBeanName):
  • multicastEvent(ApplicationEvent event):广播事件;
  • multicastEvent(ApplicationEvent event, @Nullable
    ResolvableType eventType):广播事件,指定事件的source类型。

在这里插入图片描述

3. 异步监听

从上图断点可以看到ApplicationEventMulticaster对象持有有taskExecutor字段为null,导致没有异步执行所有监听器。这里需要想办法这个字段设置线程池即可:
springboot默认会配置一个ThreadPoolTaskExecutor对象在容器里,这里把它拿出来设置给ApplicationEventMulticaster对象即可

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;


/**
 * @author Administrator
 */
@SpringBootApplication
public class DemoApplication {

    @Resource
    private SimpleApplicationEventMulticaster eventMulticaster;
    @Resource
    private ThreadPoolTaskExecutor executor;

    @PostConstruct
    public void setEventExecutor() {
        eventMulticaster.setTaskExecutor(executor);
    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

4.ApplicationListener子接口

还可以实现子类的getOrder方法可以实现多个监听器排序;实现supportsEventType,supportsSourceType可以实现按过滤Class过来或按事件源Source的Class过滤
在这里插入图片描述

5. 注解支持

这里不通过实现接口来实现监听,顺序排序,按事件类型过滤监听,采用更方便的注解实现,且一个类中就可以实现多个监听

package com.example.demo.event;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
public class Listener3 {

    @Order(Integer.MIN_VALUE) // 优先级最高
    @EventListener(MyEvent.class)  // 只监听指定类型的事件
    public void onApplicationEvent(ApplicationEvent event) {
        MyEvent myEvent = (MyEvent) event;
        System.out.println(this.getClass().getName() + ":" + myEvent.getSource());
    }
}

6. 基于观察者模式高仿spring事件监听

6.1 先定义自定义一个事件

Java中已定义观察者模式事件及监听器顶级接口

package com.example.demo.javanativeevent;

import java.util.EventObject;

public class MyJavaNativeEvent extends EventObject {

    public MyJavaNativeEvent(Object source) {
        super(source);
    }
}

6.2 定义两个监听器

因为Java提供的EventListener无具体监听方法,且无合适的子接口,故这里自定义一个类似spirng的子接口NativeEventListener。这样后续事件发布就是遍历这种类型接口并调用onApplicationEvent()方法

package com.example.demo.javanativeevent;

import java.util.EventListener;
import java.util.EventObject;

public interface NativeEventListener extends EventListener {
    void onApplicationEvent(EventObject event);
}
package com.example.demo.javanativeevent;

import java.util.EventObject;


public class JavaNativeListener1 implements NativeEventListener {

    @Override
    public void onApplicationEvent(EventObject event){
        String source = (String)event.getSource();
        System.out.println(this.getClass().getName()+":"+source);
    }
}

6.3 定义一个持有所有监听器的对象,类似spring的SimpleApplicationEventMulticaster

package com.example.demo.javanativeevent;

import java.util.ArrayList;
import java.util.Collections;
import java.util.EventObject;
import java.util.List;

/**
 * TODO
 *
 * @author majun
 * @version 1.0
 * @since 2023-08-13 18:50
 */
public class SimpleJavaNativeEventMulticaster {

    public List<NativeEventListener> eventListeners= Collections.synchronizedList(new ArrayList<>(8));


    public void addListener(NativeEventListener listener){
        this.eventListeners.add(listener);
    }
    public void multicastEvent(EventObject eventObject){
        eventListeners.stream().parallel().forEach(listener -> {
           listener.onApplicationEvent(eventObject);
        });
    }
}

6.4 事件发布测试

package com.example.demo.javanativeevent;

/**
 * TODO
 *
 * @author majun
 * @version 1.0
 * @since 2023-08-13 19:01
 */
public class EventPublishTest {


    public static void main(String[] args) {
        // 注册两个listener,这是spirng把这个过程隐藏在spring容器初始化过程中了
        SimpleJavaNativeEventMulticaster eventMulticaster = new SimpleJavaNativeEventMulticaster();
        eventMulticaster.addListener(new JavaNativeListener1());
        eventMulticaster.addListener(new JavaNativeListener2());
        // 发布事件
        eventMulticaster.multicastEvent(new MyJavaNativeEvent("yyyy"));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值