Soul网关(12) - 观察者模式

526 阅读3分钟

话不多说,上来就干

背景

在跟读soul源码的过程中,发现很多监听器,这些监听器是基于事件触发机制,而soul本身是采用响应式编程,网络框架采用netty。这其中都绕不开事件机制,而在java中,spring通过实现java.util.EventObject接口,来设计事件抽象类应用事件ApplicationEvent,这个接口中只有一个成员变量source,表示事件初始化发生时的对象


    /**
     * The object on which the Event initially occurred.
     */
    protected transient Object  source;

soul中的观察者模式之发布监听模式

soul源码中,DataChangedEvent继承spring的应用事件抽象类,并增加了两个成员变量


public class DataChangedEvent extends ApplicationEvent {

    /**
     * 数据事件类型
     * 包含增删改查等一系列对数据的操作
     */
    private DataEventTypeEnum eventType;

    /**
     * 配置组
     * 业务维度上的数据模型
     * 包含了权限/插件/规则/选择器等
     */
    private ConfigGroupEnum groupKey;

    /**
     * Instantiates a new Data changed event.
     *
     * @param groupKey the group key
     * @param type     the type
     * @param source   the source
     */
    public DataChangedEvent(final ConfigGroupEnum groupKey, final DataEventTypeEnum type, final List<?> source) {
        super(source);
        this.eventType = type;
        this.groupKey = groupKey;
    }
}

之所以增加两个成员变量,是因为需要通过这两个成员变量控制数据变更事件的类型,用于数据链路后的DataChangedEventDispatcher类进行匹配分发给不同的监听器,处理不同的逻辑。

EventPublisher 事件发布者

在soul的admin服务中,对于数据的写操作,基本逻辑都遵循 修改admin服务数据库数据或缓存 -> 发布数据变更事件 -> 后续逻辑....

    public String createOrUpdate(final PluginDTO pluginDTO) {
    
        //admin数据逻辑
        final String msg = checkData(pluginDTO);
        if (StringUtils.isNoneBlank(msg)) {
            return msg;
        }
        PluginDO pluginDO = PluginDO.buildPluginDO(pluginDTO);
        DataEventTypeEnum eventType = DataEventTypeEnum.CREATE;
        if (StringUtils.isBlank(pluginDTO.getId())) {
            pluginMapper.insertSelective(pluginDO);
        } else {
            eventType = DataEventTypeEnum.UPDATE;
            pluginMapper.updateSelective(pluginDO);
        }

        // 发布数据变更事件
        eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.PLUGIN, eventType,
                Collections.singletonList(PluginTransfer.INSTANCE.mapToData(pluginDO))));
                 
        return StringUtils.EMPTY;
    }

eventPublisher就是spring注入的应用发布者ApplicationEventPublisher,这个接口被函数式编程接口注解修饰@FunctionalInterface,表面这是一个函数式接口,只有一个抽象方法,另个default方法,相当于约束了唯一的抽象方法的参数类型为ApplicationEvent

@FunctionalInterface
public interface ApplicationEventPublisher {

	default void publishEvent(ApplicationEvent event) {
		publishEvent((Object) event);
	}

	void publishEvent(Object event);

}

具体实现

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

其中,multicastEvent(applicationEvent, eventType)是直接执行传播事件的方法

	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        //获取并发线程执行器
		Executor executor = getTaskExecutor();
        // 获取event类型对应的监听器,并循环调用监听器的监听方法
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			if (executor != null) {
            
            // 调用对应的事件的监听器,通过线程池中的可用线程执行
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
            
            // 调用对应事件的监听器,直接使用mian线程执行
				invokeListener(listener, event);
			}
		}
	}
   

直接调用具体类型实现类的onApplicationEvent()方法,这个方法就是监听者重写的方法,重写内容为监听到相关信息所做的具体逻辑处理

DataChangedListener 事件监听者

实际上在调用具体的监听者之前,还会通过DataChangedEventDispatcher调度器分发到具体的数据变更事件逻辑,继续处理

    public void onApplicationEvent(final DataChangedEvent event) {
        for (DataChangedListener listener : listeners) {
            switch (event.getGroupKey()) {
                case APP_AUTH:
                    listener.onAppAuthChanged((List<AppAuthData>) event.getSource(), event.getEventType());
                    break;
                case PLUGIN:
                    listener.onPluginChanged((List<PluginData>) event.getSource(), event.getEventType());
                    break;
                case RULE:
                    listener.onRuleChanged((List<RuleData>) event.getSource(), event.getEventType());
                    break;
                case SELECTOR:
                    listener.onSelectorChanged((List<SelectorData>) event.getSource(), event.getEventType());
                    break;
                case META_DATA:
                    listener.onMetaDataChanged((List<MetaData>) event.getSource(), event.getEventType());
                    break;
                default:
                    throw new IllegalStateException("Unexpected value: " + event.getGroupKey());
            }
        }
    }