美文网首页
spring 事件机制

spring 事件机制

作者: bpker | 来源:发表于2019-08-02 21:29 被阅读0次

      在软件开发过程中,有时候我们会遇到需要把具体业务解耦出来,让各个模块只负责相应的处理逻辑.比如说,在我们的抽象业务逻辑中有一个负责开往目的地的司机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)方法来实现的。当事件广播器广播具体的事件源后,事件监听器能接到该事件的发布消息,然后处理相关事件。

    相关文章

      网友评论

          本文标题:spring 事件机制

          本文链接:https://www.haomeiwen.com/subject/pqmrdctx.html