模拟Spring自实现监听器

模拟Spring自实现监听器

  注意:在toC的项目中禁止使用延时发布事件(事件发布后延时执行),采用sleep方式,会造成线程池任务堆积,从而执行拒绝策略,同时等待队列中任务排队等待时间过长,造成任务执行的积压

 

组件:

  事件(Event):即监听什么。如任务即将执行、任务执行完毕

  监听器(Listener):谁来监听,<E extends Event> :E,对什么时间感兴趣(监听特定类型的事件)

  广播器(Multicaster):发布事件、添加/移除监听器

  事件触发机制:事件什么时候发布

 

1、事件 抽象类Event,其他要监控的事件继承它

/**
 * 事件
 *
 * @author yangyongjie
 * @date 2020/9/30
 * @desc
 */
public abstract class Event<T> {
    /**
     * 事件自身资源,用来发布任务时传递一些参数信息
     */
    protected T source;
    /**
     * 事件发生时间
     */
    private final long timestamp;

    public Event(T source) {
        this.source = source;
        this.timestamp = System.currentTimeMillis();
    }

    public T getSource() {
        return source;
    }

    public void setSource(T source) {
        this.source = source;
    }

    public long getTimestamp() {
        return timestamp;
    }
}

 如流程结束事件:

/**
 * 审批流程结束事件
 *
 * @author yangyongjie
 * @date 2020/10/15
 * @desc
 */
public class AuditFlowFinishEvent extends Event<AuditFlow> {

    public AuditFlowFinishEvent(AuditFlow auditFlow) {
        super(auditFlow);
    }

}

 

 

2、监听器接口 Listener,自定义监听器实现它;泛型E表示要监听的事件 

/**
 * 监听器
 *
 * @author yangyongjie
 * @date 2020/9/30
 * @desc
 */
public interface Listener<E extends Event> {

    /**
     * 当事件发生做一些事情
     *
     * @param event
     */
    void onEvent(E event);
}

 如:审核流程结束监听器

/**
 * 审核流程结束监听器
 *
 * @author yangyongjie
 * @date 2020/10/15
 * @desc
 */
@Component
public class AuditFlowFinishListener implements Listener<AuditFlowFinishEvent> {

    private static final Logger LOGGER = LoggerFactory.getLogger(AuditFlowFinishListener.class);

    @Override
    public void onEvent(AuditFlowFinishEvent event) {
        AuditFlow auditFlow = event.getSource();
        LOGGER.info("流程结束监听器工作了!");
    }
}

 

 

3、广播器,管理监听器,发布事件 (需注入到Spring容器中)

 V1.0:

 1)广播器接口:

/**
 * 事件广播器
 *
 * @author yangyongjie
 * @date 2020/9/30
 * @desc
 */
public interface EventMulticaster {

    /**
     * 添加监听器
     *
     * @param listener
     */
    void addListener(Listener<?> listener);

    /**
     * 移除监听器
     *
     * @param listener
     */
    void removeListener(Listener<?> listener);

    /**
     * 发布事件
     *
     * @param event
     */
    void multicastEvent(Event event);

}

 2)广播器实现类

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 广播器(事件发布器)
 *
 * @author yangyongjie
 * @date 2020/10/15
 * @desc
 */
@Component
public class SimpleEventMulticaster implements EventMulticaster, ApplicationContextAware {

    private static final Logger LOGGER = LoggerFactory.getLogger(SimpleEventMulticaster.class);

    private final Set<Listener<?>> listeners = new LinkedHashSet<>();

    /**
     * 创建一个执行监听器线程池,核心线程数为1,最大线程数为5,线程空闲时间为60s,拒绝策略为打印日志并直接执行被拒绝的任务
     */
    private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(1, 5, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(50), new CustomThreadFactory("simpleEventMulticaster"), (r, executor) -> {
        LOGGER.error("Task:{},rejected from:{}", r.toString(), executor.toString());
        // 直接执行被拒绝的任务,JVM另起线程执行
        r.run();
    });

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 获取容器中实现Listener接口的监听器,并添加到listeners缓存中
        Map<String, Listener> listenerMap = applicationContext.getBeansOfType(Listener.class);
        for (Map.Entry<String, Listener> entry : listenerMap.entrySet()) {
            addListener(entry.getValue());
        }
    }

    @Override
    public void addListener(Listener<?> listener) {
        this.listeners.add(listener);
    }

    @Override
    public void removeListener(Listener<?> listener) {
        this.listeners.remove(listener);
    }

    @Override
    public void multicastEvent(final Event event) {
        multicastEvent(event, true);
    }

    /**
     * 是否异步,默认true
     *
     * @param event
     * @param async
     */
    public void multicastEvent(final Event event, boolean async) {
        Class eventClass = event.getClass();
        Set<Listener> interestedListeners = getInterestedListeners(eventClass);
        // 事件发生,异步调用监听器的事件方法
        if (async) {
            for (final Listener listener : interestedListeners) {
                EXECUTOR.execute(() -> listener.onEvent(event));
            }
        } else {
            for (final Listener listener : interestedListeners) {
                listener.onEvent(event);
            }
        }

    }

    /**
     * 获取对当前事件感兴趣的监听器
     *
     * @param eventClass
     */
    private Set<Listener> getInterestedListeners(Class eventClass) {
        // 存放监听对发布事件感兴趣的监听器
        Set<Listener> interestedListeners = new LinkedHashSet<>();
        for (Listener listener : listeners) {
            // 获取监听器的泛型类型
            ParameterizedType parameterizedType = (ParameterizedType) listener.getClass().getGenericInterfaces()[0];
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            Listener filterListener = null;
            for (Type actualTypeArgument : actualTypeArguments) {
                if (StringUtils.equals(eventClass.getName(), actualTypeArgument.getTypeName())) {
                    filterListener = listener;
                }
            }
            if (filterListener != null) {
                interestedListeners.add(filterListener);
            }
        }
        return interestedListeners;
    }

}

  注1:1.8之前版本  actualTypeArgument.getTypeName() 替换成  ((Class) actualTypeArgument).getName() ;并替换掉 Lambda表达式

  注2:若在监听器的onEvent方法上加了@Transactional注解,那么获取到的监听器的对象就是代理对象,在获取监听器泛型的时候会有问题,需要拿到被代理的目标类对象,然后再去获取泛型类型:

  修改后的getInterestedListeners()方法的for循环第一行:

  ParameterizedType parameterizedType = (ParameterizedType) AopTargetUtil.getTarget(listener).getClass().getGenericInterfaces()[0];

 

  V2.0:

  1)广播器接口:

/**
 * 事件广播器
 *
 * @author yangyongjie
 * @date 2020/9/30
 * @desc
 */
public interface EventMulticaster {

    /**
     * 添加监听器
     *
     * @param listener
     */
    void addListener(Listener<?> listener);

    /**
     * 移除监听器
     *
     * @param listener
     */
    void removeListener(Listener<?> listener);

    /**
     * 发布事件,默认异步执行监听
     *
     * @param event
     */
    void multicastEvent(Event<?> event);

    /**
     * 发布事件,按参数确定异步还是同步执行监听
     *
     * @param event
     * @param async
     */
    void multicastEvent(Event<?> event, boolean async);

}

 

  2)广播器实现类:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.ResolvableType;
import org.springframework.stereotype.Component;

import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 广播器(事件发布器)
 *
 * @author yangyongjie
 * @date 2021/1/28
 */
@Component
public class SimpleEventMulticaster implements EventMulticaster, ApplicationContextAware {

    private static final Logger LOGGER = LoggerFactory.getLogger(SimpleEventMulticaster.class);

    /**
     * 所有监听器的集合
     */
    private final Set<Listener<?>> listeners = new LinkedHashSet<>();

    /**
     * 创建一个执行监听器线程池,核心线程数为2,最大线程数为5,线程空闲时间为60s,拒绝策略为打印日志并直接执行被拒绝的任务
     * 线程数和队列依具体业务而定
     */
    private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(
            2,
            5,
            60, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(50),
            new CustomThreadFactory("simpleEventMulticaster"),
            (r, executor) -> {
                LOGGER.error("Task:{},rejected from:{}", r.toString(), executor.toString());
                // 直接执行被拒绝的任务,JVM另起线程执行
                r.run();
            });

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 获取容器中实现Listener接口的监听器,并添加到listeners缓存中
        Map<String, Listener> listenerMap = applicationContext.getBeansOfType(Listener.class);
        for (Map.Entry<String, Listener> entry : listenerMap.entrySet()) {
            addListener(entry.getValue());
        }
    }

    @Override
    public void addListener(Listener<?> listener) {
        this.listeners.add(listener);
    }

    @Override
    public void removeListener(Listener<?> listener) {
        this.listeners.remove(listener);
    }

    /**
     * 发布事件
     *
     * @param event
     */
    @Override
    public void multicastEvent(Event<?> event) {
        multicastEvent(event, true);
    }

    @Override
    public void multicastEvent(Event<?> event, boolean async) {
        Class eventClass = event.getClass();
        Set<Listener<?>> interestedListeners = getInterestedListeners(eventClass);
        // 事件发生,异步调用监听器的事件方法
        for (Listener<?> listener : interestedListeners) {
            if (async) {
                EXECUTOR.execute(() -> invokeListener(listener, event));
            } else {
                invokeListener(listener, event);
            }
        }
    }

    /**
     * 触发监听器事件处理
     *
     * @param listener
     * @param event
     */
    private void invokeListener(Listener listener, Event event) {
        try {
            listener.onEvent(event);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
    }

    /**
     * 获取对当前事件感兴趣的监听器(监听了当前事件或当前事件的父事件)
     *
     * @param eventClass
     */
    private Set<Listener<?>> getInterestedListeners(Class eventClass) {
        // 存放监听对发布事件感兴趣的监听器
        Set<Listener<?>> interestedListeners = new LinkedHashSet<>();
        for (Listener<?> listener : listeners) {
            // 避免listener被aop代理,因此获取其被代理的listener
            Class<?> targetClass = AopUtils.getTargetClass(listener);
            // 获取监听器的泛型类型(即监听器监听的事件类型)
            ResolvableType genericEventType = ResolvableType.forClass(targetClass).as(Listener.class).getGeneric();
            // 监听器监听的事件类型是否是发布事件类型的父类 或与发布的事件类型相同
            if (genericEventType.isAssignableFrom(eventClass)) {
                interestedListeners.add(listener);
            }
        }
        return interestedListeners;
    }

}

 

4、使用广播器发布事件(在事件源中发布事件)

    @Autowired
    private EventMulticaster eventMulticaster;

    // 发布事件
    eventMulticaster.multicastEvent(new AuditFlowFinishEvent(auditFlow));

 

  V3.0  

   改进:

    痛点:发布事件需要注入EventMulticaster依赖,非常麻烦

    目标:通过工具类直接发布事件,工具类中有EventMulticaster的实例,且工具类不需要作为bean注入到Spring容器中

  1、新建EventCaster:

public class EventCaster {

    private static SimpleEventMulticaster simpleEventMulticaster;

    public static void SetSimpleEventMulticaster(SimpleEventMulticaster simpleEventMulticaster) {
        EventCaster.simpleEventMulticaster = simpleEventMulticaster;
    }

    /**
     * 异步的事件发布
     *
     * @param event
     */
    public static void multicastEvent(Event<?> event) {
        simpleEventMulticaster.multicastEvent(event);
    }

    /**
     * 自定义同步or异步的事件发布
     *
     * @param event
     * @param async
     */
    public static void multicastEvent(Event<?> event, boolean async) {
        simpleEventMulticaster.multicastEvent(event, async);
    }

}

  2、修改SimpleEventMulticaster,为EventCaster设置SimpleEventMulticaster的实例

/**
 * 广播器(事件发布器)
 *
 * @author yangyongjie
 * @date 2020/10/15
 */
@Component
public class SimpleEventMulticaster implements EventMulticaster, ApplicationContextAware, InitializingBean {

    private static final Logger LOGGER = LoggerFactory.getLogger(SimpleEventMulticaster.class);

    private final Set<Listener<?>> listeners = new LinkedHashSet<>();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 获取容器中实现Listener接口的监听器,并添加到listeners缓存中
        Map<String, Listener> listenerMap = applicationContext.getBeansOfType(Listener.class);
        for (Map.Entry<String, Listener> entry : listenerMap.entrySet()) {
            addListener(entry.getValue());
        }
    }

    @Override
    public void afterPropertiesSet() {
        // 为EventCaster设置SimpleEventMulticaster的实例
        EventCaster.SetSimpleEventMulticaster(this);
    }

    @Override
    public void addListener(Listener<?> listener) {
        this.listeners.add(listener);
    }

    @Override
    public void removeListener(Listener<?> listener) {
        this.listeners.remove(listener);
    }

    @Override
    public void multicastEvent(Event<?> event) {
        multicastEvent(event, true);
    }

    @Override
    public void multicastEvent(Event<?> event, boolean async) {
        Class<?> eventClass = event.getClass();
        Set<Listener<?>> interestedListeners = getInterestedListeners(eventClass);
        // 事件发生,异步调用监听器的事件方法
        for (Listener<?> listener : interestedListeners) {
            if (async) {
                ThreadPoolUtil.execute(() -> invokeListener(listener, event));
            } else {
                invokeListener(listener, event);
            }
        }
    }

    private void invokeListener(Listener listener, Event event) {
        try {
            // 睡眠1s等待前面的事务提交
            Thread.sleep(5000);
            listener.onEvent(event);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
            Thread.currentThread().interrupt();
        }
    }

    /**
     * 获取对当前事件感兴趣的监听器(监听了当前事件或当前事件的父事件)
     *
     * @param eventClass
     */
    private Set<Listener<?>> getInterestedListeners(Class<?> eventClass) {
        // 存放监听对发布事件感兴趣的监听器
        Set<Listener<?>> interestedListeners = new LinkedHashSet<>();
        for (Listener<?> listener : listeners) {
            // 避免listener被aop代理,因此获取其被代理的listener
            Class<?> targetClass = AopUtils.getTargetClass(listener);
            // 获取监听器的泛型类型(即监听器监听的事件类型)
            ResolvableType genericEventType = ResolvableType.forClass(targetClass).as(Listener.class).getGeneric();
            // 监听器监听的事件类型是否是发布事件类型的父类 或与发布的事件类型相同
            boolean interested = genericEventType.isAssignableFrom(eventClass);
            if (interested) {
                interestedListeners.add(listener);
            }
        }
        return interestedListeners;
    }

}

  3、发布事件:

 EventCaster.multicastEvent(new NoUpdateCalendarEvent(highEfficientMovie));

 

  v 4.0

  支持事件延迟发布

  EventMulticaster 增加:

    /**
     * 发布事件
     *
     * @param event       事件实例
     * @param async       是否异步
     * @param delayMillis 延迟毫秒数
     */
    void multicastEvent(Event<?> event, boolean async, long delayMillis);

  SimpleEventMulticaster:

/**
 * 广播器(事件发布器)
 *
 * @author yangyongjie
 * @date 2020/10/15
 */
@Component
public class SimpleEventMulticaster implements EventMulticaster, ApplicationContextAware {

    private static final Logger LOGGER = LoggerFactory.getLogger(SimpleEventMulticaster.class);

    private final Set<Listener<?>> listeners = new LinkedHashSet<>();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 获取容器中实现Listener接口的监听器,并添加到listeners缓存中
        Map<String, Listener> listenerMap = applicationContext.getBeansOfType(Listener.class);
        for (Map.Entry<String, Listener> entry : listenerMap.entrySet()) {
            addListener(entry.getValue());
        }
        // 为EventCaster设置SimpleEventMulticaster的实例
        EventCaster.SetSimpleEventMulticaster(this);
    }

    @Override
    public void addListener(Listener<?> listener) {
        this.listeners.add(listener);
    }

    @Override
    public void removeListener(Listener<?> listener) {
        this.listeners.remove(listener);
    }

    @Override
    public void multicastEvent(Event<?> event) {
        multicastEvent(event, true);
    }

    @Override
    public void multicastEvent(Event<?> event, boolean async) {
        multicastEvent(event, async, 0L);
    }

    @Override
    public void multicastEvent(Event<?> event, boolean async, long delayMillis) {
        Class<?> eventClass = event.getClass();
        Set<Listener<?>> interestedListeners = getInterestedListeners(eventClass);
        // 事件发生,异步调用监听器的事件方法
        for (Listener<?> listener : interestedListeners) {
            if (async) {
                ThreadPoolUtil.execute(() -> {
                    // 调用监听器的执行
                    invokeListener(listener, event, delayMillis);
                });
            } else {
                // 调用监听器的执行
                invokeListener(listener, event, delayMillis);
            }
        }
    }

    /**
     * 调用监听器执行
     *
     * @param listener
     * @param event
     */
    private void invokeListener(Listener listener, Event<?> event, long delayMillis) {
        try {
            // 如果延迟时间不为0,则睡眠等待
            if (delayMillis != 0) {
                Thread.sleep(delayMillis);
            }
            listener.onEvent(event);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
    }

    /**
     * 获取对当前事件感兴趣的监听器(监听了当前事件或当前事件的父事件)
     *
     * @param eventClass
     */
    private Set<Listener<?>> getInterestedListeners(Class<?> eventClass) {
        // 存放监听对发布事件感兴趣的监听器
        Set<Listener<?>> interestedListeners = new LinkedHashSet<>();
        for (Listener<?> listener : listeners) {
            // 避免listener被aop代理,因此获取其被代理的listener
            Class<?> targetClass = AopUtils.getTargetClass(listener);
            // 获取监听器的泛型类型(即监听器监听的事件类型)
            ResolvableType genericEventType = ResolvableType.forClass(targetClass).as(Listener.class).getGeneric();
            // 监听器监听的事件类型是否是发布事件类型的父类 或与发布的事件类型相同
            boolean interested = genericEventType.isAssignableFrom(eventClass);
            if (interested) {
                interestedListeners.add(listener);
            }
        }
        return interestedListeners;
    }
}

   EventCaster 增加:

/**
 * 支持事件延迟发布
 * @param event
 * @param async
 * @param delayMillis
 */
public static void multicastEvent(Event<?> event, boolean async, long delayMillis) {
    simpleEventMulticaster.multicastEvent(event,async,delayMillis);
}

  

  最终代码:

 Event:

/**
 * 事件
 *
 * @author yangyongjie
 * @date 2020/9/30
 */
public abstract class Event<T> {
    /**
     * 事件自身资源,用来发布任务时传递一些参数信息
     */
    protected T source;
    /**
     * 事件发生时间
     */
    private final long timestamp;

    protected Event(T source) {
        this.source = source;
        this.timestamp = System.currentTimeMillis();
    }

    public T getSource() {
        return source;
    }

    public void setSource(T source) {
        this.source = source;
    }

    public long getTimestamp() {
        return timestamp;
    }
}

  EventCaster:

/**
 * 事件发布器
 *
 * @author yangyongjie
 */
public class EventCaster {

    private static SimpleEventMulticaster simpleEventMulticaster;

    public static void SetSimpleEventMulticaster(SimpleEventMulticaster simpleEventMulticaster) {
        EventCaster.simpleEventMulticaster = simpleEventMulticaster;
    }

    /**
     * 异步的事件发布
     *
     * @param event
     */
    public static void multicastEvent(Event<?> event) {
        simpleEventMulticaster.multicastEvent(event);
    }

    /**
     * 自定义同步or异步的事件发布
     *
     * @param event
     * @param async
     */
    public static void multicastEvent(Event<?> event, boolean async) {
        simpleEventMulticaster.multicastEvent(event, async);
    }

    /**
     * 支持事件延迟发布
     *
     * @param event
     * @param async
     * @param delayMillis
     */
    public static void multicastEvent(Event<?> event, boolean async, long delayMillis) {
        simpleEventMulticaster.multicastEvent(event, async, delayMillis);
    }

}

  EventMulticaster:

/**
 * 事件广播器
 *
 * @author yangyongjie
 * @date 2020/9/30
 */
public interface EventMulticaster {

    /**
     * 添加监听器
     *
     * @param listener
     */
    void addListener(Listener<?> listener);

    /**
     * 移除监听器
     *
     * @param listener
     */
    void removeListener(Listener<?> listener);

    /**
     * 发布事件,默认异步执行监听
     *
     * @param event
     */
    void multicastEvent(Event<?> event);

    /**
     * 发布事件,按参数确定异步还是同步执行监听
     *
     * @param event
     * @param async
     */
    void multicastEvent(Event<?> event, boolean async);

    /**
     * 发布事件
     *
     * @param event       事件实例
     * @param async       是否异步
     * @param delayMillis 延迟毫秒数
     */
    void multicastEvent(Event<?> event, boolean async, long delayMillis);

}

  Listener:

/**
 * 监听器
 *
 * @author yangyongjie
 * @date 2020/9/30
 */
public interface Listener<E extends Event<?>> {

    /**
     * 当事件发生做一些事件
     *
     * @param event 事件
     * @throws Exception
     */
    void onEvent(E event) throws Exception;
}

 ListenerExecutors:

/**
 * 监听器专用线程池
 *
 * @author yangyongjie
 */
public class ListenerExecutors {

    private ListenerExecutors() {
    }

    private static final Logger LOGGER = LoggerFactory.getLogger(ListenerExecutors.class);

    /**
     * cpu核心数
     */
    private static final int CPU_CORE = Runtime.getRuntime().availableProcessors();

    /**
     * 核心线程数
     */
    private static final int HYPER_THREAD = CPU_CORE * 2;

    /**
     * 线程池
     */
    private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(
            CPU_CORE,
            HYPER_THREAD,
            60,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(10000),
            new ThreadPoolUtil.CustomThreadFactory("common"),
            (r, executor) -> {
                // 打印日志
                String taskName = r.toString();
                LOGGER.error("Task:{}, rejected from common", taskName);
                // 直接执行被拒绝的任务,JVM另起线程执行
                r.run();
            }
    );

    /**
     * 提交线程池处理
     *
     * @param runnable 任务
     */
    protected static void execute(Runnable runnable) {
        EXECUTOR.execute(runnable);
    }

    /**
     * 提交线程池处理任务,可获取返回值
     *
     * @param callable 任务
     * @param <T>      返回值类型
     * @return Future
     */
    protected static <T> Future<T> submit(Callable<T> callable) {
        return EXECUTOR.submit(callable);
    }
}

  SimpleEventMulticaster:

/**
 * 广播器(事件发布器)
 *
 * @author yangyongjie
 * @date 2020/10/15
 */
@Component
public class SimpleEventMulticaster implements EventMulticaster, ApplicationContextAware {

    private static final Logger LOGGER = LoggerFactory.getLogger(SimpleEventMulticaster.class);

    private final Set<Listener<?>> listeners = new LinkedHashSet<>();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 获取容器中实现Listener接口的监听器,并添加到listeners缓存中
        Map<String, Listener> listenerMap = applicationContext.getBeansOfType(Listener.class);
        for (Map.Entry<String, Listener> entry : listenerMap.entrySet()) {
            addListener(entry.getValue());
        }
        // 为EventCaster设置SimpleEventMulticaster的实例
        EventCaster.SetSimpleEventMulticaster(this);
    }

    @Override
    public void addListener(Listener<?> listener) {
        this.listeners.add(listener);
    }

    @Override
    public void removeListener(Listener<?> listener) {
        this.listeners.remove(listener);
    }

    @Override
    public void multicastEvent(Event<?> event) {
        multicastEvent(event, true);
    }

    @Override
    public void multicastEvent(Event<?> event, boolean async) {
        multicastEvent(event, async, 0L);
    }

    @Override
    public void multicastEvent(Event<?> event, boolean async, long delayMillis) {
        Class<?> eventClass = event.getClass();
        Set<Listener<?>> interestedListeners = getInterestedListeners(eventClass);
        // 事件发生,异步调用监听器的事件方法
        for (Listener<?> listener : interestedListeners) {
            if (async) {
                ListenerExecutors.execute(() -> {
                    // 调用监听器的执行
                    invokeListener(listener, event, delayMillis);
                });
            } else {
                // 调用监听器的执行
                invokeListener(listener, event, delayMillis);
            }
        }
    }

    /**
     * 调用监听器执行
     *
     * @param listener
     * @param event
     */
    private void invokeListener(Listener listener, Event<?> event, long delayMillis) {
        try {
            // 如果延迟时间不为0,则睡眠等待
            if (delayMillis != 0) {
                Thread.sleep(delayMillis);
            }
            listener.onEvent(event);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
    }

    /**
     * 获取对当前事件感兴趣的监听器(监听了当前事件或当前事件的父事件)
     *
     * @param eventClass
     */
    private Set<Listener<?>> getInterestedListeners(Class<?> eventClass) {
        // 存放监听对发布事件感兴趣的监听器
        Set<Listener<?>> interestedListeners = new LinkedHashSet<>();
        for (Listener<?> listener : listeners) {
            // 避免listener被aop代理,因此获取其被代理的listener
            Class<?> targetClass = AopUtils.getTargetClass(listener);
            // 获取监听器的泛型类型(即监听器监听的事件类型)
            ResolvableType genericEventType = ResolvableType.forClass(targetClass).as(Listener.class).getGeneric();
            // 监听器监听的事件类型是否是发布事件类型的父类 或与发布的事件类型相同
            boolean interested = genericEventType.isAssignableFrom(eventClass);
            if (interested) {
                interestedListeners.add(listener);
            }
        }
        return interestedListeners;
    }

}

  依赖ThreadPoolUtil:

查看代码
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 线程池工具
 *
 * @author liangjinxin
 */
public final class ThreadPoolUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolUtil.class);

    /**
     * cpu核心数
     */
    public static final int CPU_CORE = Runtime.getRuntime().availableProcessors();

    /**
     * 核心线程数
     */
    public static final int HYPER_THREAD = CPU_CORE * 2;

    /**
     * 线程池
     */
    private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(
            CPU_CORE,
            HYPER_THREAD,
            60,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(10000),
            new CustomThreadFactory("common"),
            (r, executor) -> {
                // 打印日志
                String taskName = r.toString();
                LOGGER.error("Task:{}, rejected from common", taskName);
                // 当前提交任务的线程来直接执行被拒绝的任务,非另起线程执行!
                r.run();
            }
    );

    private ThreadPoolUtil() {
    }

    /**
     * 提交线程池处理
     *
     * @param runnable 任务
     */
    public static void execute(Runnable runnable) {
        EXECUTOR.execute(runnable);
    }

    /**
     * 提交线程池处理任务,可获取返回值
     *
     * @param callable 任务
     * @param <T>      返回值类型
     * @return Future
     */
    public static <T> Future<T> submit(Callable<T> callable) {
        return EXECUTOR.submit(callable);
    }

    /**
     * 创建线程的工厂,指定有意义的线程组名称,方便回溯
     *
     * @author yangyongjie
     */
    public static class CustomThreadFactory implements ThreadFactory {
        /**
         * 线程池中的线程名称前缀
         */
        private final String namePrefix;

        /**
         * 用于线程的名称递增排序
         */
        private final AtomicInteger atomicInteger = new AtomicInteger(1);

        public CustomThreadFactory(String whatFeatureOfGroup) {
            this.namePrefix = "From CustomThreadFactory-" + whatFeatureOfGroup + "-worker-";
        }

        @Override
        public Thread newThread(@Nonnull Runnable r) {
            String name = namePrefix + atomicInteger.getAndIncrement();
            return new Thread(r, name);
        }
    }

}

 

 

 附录

 1)AopTargetUtil:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.framework.AopProxy;
import org.springframework.aop.support.AopUtils;

import java.lang.reflect.Field;

/**
 * 通过代理对象获取被代理的目标对象
 *
 * @author yangyongjie
 * @date 2020/12/10
 * @desc
 */
public class AopTargetUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(AopTargetUtil.class);

    private AopTargetUtil() {
    }

    /**
     * 获取 目标对象
     *
     * @param proxy 代理对象
     * @return
     * @throws Exception
     */
    public static Object getTarget(Object proxy) {

        // 不是代理对象,即没有被aop代理,直接返回
        if (!AopUtils.isAopProxy(proxy)) {
            return proxy;
        }
        try {
            // cglibProxy
            if (AopUtils.isCglibProxy(proxy)) {
                return getCglibProxyTargetObject(proxy);
                // jdkDynamicProxy
            } else {
                return getJdkDynamicProxyTargetObject(proxy);
            }
        } catch (Exception e) {
            LOGGER.error("获取被代理类对象异常:" + e.getMessage(), e);
            return proxy;
        }
    }


    /**
     * CGLIB方式被代理类的获取
     *
     * @param proxy
     * @return
     * @throws Exception
     */
    private static Object getCglibProxyTargetObject(Object proxy) throws Exception {
        Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
        h.setAccessible(true);
        Object dynamicAdvisedInterceptor = h.get(proxy);

        Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
        advised.setAccessible(true);

        Object target = ((AdvisedSupport) advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();

        return target;
    }

    /**
     * JDK动态代理方式被代理类的获取
     *
     * @param proxy
     * @return
     * @throws Exception
     */
    private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception {
        Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
        h.setAccessible(true);
        AopProxy aopProxy = (AopProxy) h.get(proxy);

        Field advised = aopProxy.getClass().getDeclaredField("advised");
        advised.setAccessible(true);

        Object target = ((AdvisedSupport) advised.get(aopProxy)).getTargetSource().getTarget();

        return target;
    }

}
View Code

 

 2)org.springframework.aop.support.AopUtils:

/*
 * Copyright 2002-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.aop.support;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.springframework.aop.Advisor;
import org.springframework.aop.AopInvocationException;
import org.springframework.aop.IntroductionAdvisor;
import org.springframework.aop.IntroductionAwareMethodMatcher;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.aop.SpringProxy;
import org.springframework.aop.TargetClassAware;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.MethodIntrospector;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;

/**
 * Utility methods for AOP support code.
 *
 * <p>Mainly for internal use within Spring's AOP support.
 *
 * <p>See {@link org.springframework.aop.framework.AopProxyUtils} for a
 * collection of framework-specific AOP utility methods which depend
 * on internals of Spring's AOP framework implementation.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Rob Harrop
 * @see org.springframework.aop.framework.AopProxyUtils
 */
public abstract class AopUtils {

    /**
     * Check whether the given object is a JDK dynamic proxy or a CGLIB proxy.
     * <p>This method additionally checks if the given object is an instance
     * of {@link SpringProxy}.
     * @param object the object to check
     * @see #isJdkDynamicProxy
     * @see #isCglibProxy
     */
    public static boolean isAopProxy(@Nullable Object object) {
        return (object instanceof SpringProxy && (Proxy.isProxyClass(object.getClass()) ||
                object.getClass().getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)));
    }

    /**
     * Check whether the given object is a JDK dynamic proxy.
     * <p>This method goes beyond the implementation of
     * {@link Proxy#isProxyClass(Class)} by additionally checking if the
     * given object is an instance of {@link SpringProxy}.
     * @param object the object to check
     * @see java.lang.reflect.Proxy#isProxyClass
     */
    public static boolean isJdkDynamicProxy(@Nullable Object object) {
        return (object instanceof SpringProxy && Proxy.isProxyClass(object.getClass()));
    }

    /**
     * Check whether the given object is a CGLIB proxy.
     * <p>This method goes beyond the implementation of
     * {@link ClassUtils#isCglibProxy(Object)} by additionally checking if
     * the given object is an instance of {@link SpringProxy}.
     * @param object the object to check
     * @see ClassUtils#isCglibProxy(Object)
     */
    public static boolean isCglibProxy(@Nullable Object object) {
        return (object instanceof SpringProxy &&
                object.getClass().getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR));
    }

    /**
     * Determine the target class of the given bean instance which might be an AOP proxy.
     * <p>Returns the target class for an AOP proxy or the plain class otherwise.
     * @param candidate the instance to check (might be an AOP proxy)
     * @return the target class (or the plain class of the given object as fallback;
     * never {@code null})
     * @see org.springframework.aop.TargetClassAware#getTargetClass()
     * @see org.springframework.aop.framework.AopProxyUtils#ultimateTargetClass(Object)
     */
    public static Class<?> getTargetClass(Object candidate) {
        Assert.notNull(candidate, "Candidate object must not be null");
        Class<?> result = null;
        if (candidate instanceof TargetClassAware) {
            result = ((TargetClassAware) candidate).getTargetClass();
        }
        if (result == null) {
            result = (isCglibProxy(candidate) ? candidate.getClass().getSuperclass() : candidate.getClass());
        }
        return result;
    }

    /**
     * Select an invocable method on the target type: either the given method itself
     * if actually exposed on the target type, or otherwise a corresponding method
     * on one of the target type's interfaces or on the target type itself.
     * @param method the method to check
     * @param targetType the target type to search methods on (typically an AOP proxy)
     * @return a corresponding invocable method on the target type
     * @throws IllegalStateException if the given method is not invocable on the given
     * target type (typically due to a proxy mismatch)
     * @since 4.3
     * @see MethodIntrospector#selectInvocableMethod(Method, Class)
     */
    public static Method selectInvocableMethod(Method method, @Nullable Class<?> targetType) {
        if (targetType == null) {
            return method;
        }
        Method methodToUse = MethodIntrospector.selectInvocableMethod(method, targetType);
        if (Modifier.isPrivate(methodToUse.getModifiers()) && !Modifier.isStatic(methodToUse.getModifiers()) &&
                SpringProxy.class.isAssignableFrom(targetType)) {
            throw new IllegalStateException(String.format(
                    "Need to invoke method '%s' found on proxy for target class '%s' but cannot " +
                    "be delegated to target bean. Switch its visibility to package or protected.",
                    method.getName(), method.getDeclaringClass().getSimpleName()));
        }
        return methodToUse;
    }

    /**
     * Determine whether the given method is an "equals" method.
     * @see java.lang.Object#equals
     */
    public static boolean isEqualsMethod(@Nullable Method method) {
        return ReflectionUtils.isEqualsMethod(method);
    }

    /**
     * Determine whether the given method is a "hashCode" method.
     * @see java.lang.Object#hashCode
     */
    public static boolean isHashCodeMethod(@Nullable Method method) {
        return ReflectionUtils.isHashCodeMethod(method);
    }

    /**
     * Determine whether the given method is a "toString" method.
     * @see java.lang.Object#toString()
     */
    public static boolean isToStringMethod(@Nullable Method method) {
        return ReflectionUtils.isToStringMethod(method);
    }

    /**
     * Determine whether the given method is a "finalize" method.
     * @see java.lang.Object#finalize()
     */
    public static boolean isFinalizeMethod(@Nullable Method method) {
        return (method != null && method.getName().equals("finalize") &&
                method.getParameterCount() == 0);
    }

    /**
     * Given a method, which may come from an interface, and a target class used
     * in the current AOP invocation, find the corresponding target method if there
     * is one. E.g. the method may be {@code IFoo.bar()} and the target class
     * may be {@code DefaultFoo}. In this case, the method may be
     * {@code DefaultFoo.bar()}. This enables attributes on that method to be found.
     * <p><b>NOTE:</b> In contrast to {@link org.springframework.util.ClassUtils#getMostSpecificMethod},
     * this method resolves Java 5 bridge methods in order to retrieve attributes
     * from the <i>original</i> method definition.
     * @param method the method to be invoked, which may come from an interface
     * @param targetClass the target class for the current invocation.
     * May be {@code null} or may not even implement the method.
     * @return the specific target method, or the original method if the
     * {@code targetClass} doesn't implement it or is {@code null}
     * @see org.springframework.util.ClassUtils#getMostSpecificMethod
     */
    public static Method getMostSpecificMethod(Method method, @Nullable Class<?> targetClass) {
        Class<?> specificTargetClass = (targetClass != null ? ClassUtils.getUserClass(targetClass) : null);
        Method resolvedMethod = ClassUtils.getMostSpecificMethod(method, specificTargetClass);
        // If we are dealing with method with generic parameters, find the original method.
        return BridgeMethodResolver.findBridgedMethod(resolvedMethod);
    }

    /**
     * Can the given pointcut apply at all on the given class?
     * <p>This is an important test as it can be used to optimize
     * out a pointcut for a class.
     * @param pc the static or dynamic pointcut to check
     * @param targetClass the class to test
     * @return whether the pointcut can apply on any method
     */
    public static boolean canApply(Pointcut pc, Class<?> targetClass) {
        return canApply(pc, targetClass, false);
    }

    /**
     * Can the given pointcut apply at all on the given class?
     * <p>This is an important test as it can be used to optimize
     * out a pointcut for a class.
     * @param pc the static or dynamic pointcut to check
     * @param targetClass the class to test
     * @param hasIntroductions whether or not the advisor chain
     * for this bean includes any introductions
     * @return whether the pointcut can apply on any method
     */
    public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
        Assert.notNull(pc, "Pointcut must not be null");
        if (!pc.getClassFilter().matches(targetClass)) {
            return false;
        }

        MethodMatcher methodMatcher = pc.getMethodMatcher();
        if (methodMatcher == MethodMatcher.TRUE) {
            // No need to iterate the methods if we're matching any method anyway...
            return true;
        }

        IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
        if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
            introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
        }

        Set<Class<?>> classes = new LinkedHashSet<>();
        if (!Proxy.isProxyClass(targetClass)) {
            classes.add(ClassUtils.getUserClass(targetClass));
        }
        classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

        for (Class<?> clazz : classes) {
            Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
            for (Method method : methods) {
                if (introductionAwareMethodMatcher != null ?
                        introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                        methodMatcher.matches(method, targetClass)) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Can the given advisor apply at all on the given class?
     * This is an important test as it can be used to optimize
     * out a advisor for a class.
     * @param advisor the advisor to check
     * @param targetClass class we're testing
     * @return whether the pointcut can apply on any method
     */
    public static boolean canApply(Advisor advisor, Class<?> targetClass) {
        return canApply(advisor, targetClass, false);
    }

    /**
     * Can the given advisor apply at all on the given class?
     * <p>This is an important test as it can be used to optimize out a advisor for a class.
     * This version also takes into account introductions (for IntroductionAwareMethodMatchers).
     * @param advisor the advisor to check
     * @param targetClass class we're testing
     * @param hasIntroductions whether or not the advisor chain for this bean includes
     * any introductions
     * @return whether the pointcut can apply on any method
     */
    public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
        if (advisor instanceof IntroductionAdvisor) {
            return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
        }
        else if (advisor instanceof PointcutAdvisor) {
            PointcutAdvisor pca = (PointcutAdvisor) advisor;
            return canApply(pca.getPointcut(), targetClass, hasIntroductions);
        }
        else {
            // It doesn't have a pointcut so we assume it applies.
            return true;
        }
    }

    /**
     * Determine the sublist of the {@code candidateAdvisors} list
     * that is applicable to the given class.
     * @param candidateAdvisors the Advisors to evaluate
     * @param clazz the target class
     * @return sublist of Advisors that can apply to an object of the given class
     * (may be the incoming List as-is)
     */
    public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
        if (candidateAdvisors.isEmpty()) {
            return candidateAdvisors;
        }
        List<Advisor> eligibleAdvisors = new ArrayList<>();
        for (Advisor candidate : candidateAdvisors) {
            if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
                eligibleAdvisors.add(candidate);
            }
        }
        boolean hasIntroductions = !eligibleAdvisors.isEmpty();
        for (Advisor candidate : candidateAdvisors) {
            if (candidate instanceof IntroductionAdvisor) {
                // already processed
                continue;
            }
            if (canApply(candidate, clazz, hasIntroductions)) {
                eligibleAdvisors.add(candidate);
            }
        }
        return eligibleAdvisors;
    }

    /**
     * Invoke the given target via reflection, as part of an AOP method invocation.
     * @param target the target object
     * @param method the method to invoke
     * @param args the arguments for the method
     * @return the invocation result, if any
     * @throws Throwable if thrown by the target method
     * @throws org.springframework.aop.AopInvocationException in case of a reflection error
     */
    @Nullable
    public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
            throws Throwable {

        // Use reflection to invoke the method.
        try {
            ReflectionUtils.makeAccessible(method);
            return method.invoke(target, args);
        }
        catch (InvocationTargetException ex) {
            // Invoked method threw a checked exception.
            // We must rethrow it. The client won't see the interceptor.
            throw ex.getTargetException();
        }
        catch (IllegalArgumentException ex) {
            throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
                    method + "] on target [" + target + "]", ex);
        }
        catch (IllegalAccessException ex) {
            throw new AopInvocationException("Could not access method [" + method + "]", ex);
        }
    }

}
View Code

 

 

不依赖Spring版本:

1、事件 抽象类Event,其他要监控的事件继承它

/**
 * 事件(抽象类)
 * 自定义事件需继承此接口
 * 事件,即监听什么,如任务即将执行事件、任务执行完毕事件
 *
 * @author yangyongjie
 */
public abstract class Event<T> {
    /**
     * 事件自身资源,用来发布任务时传递一些参数信息
     */
    protected T source;
    /**
     * 事件发生时间
     */
    private final long timestamp;

    protected Event(T source) {
        this.source = source;
        this.timestamp = System.currentTimeMillis();
    }

    public T getSource() {
        return source;
    }

    public void setSource(T source) {
        this.source = source;
    }

    public long getTimestamp() {
        return timestamp;
    }
}

2、监听器接口 Listener,自定义监听器实现它;泛型E表示要监听的事件 

/**
 * 监听器(接口)
 * 自定义监听器需实现此接口
 * 监听感兴趣的事件,当事件发生时,执行一些具体的动作
 *
 * @author yangyongjie
 */
public interface Listener<E extends Event<?>> {

    /**
     * 当事件发生做一些事件
     *
     * @param event 事件
     * @throws Exception
     */
    void onEvent(E event) throws Exception;
}

3、自定义监听器接口实现Listener接口之后

  ①:resources下新建 META-INF/services 文件夹(SPI机制)

  ②:新建Listener接口全路径命名的文件

  ③:在文件中配置Listener实现类的全路径,每行一个

 

4、事件广播器接口

/**
 * 事件广播器(接口)
 * 发布事件、添加/移除监听器
 *
 * @author yangyongjie
 */
public interface EventMulticaster {

    /**
     * 添加监听器
     *
     * @param listener
     */
    void addListener(Listener<?> listener);

    /**
     * 移除监听器
     *
     * @param listener
     */
    void removeListener(Listener<?> listener);

    /**
     * 发布事件,默认异步执行监听
     *
     * @param event
     */
    void multicastEvent(Event<?> event);

    /**
     * 发布事件,按参数确定异步还是同步执行监听
     *
     * @param event
     * @param async
     */
    void multicastEvent(Event<?> event, boolean async);

    /**
     * 发布事件
     *
     * @param event       事件实例
     * @param async       是否异步
     * @param delayMillis 延迟毫秒数
     */
    void multicastEvent(Event<?> event, boolean async, long delayMillis);

}

5、广播器实现类(发布事件,找到对其感兴趣的监听器,触发监听器的执行)

/**
 * 简单的事件广播器
 *
 * @author yangyongjie
 */
public class SimpleEventMulticaster implements EventMulticaster {

    private static volatile SimpleEventMulticaster simpleEventMulticaster;

    private SimpleEventMulticaster() {
    }

    /**
     * 双重检查单例模式
     * @return
     */
    public static SimpleEventMulticaster getInstance() {
        if (simpleEventMulticaster == null) {
            synchronized (SimpleEventMulticaster.class) {
                if (simpleEventMulticaster == null) {
                    simpleEventMulticaster = new SimpleEventMulticaster();
                }
            }
        }
        return simpleEventMulticaster;
    }


    private static final Set<Listener<?>> LISTENERS = new LinkedHashSet<>();

    static {
        ServiceLoader<Listener> loadListeners = ServiceLoader.load(Listener.class);
        Iterator<Listener> litenersIterator = loadListeners.iterator();
        try {
            while (litenersIterator.hasNext()) {
                Listener listener = litenersIterator.next();
                LISTENERS.add(listener);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void addListener(Listener<?> listener) {
        LISTENERS.add(listener);
    }

    @Override
    public void removeListener(Listener<?> listener) {
        LISTENERS.remove(listener);
    }

    @Override
    public void multicastEvent(Event<?> event) {
        multicastEvent(event, true);
    }

    @Override
    public void multicastEvent(Event<?> event, boolean async) {
        multicastEvent(event, async, 0L);
    }

    @Override
    public void multicastEvent(Event<?> event, boolean async, long delayMillis) {
        Class<?> eventClass = event.getClass();
        Set<Listener<?>> interestedListeners = getInterestedListeners(eventClass);
        // 事件发生,异步调用监听器的事件方法
        for (Listener<?> listener : interestedListeners) {
            if (async) {
                ListenerExecutor.execute(() -> {
                    // 调用监听器的执行
                    invokeListener(listener, event, delayMillis);
                });
            } else {
                // 调用监听器的执行
                invokeListener(listener, event, delayMillis);
            }
        }
    }

    /**
     * 调用监听器执行
     *
     * @param listener
     * @param event
     */
    private void invokeListener(Listener listener, Event<?> event, long delayMillis) {
        try {
            // 如果延迟时间不为0,则睡眠等待
            if (delayMillis != 0) {
                Thread.sleep(delayMillis);
            }
            listener.onEvent(event);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取对当前事件感兴趣的监听器(监听了当前事件或当前事件的父事件)
     *
     * @param eventClass
     */
    private Set<Listener<?>> getInterestedListeners(Class<?> eventClass) {
        // 存放监听对发布事件感兴趣的监听器
        Set<Listener<?>> interestedListeners = new LinkedHashSet<>();
        for (Listener<?> listener : LISTENERS) {
            // 获取监听器的泛型类型(即监听器监听的事件类型)
            Class<?> genericClass = getGeneric(listener.getClass(), Listener.class);
            if (genericClass == null) {
                return interestedListeners;
            }
            // 监听器监听的事件类型是否是发布事件类型的父类 或与发布的事件类型相同
            boolean interested = genericClass.isAssignableFrom(eventClass);
            if (interested) {
                interestedListeners.add(listener);
            }
        }
        return interestedListeners;
    }

    private Class<?> getGeneric(Class<?> clazz, Class<?> intfClass) {
        if (intfClass != null) {
            Type[] genericIfcs = clazz.getGenericInterfaces();
            for (Type type : genericIfcs) {
                if (type instanceof ParameterizedType) {
                    ParameterizedType parameterizedType = (ParameterizedType) type;
                    Type rawType = parameterizedType.getRawType();
                    Class<?> rawTypeClass = rawType instanceof Class ? (Class<?>) rawType : null;
                    if (rawTypeClass == null || !rawTypeClass.isAssignableFrom(intfClass)) {
                        continue;
                    }
                    return resolveType(type);
                }
            }
        } else {
            // 返回表示这个类所表示的实体(类、接口、基本类型或void)的直接超类的类型,如果超类是参数化类型,则返回的type对象必须准确反映源代码中使用的实际类型参数
            Type type = clazz.getGenericSuperclass();
            return resolveType(type);
        }
        return null;
    }

    private Class<?> resolveType(Type type) {
        Class<?>[] generics;
        if (type instanceof ParameterizedType) {
            // 获取到父类/父接口的泛型数组
            Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
            int length = actualTypeArguments.length;
            generics = new Class<?>[length];
            // 获取泛型
            for (int i = 0; i < actualTypeArguments.length; i++) {
                Type actualType = actualTypeArguments[i];
                if (actualType instanceof Class) {
                    generics[i] = (Class<?>) actualType;
                }
            }
            return (generics.length == 0 ? null : generics[0]);
        }
        return null;
    }

}

6、监听器执行线程池

/**
 * 监听器执行线程池
 *
 * @author yangyongjie
 */
public final class ListenerExecutor {
    
    private ListenerExecutor() {
    }

    /**
     * cpu核心数
     */
    private static final int CPU_CORE = Runtime.getRuntime().availableProcessors();

    /**
     * 核心线程数
     */
    private static final int HYPER_THREAD = CPU_CORE * 2;

    /**
     * 线程池
     */
    private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(
            CPU_CORE,
            HYPER_THREAD,
            60,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(10000),
            new CustomThreadFactory("listenerExecutor"),
            (r, executor) -> {
                // 打印日志
                // 直接执行被拒绝的任务,JVM另起线程执行
                r.run();
            }
    );

    /**
     * 提交线程池处理
     *
     * @param runnable 任务
     */
    protected static void execute(Runnable runnable) {
        EXECUTOR.execute(runnable);
    }

    /**
     * 提交线程池处理任务,可获取返回值
     *
     * @param callable 任务
     * @param <T>      返回值类型
     * @return Future
     */
    protected static <T> Future<T> submit(Callable<T> callable) {
        return EXECUTOR.submit(callable);
    }

    /**
     * 创建线程的工厂,指定有意义的线程组名称,方便回溯
     *
     * @author yangyongjie
     */
    public static class CustomThreadFactory implements ThreadFactory {
        /**
         * 线程池中的线程名称前缀
         */
        private final String namePrefix;

        /**
         * 用于线程的名称递增排序
         */
        private final AtomicInteger atomicInteger = new AtomicInteger(1);

        public CustomThreadFactory(String whatFeatureOfGroup) {
            this.namePrefix = "From CustomThreadFactory-" + whatFeatureOfGroup + "-worker-";
        }

        @Override
        public Thread newThread(Runnable r) {
            String name = namePrefix + atomicInteger.getAndIncrement();
            return new Thread(r, name);
        }
    }
}

 

使用:

 EventCaster.multicastEvent(new DemoEvent(new HashMap<>()));

 

注意:在toC的项目中禁止使用延时发布事件(事件发布后延时执行),采用sleep方式,会造成线程池任务堆积,从而执行拒绝策略,同时等待队列中任务排队等待时间过长,造成任务执行的积压

 

END.

posted @ 2021-01-28 00:01  杨岂  阅读(342)  评论(0编辑  收藏  举报