手撸spring11: 基于观察者模式 实现事件监听器解耦代码

观察者模式可以理解为, 订阅某种行为后, 当执行该行为时, 会向订阅者发布事件, 接收该事件的订阅者,就会各自去做自己需要做的事, 以此完成系统的解耦.

如用户注册会员后, 可能需要发送短信通知, 发送优惠券等一些常见的操作.

如果把这些业务处理都写在一块就容易造成代码的耦合, 并且还会影响主流程的进行.

例如我注册会员后, 你因为发送优惠券的问题导致会员注册失败, 这不就扯淡嘛!

所以流程上来说, 应该是 我注册会员就只注册会员, 我跟需要配合的业务通知一下,这个人注册好了!你们爱怎么样就怎么样, 出问题自己解决自己的问题, 不要影响到我们尊贵的会员用户!

so, 看看spring怎么处理的.

//TODO 补充类图

全局事件接口

package com.linnine.spring.context;

/**
 * 11 定义一个具有时间功能的抽象类
 */
public abstract class ApplicationEvent extends EventObject {
    /**
     * Constructs a prototypical Event.
     *
     * @param source the object on which the Event initially occurred
     * @throws IllegalArgumentException if source is null
     */
    public ApplicationEvent(Object source) {
        super(source);
    }
}

几个实现类,一般情况下把事件需要用到的参数丢到这个构造方法的参数即可

ApplicationContextEvent

package com.linnine.spring.context.event;

public class ApplicationContextEvent extends ApplicationEvent {

    /**
     * Constructs a prototypical Event.
     *
     * @param source the object on which the Event initially occurred
     * @throws IllegalArgumentException if source is null
     */
    public ApplicationContextEvent(Object source) {
        super(source);
    }

    public final ApplicationContext getApplicationContext(){
        return (ApplicationContext) getSource();
    }
}

ContextClosedEvent

package com.linnine.spring.context.event;

/**
 * 监听关闭
 */
public class ContextClosedEvent extends ApplicationEvent {
    /**
     * Constructs a prototypical Event.
     *
     * @param source the object on which the Event initially occurred
     * @throws IllegalArgumentException if source is null
     */
    public ContextClosedEvent(Object source) {
        super(source);
    }

}

ContextRefreshedEvent

package com.linnine.spring.context.event;

/**
 * 监听刷新
 */
public class ContextRefreshedEvent extends ApplicationEvent {
    /**
     * Constructs a prototypical Event.
     *
     * @param source the object on which the Event initially occurred
     * @throws IllegalArgumentException if source is null
     */
    public ContextRefreshedEvent(Object source) {
        super(source);
    }
}

事件发布者ApplicationEventPublisher

专门用来推送事件的接口类

package com.linnine.spring.context;

/**
 * 11 事件发布者
 */
public interface ApplicationEventPublisher {

    void publishEvent(ApplicationEvent event);
}

事件监听者ApplicationListener

暂时还没有操作,后面可能有坑要填

package com.linnine.spring.context;

public class ApplicationListener<T> {
}

事件广播器 ApplicationEventMulticaster

用于添加和删除事件监听者

package com.linnine.spring.context.event;

/**
 * 11 事件广播器
 */
public interface ApplicationEventMulticaster {

    void addApplicationListener(ApplicationListener<?> listener);

    void removeApplicationListener(ApplicationListener<?> listener);

    void multicastEvent(ApplicationEvent event);
}

事件广播器简单实现 SimpleApplicationEventMulticaster

还没有具体实现,后面慢慢填坑

package com.linnine.spring.context.event;

/**
 * 简单事件广播器
 */
@Data
@AllArgsConstructor
public class SimpleApplicationEventMulticaster implements ApplicationEventMulticaster{

    private BeanFactory beanFactory;

    @Override
    public void addApplicationListener(ApplicationListener<?> listener) {

    }

    @Override
    public void removeApplicationListener(ApplicationListener<?> listener) {

    }

    @Override
    public void multicastEvent(ApplicationEvent event) {

    }
}

改造原来的流程

AbstractApplicationContext

package com.linnine.spring.context.support;

主要是在刷新容器和关闭时发布对应的事件

/**
 * 应用上下文 抽象类实现
 */
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {

    public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";

    private ApplicationEventMulticaster applicationEventMulticaster;


    @Override
    public void refresh() throws BeansException {

        //11新增 初始化事件发布者
        initApplicationEventMulticaster();

        // 11新增 注册事件监听器
        registerListeners();

        // 11新增 发布容器刷新完成事件
        finishRefresh();

		//...旧的省略掉
    }



    private  void initApplicationEventMulticaster(){
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        //11又要往这个类里加个方法
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, applicationEventMulticaster);
    }

    private void registerListeners(){
        Collection<ApplicationListener> applicationListeners = getBeansOfType(ApplicationListener.class).values();
        for (ApplicationListener listener : applicationListeners) {
            applicationEventMulticaster.addApplicationListener(listener);
        }
    }

    /**
     * 发送刷新事件
     */
    private void finishRefresh(){
        publishEvent(new ContextRefreshedEvent(this));
    }

    /**
     * 发布事件
     * @param event
     */
    private void publishEvent(ApplicationEvent event) {
        applicationEventMulticaster.multicastEvent(event);
    }

    //...

    /**
     * 关闭
     */
    @Override
    public void close(){
        //11 新增 发布 关闭容器 事件
        publishEvent(new ContextClosedEvent(this));
        getBeanFactory().destroySingletons();
    }

}

加了个 beanFactory.registerSingleton方法, 还有掰正destroySingletons方法
一层一层往上走吧

ConfigurableListableBeanFactory

之前临时把destroySingletons丢在这里面了,现在干掉他!

package com.linnine.spring.beans.factory;

在这里插入图片描述

ConfigurableBeanFactory

应该在这里定义方法,并改了个继承

package com.linnine.spring.beans.factory.config;
在这里插入图片描述

SingletonBeanRegistry

在这里定义一个注册单例的方法

package com.linnine.spring.beans.factory.config;

在这里插入图片描述

DefaultSingletonBeanRegistry

在这里实现注册单例的方法,一开始这里面就是原来管理那些单例类

package com.linnine.spring.beans.factory.support;

public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {


    @Override
    public void registerSingleton(String name,Object singletonBean){
        singletonObjects.put(name,singletonBean);
    }

	//... 其他
}

spring代码准备工作做好了, 开始整测试类

ListableBeanFactory

继承 BeanFactory,因为AbstractApplicationContext里有个getBeanFactory()方法返回的是ConfigurableListableBeanFactory, 这个类就是继承自ListableBeanFactory 所以让他爹来继承BeanFactory,这样他也就跟BeanFactory通了!

package com.linnine.spring.beans.factory;

public interface ListableBeanFactory extends BeanFactory{
    <T> Map<String, T> getBeansOfType(@Nullable Class<T> var1) throws BeansException;

    <T> Map<String, T> getBeansOfType(@Nullable Class<T> var1, boolean var2, boolean var3) throws BeansException;

}

AutowireCapableBeanFactory

这个类也要实现BeanFactory 主要是因为AbstractAutowireCapableBeanFactory继承过来的,同上,

在这里需要

在这里插入图片描述

CustomEvent

外部实现自定义事件

package com.linnine.spring.event;

@Getter
@Setter
public class CustomEvent extends ApplicationEvent {

    private Long id;

    private String message;

    /**
     * Constructs a prototypical Event.
     *
     * @param source the object on which the Event initially occurred
     * @throws IllegalArgumentException if source is null
     */
    public CustomEvent(Object source, Long id, String message) {
        super(source);
        this.id = id;
        this.message = message;
    }
}

CustomEventListener

外部事件对应的时间监听器

package com.linnine.spring.event;

public class CustomEventListener implements ApplicationListener<CustomEvent> {

    @Override
    public void onApplicationEvent(CustomEvent event) {
        System.out.println("收到:" + event.getSource() + "消息;时间:" + new Date());
        System.out.println("消息:" + event.getId() + ":" + event.getMessage());
    }
}

ApplicationListener

反手完善这个类

package com.linnine.spring.context;

public interface ApplicationListener<T extends ApplicationEvent> {

    void onApplicationEvent(T event);
} 

两个监听类

CustomClosedEventListener

package com.linnine.spring.event;

public class CustomClosedEventListener implements ApplicationListener<ContextClosedEvent> {

    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        System.out.println("收到:" + event.getSource() + "销毁消息;时间:" + new Date());
    }
}

CustomRefreshedEventListener

package com.linnine.spring.event;

public class CustomRefreshedEventListener implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        System.out.println("收到:" + event.getSource() + "刷新消息;时间:" + new Date());
    }
}

spring.xml

注册这三个bean

    <bean class="com.linnine.spring.event.CustomEventListener" />
    <bean class="com.linnine.spring.event.CustomRefreshedEventListener" />
    <bean class="com.linnine.spring.event.CustomClosedEventListener" />

测试代码

@Test
public void test_event() {
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
    applicationContext.publishEvent(new CustomEvent(applicationContext, 1019129009086763L, "成功了!"));

    applicationContext.registerShutdownHook();
}

果然第一遍跑完屁事没有! 就是什么异常也没有, 但什么日志也都没有打印 坑爹啊!

就是我的事件监听器没有监听到,因为压根就没塞到spring的代码里!

应该是在SimpleApplicationEventMulticaster里面处理了!

搬源码搬的有点麻了, 歇会儿, 后面自己想办法简化一下, 就是差一个 判断 class类型 与泛型是否匹配.


ok啦! 通过java的反射机制 简单的判断了一下!

改了挺多代码的!

AbstractApplicationContext

前面在刷新的方法中加入了 事件相关的代码, 但是顺序不对 得放到后面
在这里插入图片描述

前面思考的是SimpleApplicationEventMulticaster 里面没有做实现, 然后看了一下源码 上面还封装了一蹭抽象类,对监听器进行管理.

发现spring的又一个小细节, 在抽象类中管理一些类, 具体的实现方式再让下级自己去处理.

一般也都是这种思想

接口 I 有三个抽象方法, X,Y,Z 要去实现它, 但是I的抽象方法中有两个方法 不管是X,Y,Z的实现方式都是一样的, 只有最后一个抽象方法处理不同.

这个时候就可以给X,Y,Z找个大爹A(Abstract).统一帮他们处理好前面两个方法, 再让他们去继承, 各自实现方法三就行了.

假设 方法一 中有些步骤是灵活的情况下, A还可以用模板模式, 在方法一中调用一些抽象方法, 再让他的儿子们自己做主,去实现这些抽象方法,也是可以的嘛!

这就是抽象类的妙了!


回到主题

原先SimpleApplicationEventMulticaster是直接实现ApplicationEventMulticaster 就需要实现他的三个方法, 现在交个父类来管理监听器集合, 顺便实现了里面的两个接口

AbstractApplicationEventMulticaster

package com.linnine.spring.context.event;

/**
 * 在这个类里管理监听器
 */
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanFactoryAware {

    private final Set<ApplicationListener<?>> applicationListeners =new HashSet<>();

    private ConfigurableBeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory){
        if (!(beanFactory instanceof ConfigurableBeanFactory)){
            throw new IllegalStateException("Not running in a ConfigurableBeanFactory: " + beanFactory);
        }
        this.beanFactory = (ConfigurableBeanFactory) beanFactory;
    }

    public ConfigurableBeanFactory getBeanFactory(){
        return this.beanFactory;
    }


    Set<ApplicationListener<?>> getApplicationListeners(){
        return applicationListeners;
    }
    
    /**
     * 根据事件 获取对应的事件监听器
     * @param event
     * @return
     */
    Set<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event) {

        Set<ApplicationListener<?>> resultSet = new HashSet<>();

        for (ApplicationListener<?> applicationListener : applicationListeners) {
            Class<? extends ApplicationListener> aClass = applicationListener.getClass();
            Method method = null;
            try {
                //判断其方法的 参数类型 是否匹配
                method = aClass.getMethod("onApplicationEvent", event.getClass());
            } catch (NoSuchMethodException ignored) { }
            //如果匹配就加入
            if (method!=null){
                resultSet.add(applicationListener);
            }

        }
        return resultSet;
    }
    @Override
    public void addApplicationListener(ApplicationListener<?> listener) {
        applicationListeners.add(listener);
    }

    @Override
    public void removeApplicationListener(ApplicationListener<?> listener) {
        applicationListeners.remove(listener);
    }

}

ApplicationListener

这个补个继承,看源码上有 跟着加了一下
package com.linnine.spring.context;

public interface ApplicationListener<T extends ApplicationEvent> extends EventListener {

    void onApplicationEvent(T event);
}

SimpleApplicationEventMulticaster

这个改造就简单了, 管理数据父类已经解决了, 我们直接获取过来调用一下就Ok了!

package com.linnine.spring.context.event;

/**
 * 简单事件广播器
 */
@Data
@AllArgsConstructor
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster{

    public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
        setBeanFactory(beanFactory);
    }

    public void multicastEvent(ApplicationEvent event) {
        for (ApplicationListener<?> listener : getApplicationListeners(event)) {
            invokeListener(listener,event);
        }
    }

    private void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
        doInvokeListener(listener,event);
    }

    private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
        listener.onApplicationEvent(event);
    }



}

最后的运行结果:完美!在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值