spring框架四个基础核心三(事件监听)

157 阅读3分钟

1.引言

spring框架有四个基础核心:

  • IoC容器
  • JavaConfig
  • 事件监听
  • Spring factories

2.事件监听

关于什么是事件监听?

有一定开发经验的朋友,事件监听都不陌生。在我刚毕业的的时候,以至还在学校的时候,还一定程度上有机会见识java桌面应用开发(swing),当然今天其实也还有基于swing开发的一些工具型应用,比如大名鼎鼎的性能压测工具:Jmeter。

为什么我会提到swing桌面应用开发呢?因为做过GUI开发的同学,对事件监听这个事显得更亲切!

话说回来,你要没有做过桌面应用开发,也没有关系。基于servlet的web应用开发,里面是不是也有监听器?比如说:ServletRequestListener,SessionListener,ServletContextListener等

哪怕没有机会写原生的servlet,spring 框架提供的ContextLoaderListener,总还有印象的吧!

话说回来,事件监听到底是怎么一回事呢?它其实就是观察者模式的体现,比如考试的时候,有监考老师时刻盯着你,一旦你作弊,或者想作弊,监考老师马上直勾勾的看着你。像这样的

image.png

spring 提供事的件监听

在基于spring的应用中,有时候我们需要在应用启动的时候,做一些初始化资源的事情,比如说线程池、比如说初始化调度任务。可以通过扩展ApplicationListener来承担实现这样的需求,ApplicationListener即是spring框架提供的监听器。

spring应用提供了完整的事件监听组件

  • 事件:ApplicationEvent,在spring应用启动的时候,会通过ApplicationContext发布相关的事件,比如刷新容器事件ContextRefreshedEvent,比如容器关闭事件ContextClosedEvent
  • 事件监听器:ApplicationListener,监听处理通过ApplicationContext发布的相关事件
  • 事件发布者:ApplicationContext

基于以上组件,可以灵活进行扩展实现各种需求。只需要扩展ApplicationListener接口,监听特定类型事件,再通过ApplicationContext在合适的时机发布事件即可。

java原生事件监听案例

spring提供了完整的事件监听机制,如果我们不使用spring框架,或者说我想知道spring框架的事件监听的底层实现。事实上非常简单!java原生就提供了事件监听的机制和组件

  • 事件:EventObject
  • 监听器:EventListener

基于以上两个组件,我们就能实现满足应用需要的事件监听。下面跟着我来完成一个案例,看完案例相信你就能明白了。

案例说明:通过原生的java事件监听组件,实现统计方法执行耗时。

扩展事件
package com.anan.edu.common.event;

import java.util.EventObject;

/**
 * 方法执行耗时 事件 Event
 *
 * @author ThinkPad
 */
public class MonitorMethodTimeEvent extends EventObject {

    /**
     * 时间
     */
    public Long time;

    public MonitorMethodTimeEvent(Object source) {
        super(source);
    }
}
扩展监听器

接口:

package com.anan.edu.common.event;

import java.util.EventListener;

/**
 * 事件监听器接口
 *
 * @author ThinkPad
 */
public interface MonitorMethodTimeEventListener extends EventListener{

    /**
     * 方法开始
     * @param event
     */
    void onBegin(MonitorMethodTimeEvent event);

    /**
     * 方法结束
     * @param event
     */
    void onEnd(MonitorMethodTimeEvent event);
}

实现类:

package com.anan.edu.common.event;

import lombok.extern.slf4j.Slf4j;

/**
 * 事件监听器具体实现
 *
 * @author ThinkPad
 */
@Slf4j
public class MyMonitorMethodTimeEventListener implements MonitorMethodTimeEventListener {

    /**
     * 方法开始
     *
     * @param event
     */
    @Override
    public void onBegin(MonitorMethodTimeEvent event) {
        event.time = System.currentTimeMillis();
    }

    /**
     * 方法结束
     *
     * @param event
     */
    @Override
    public void onEnd(MonitorMethodTimeEvent event) {
        Long time = System.currentTimeMillis() - event.time;
        log.info("方法执行耗时:{}", time);
    }
}
定义事件发布者
package com.anan.edu.common.event;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

/**
 * 事件发布者
 *
 * @author ThinkPad
 */
public class MonitorMethodTimeEventPublisher {
    // 监听器集合
    private static List<MonitorMethodTimeEventListener> list =
        new ArrayList<MonitorMethodTimeEventListener>();

    public static void main(String[] args) {
        // 监听器
        MonitorMethodTimeEventListener listener = new MyMonitorMethodTimeEventListener();
        list.add(listener);

        // 方法监听
        MonitorMethodTimeEventPublisher publisher = new MonitorMethodTimeEventPublisher();
        publisher.monitor();

    }

    /**
     * 监听
     */
    public void monitor(){
        // 发布事件
        MonitorMethodTimeEvent event = new MonitorMethodTimeEvent(this);
        publishEvent("begin", event);

        // 模拟方法执行时间
        try {
            TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(10));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        publishEvent("end", event);
    }
    /**
     * 发布事件
     * @param type
     * @param event
     */
    private static void publishEvent(String type,MonitorMethodTimeEvent event){
        list.forEach(listener ->{
            if("begin".equals(type)){
                listener.onBegin(event);
            }else if("end".equals(type)){
                listener.onEnd(event);
            }
        });
    }
}

通过以上代码,即完成了一个java原生事件监听的案例。我们说万变不离其宗,当你在使用各种开发框架,比如spring,比如mybatis框架的时候,它们所提供的事件监听不外乎是如此。