spring 事件机制

  在软件开发过程中,有时候我们会遇到需要把具体业务解耦出来,让各个模块只负责相应的处理逻辑.比如说,在我们的抽象业务逻辑中有一个负责开往目的地的司机driver,现在我们的业务系统中不仅要处理司机去往目的地的逻辑,也有其他业务模块需要关注司机具体的目的地是什么地方。然而司机只负责把乘客送到具体地方。不需要负责告诉业务他去哪里。这时候我们可以采用spring的事件机制,让业务解耦。

spring的事件机制包括:

事件源,对应具体的事件.
事件监听器,负责接收具体的事件源.
事件广播器, 负责发布事件源。

  相应的处理逻辑为:事件监听器会注册具体的事件源,当事件广播器广播具体的事件源后,事件监听器能接到该事件的发布消息,然后处理相关事件。

事件源

  定义事件源需要继承spring的ApplicationEvent类,该类有两子类ApplicationContextEvent,RequestHandledEvent.
  ApplicationContextEvent有4个子类,ContextStartedEvent,ContextRefreshedEvent,ContextClosedEvent,ContextStoppedEvent,分别表示容器启动,刷新,关闭,停止的事件。   RequestHandledEvent只有定义了DispatcherServlet时才会产生该事件,它的子类ServletRequestHandledEvent代表Servlet请求事件。
  这里选择定义一个司机行驶的事件类:DriverEvent,它继承于ApplicationContextEvent。它有一个目的地属性destination,然后这里需要实现它的构造函数,提供一个spring的上下文。

package spring;

import lombok.Data;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ApplicationContextEvent;

@Data
public class DriveEvent extends ApplicationContextEvent {

    private String destination;
    public DriveEvent(ApplicationContext source, String destination) {
        super(source);
        this.destination = destination;
    }
}

事件监听器

  定于事件监听器需要实现ApplicationListener接口,我们定义一个DriveEventListener事件监听器,通过泛型注册了它关注的事件DriveEvent,然后实现接口的onApplicationEvent(DriveEvent event),这里我们把事件的目的地打印出来。

package spring;

import org.springframework.context.ApplicationListener;

public class DriveEventListener implements ApplicationListener<DriveEvent> {
    @Override
    public void onApplicationEvent(DriveEvent event) {
        System.out.println("本次哈哈列车开往目的地:" + event.getDestination());
    }
}

事件广播器

  接下来就需要定义事件广播器了,事件的广播器其实是通过spring的上下文ApplicationContext调用它的publishEvent(ApplicationEvent event)方法的,参数就是具体的继承于ApplicationEvent的事件源,这里我们定义一个Driver类,该类负责具体驱车前往目的地,然后发布一个DriveEvent。

package spring;

import org.springframework.context.ApplicationContext;

public class Driver {
    private ApplicationContext applicationContext = SpingContextHolder.getApplicationContext();
    
	public void drive(String destionation) {
        System.out.println("司机开车前往目的地");
        DriveEvent driveEvent = new DriveEvent(applicationContext, destionation);
        applicationContext.publishEvent(driveEvent);
    }
}

  这里可以看到Driver有一个drive(String desctination)方法,它负责具体的驱车逻辑,然后他会通过springcontext发布一个驱车事件,出于方便,我们再定义一个SpingContextHolder来获取spring的上下文。
  在程序中获取spring上下文可以通过指定具体的xml文件,也可以通过实现ApplicationContextAware 接口,然后实现它的setApplicationContext(ApplicationContext ctx)方法,spring会传递当先程序的上下文,我们给该类定义一个静态的上下文变量context,把spring的上下文分配给它。代码如下:

package spring;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class SpingContextHolder implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        context = ctx;
    }

    public static ApplicationContext getApplicationContext(){
        return context;
    }
}

启动类

  现在相应的事件机制组件都已经定义好了,我们这里再定义一个启动类。
  启动类的逻辑流程为:我们在spring的配置文件context.xml中装配一个司机组件driver;程序启动,通过ClassPathXmlApplicationContext来获取司机的bean,司机driver调用drive方法驱车前往目的地。这时候自己的drive方法会发布DriveEvent事件,DriveEventListner会监听到然后打印出司机前往的目的地。这里司机只是在drive方法中发布一个驱车事件,然后驱车前往目的地,具体的处理逻辑通过事件机制交给了监听器处理逻辑,达到了程序解耦的效果。

package spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-context.xml");
        Driver driver = (Driver) applicationContext.getBean("driver");
        driver.drive("上海浦东");
    }
}

spring配置文件:

   <bean id="spingContextHolder" class="spring.SpingContextHolder"/>
   <bean id="driver" class="spring.Driver"/>
   <bean id="driveListener" class="spring.DriveEventListener"/>

总结

  我们通过继承ApplicationEvent类来定义具体的事件,然后实现ApplicationListener来注册具体的事件以及相应的处理逻辑,事件的广播是通过spring的上下文ApplicationContext调用它的publishEvent(ApplicationEvent event)方法来实现的。当事件广播器广播具体的事件源后,事件监听器能接到该事件的发布消息,然后处理相关事件。

转载于:https://my.oschina.net/u/3562205/blog/3083030

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值