观察模式、监听器模式、Spring监听器源码分析

Spring监听器模式与源码分析

目录

观察者模式

监听器模式

Spring监听器源码分析

事件源 

事件

事件监听器

事件广播器

源码分析

自定义Spring监听器

完结撒花


观察者模式

废话不多说,直接上代码 我相信看代码比文字来的更加明白

主题  Subject

package com.ruoyi.observermodel;

import java.util.ArrayList;
import java.util.List;

/**
 * 抽象主题类(作用是通知观察者)
 *@Author:luyongcheng
 *@Date:2024/11/8 10:18
 */
public abstract class Subject {
    // 定义观察者集合
    private List<Observer> observers = new ArrayList<>();

    /**
     * 增加观察者
     */
    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    /**
     * 删除观察者
     */
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    /**
     * 通知注册该主题的观察者
     */
    public void notifyObservers(Object message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

主题的具体实现 ObserverImpl

package com.ruoyi.observermodel;

import lombok.Data;
import lombok.experimental.Accessors;

/**
 *@Author:luyongcheng
 *@Date:2024/11/8 10:47
 */
@Data
@Accessors(chain = true)
public class ObserverImpl implements Observer {
    private String name;

    @Override
    public void update(Object message) {
        // 业务逻辑实现
        System.out.println("观察者:" + name + ",接收到主题的消息: " + message);
    }
}

观察者 Observer

package com.ruoyi.observermodel;

/**
 * 观察者接口
 *@Author:luyongcheng
 *@Date:2024/11/8 10:19
 */
public interface Observer {
    void update(Object message);
}

观察者具体实现 ObserverImpl

package com.ruoyi.observermodel;

import lombok.Data;
import lombok.experimental.Accessors;

/**
 *@Author:luyongcheng
 *@Date:2024/11/8 10:47
 */
@Data
@Accessors(chain = true)
public class ObserverImpl implements Observer {
    private String name;

    @Override
    public void update(Object message) {
        // 业务逻辑实现
        System.out.println("观察者:" + name + ",接收到主题的消息: " + message);
    }
}

客户端调用 ObserverModelClient

package com.ruoyi.observermodel;

/**
 *@Author:luyongcheng
 *@Date:2024/11/8 10:48
 */
public class ObserverModelClient {
    public static void main(String[] args) {
        SubjectImpl subject = new SubjectImpl();
        subject.addObserver(new ObserverImpl().setName("1"));
        subject.addObserver(new ObserverImpl().setName("2"));
        subject.addObserver(new ObserverImpl().setName("3"));
        subject.notifyObservers("主题状态发生变化!");
    }
}

总结:

Observer 注册到Subject ,SUbject调用 notifyObservers(Object message) 方法 通知观察者主题发生了变化

主题------>消息传递------>观察者

监听器模式

同样上代码

事件源EventSource

package com.ruoyi.listenermode;

import java.util.ArrayList;
import java.util.List;

/**
 *@Author:luyongcheng
 *@Date:2024/11/8 11:00
 */
public class EventSource {

    private List<EventListener> listeners = new ArrayList<>();

    /**
     * 添加监听器
     * @param listener
     */
    public void addListener(EventListener listener) {
        listeners.add(listener);
    }

    /**
     * 移除监听器
     * @param listener
     */
    public void removeListener(EventListener listener) {
        listeners.remove(listener);
    }

    public void notifyAll(Event event) {
        for (EventListener listener : listeners) {
            listener.onClick(event);
        }
    }
}

事件 Event

package com.ruoyi.listenermode;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 *@Author:luyongcheng
 *@Date:2024/11/8 10:58
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Event {
    /**
     * 数据
     */
    private String data;

    /**
     * 类型
     */
    private String type;
}

事件监听器抽象类 EventListener

package com.ruoyi.listenermode;

/**
 *@Author:luyongcheng
 *@Date:2024/11/8 11:01
 */
@FunctionalInterface
public interface EventListener {
    /**
     * 点击事件
     * @param event
     */
    void onClick(Event event);
}

客户端调用ListenerModeClient

package com.ruoyi.listenermode;

/**
 *@Author:luyongcheng
 *@Date:2024/11/8 11:05
 */
public class ListenerModeClient {
    public static void main(String[] args) {
        EventSource eventSource = new EventSource();
        eventSource.addListener(event -> System.out.println("listener1: " + event.getData() + "," + event.getType()));
        eventSource.notifyAll(new Event("hello world", "click"));
    }
}

总结:

事件监听器注册到时间源,事件源调用notifyAll(Even enen)方法 执行事件监听器实现类方法

事件源------>传递事件------>事件监听器

Spring监听器源码分析

事件源

事件          增加了 事件广播器  负责把事件传给时间监听器 实现了事件源和时间监听器的解耦合                     增加了这一层 这一层就是事件广播器

事件监听器

事件源 

ApplicationContext 是Spring的容器 继承了ApplicationEventPublisher ,这类有发布事件的方法所以ApplicationContext可以作为时间源类

事件

ApplicationEvent 继承了 EventObject 这个类有可以获取到Source信息

事件监听器

ApplicationListener 继承了 EventListener 这个类有一个方法onApplicationEnent 监听器的执行方法 multicastEvent(ApplicationEvent event)

事件广播器

ApplicationEventMulticaster  把AppliactionContext 发布的ApplicationEven 传递给 AppliactionListener 用到的方法 multicastEvent

源码分析

在AbstractApplicationContext的refresh() 方法中 有

// 初始化事件广播器

initApplicationEventMulticaster();

深入方法内

protected void initApplicationEventMulticaster() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        // 判断工厂容器是否有时间广播器 如果没有new一个 放到工厂容器里面
		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
			this.applicationEventMulticaster =
					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
			if (logger.isTraceEnabled()) {
				logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
			}
		}
		else {
			this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
			beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
			if (logger.isTraceEnabled()) {
				logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
						"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
			}
		}
	}

// 注册监听器

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!
		String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
		for (String listenerBeanName : listenerBeanNames) {
			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
		}

		// Publish early application events now that we finally have a multicaster...
        // 此时是事件管理器发布事件到事件监听器
		Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
		this.earlyApplicationEvents = null;
		if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
				getApplicationEventMulticaster().multicastEvent(earlyEvent);
			}
		}
	}
finishRefresh(); 完成刷新

深入到方法

protected void finishRefresh() {
		// Clear context-level resource caches (such as ASM metadata from scanning).
		clearResourceCaches();

		// Initialize lifecycle processor for this context.
		initLifecycleProcessor();

		// Propagate refresh to lifecycle processor first.
		getLifecycleProcessor().onRefresh();

		// Publish the final event.
        // 执行事件监听器
		publishEvent(new ContextRefreshedEvent(this));

		// Participate in LiveBeansView MBean, if active.
		if (!NativeDetector.inNativeImage()) {
			LiveBeansView.registerApplicationContext(this);
		}
	}

继续深入publishEvent(new ContextRefreshedEvent(this));

	public void publishEvent(ApplicationEvent event) {
		publishEvent(event, null);
	}

继续深入

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

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

		// Publish event via parent context as well...
		if (this.parent != null) {
			if (this.parent instanceof AbstractApplicationContext) {
				((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
			}
			else {
				this.parent.publishEvent(event);
			}
		}
	}

继续深入getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);

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

继续深入executor.execute(() -> invokeListener(listener, event));

	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(ApplicationListener listener, ApplicationEvent event);

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
		try {
			listener.onApplicationEvent(event);
		}
		catch (ClassCastException ex) {
			String msg = ex.getMessage();
			if (msg == null || matchesClassCastMessage(msg, event.getClass()) ||
					(event instanceof PayloadApplicationEvent &&
							matchesClassCastMessage(msg, ((PayloadApplicationEvent) event).getPayload().getClass()))) {
				// Possibly a lambda-defined listener which we could not resolve the generic event type for
				// -> let's suppress the exception.
				Log loggerToUse = this.lazyLogger;
				if (loggerToUse == null) {
					loggerToUse = LogFactory.getLog(getClass());
					this.lazyLogger = loggerToUse;
				}
				if (loggerToUse.isTraceEnabled()) {
					loggerToUse.trace("Non-matching event type for listener: " + listener, ex);
				}
			}
			else {
				throw ex;
			}
		}
	}

listener.onApplicationEvent(event); 大家看到这行代码恍然大悟了吗

有很多事件实现的方法 自己Debug去看吧 在SpringBoot框架中 监听器贯穿了整个SpringBoot启动过程 

自定义Spring监听器

事件

package com.ruoyi.customListeners;

import org.springframework.context.ApplicationEvent;

/**
 *@Author:luyongcheng
 *@Date:2024/11/8 12:50
 */
public class OrderEvent extends ApplicationEvent {
    private String name;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

事件监听器

package com.ruoyi.customListeners;

import org.springframework.context.ApplicationListener;

/**
 *@Author:luyongcheng
 *@Date:2024/11/8 12:51
 */
public class OrderEventListener implements ApplicationListener<OrderEvent> {
    @Override
    public void onApplicationEvent(OrderEvent event) {
        System.out.println("event.getName() = " + event.getName());
    }
}

客户端调用

package com.ruoyi.customListeners;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 *@Author:luyongcheng
 *@Date:2024/11/8 12:52
 */
public class CustomListenersClient {
    public static void main(String[] args) {
        // 创建事件源
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(XXX.class);
        // 发布事件  source 是事件数据 name 也是  
        context.publishEvent(new OrderEvent(source, name));
    }
}
完结撒花
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值