Spring中的事件发布监听

本文介绍了Spring框架中的观察者模式,包括编码式和注解式的监听器实现。通过创建事件、发布事件和监听事件的流程,展示了如何在Spring中使用ApplicationEvent和ApplicationListener接口进行事件处理。同时,深入解析了Spring内部事件发布的实现原理,涉及ApplicationEventMulticaster的多播事件过程。
摘要由CSDN通过智能技术生成

Spring中的观察者模式

编码式监听器

观察者模式三个角色:事件本身,事件发布者,事件监听者。
Spring中的事件本身:集成抽象类ApplicationEvent
Spring中的事件发布者:ApplicationContext
Spring中的事件监听者:实现ApplicationListener接口

观察者模式实现的流程:
创建事件Event,Application发布Event,事件监听者接收处理Event。

实践代码

// 事件监听者
@Component
public class HuyonghaoListener implements ApplicationListener<HuyonghaoEvent> {

    @Override
    public void onApplicationEvent(HuyonghaoEvent event) {
        System.out.println("监听到我这个成功了");
        Huyonghao huyonghao = (Huyonghao) event.getSource();
        System.out.println("我是谁:" +huyonghao.getName() + ", 我多大了" + huyonghao.getAge());
    }
}

// source实体类
@Data
public class Huyonghao {
    private String name;

    private Integer age;

}

// 事件本身
public class HuyonghaoEvent extends ApplicationEvent {
    public HuyonghaoEvent(Object source) {
        super(source);
    }
}

// 测试方法
 public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
                "com.example.springlearn.listener");

        HuyonghaoEvent event = new HuyonghaoEvent("sss");
        Huyonghao huyonghao = new Huyonghao();
        huyonghao.setAge(26);
        huyonghao.setName("huyonghao");
        ctx.publishEvent(new HuyonghaoEvent(huyonghao));
    }

运行结果:
	监听到我这个成功了
	我是谁:huyonghao, 我多大了26

注解式监听器

@Component
public class HuyonghaoListenerDouble {

@EventListener
public void onApplicationEvent(HuyonghaoEvent event) {
    System.out.println("监听到我这个成功了--2");
    Huyonghao huyonghao = (Huyonghao) event.getSource();
    System.out.println("我是谁:" +huyonghao.getName() + ", 我多大了--2" + huyonghao.getAge());
}

}

Spring中监听器实现原理

ApplicationContext实现了ApplicationEventPublisher接口
该接口中有两个方法

// 调用发布事件
@FunctionalInterface
public interface ApplicationEventPublisher {
	default void publishEvent(ApplicationEvent event) {
		publishEvent((Object) event);
	}
// 真正执行的方法
	void publishEvent(Object event);
	}

改接口也有回调接口 ApplicationEventPublisherAware,实现改接口可实现启动容器注入事件发布者的子类,而不使用ApplicationContext进行发布事件

public interface ApplicationEventPublisherAware extends Aware {


	void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher);

}

上述代码使用DEBUG跟踪:
最终发布事件调用的代码为AbstractApplicationContext 中的publishEvent方法

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
    protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
		Assert.notNull(event, "Event must not be null");

		// Decorate event as an ApplicationEvent if necessary
		ApplicationEvent applicationEvent;
		if (event instanceof ApplicationEvent) {
			applicationEvent = (ApplicationEvent) event;
		}
		else {
			applicationEvent = new PayloadApplicationEvent<>(this, event);
			if (eventType == null) {
				eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
			}
		}

		if (this.earlyApplicationEvents != null) {
			this.earlyApplicationEvents.add(applicationEvent);
		}
		else {
		    // 主要方法
			getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
		}

		if (this.parent != null) {
			if (this.parent instanceof AbstractApplicationContext) {
				((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
			}
			else {
				this.parent.publishEvent(event);
			}
		}
	}
}

最终获取监听器,执行监听器中的代码

@Override
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		Executor executor = getTaskExecutor();
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				invokeListener(listener, event);
			}
		}
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值