ApplicationEvent,ApplicationListener,ApplicationEventPublisher是Spring为我们我们提供的一个事件监听 订阅的实现,内部实现原理是观察者设计模式.设计初衷也是为了系统业务逻辑之间的解耦,提高可扩展性以及可维护性.事件发布者并不需要考虑谁去监听,监听具体的实现内容是什么,发布者的工作只是发布事件.

maven依赖

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.1.8.RELEASE</version>
      <scope>compile</scope>
    </dependency>

event相关都在context中,可以直接引入spring-boot-starter-web,方便测试.

之前有自己实现简单的观察者模式code案例,现在我们先使用Spring的事件监听机制来具体应用,然后再来看看它的优雅的实现.

模拟监听订单通知

创建订单的Entity,只是一个单纯的数据载体.实际中可以是任意类型.和我们之前在订阅者中定义的变量意义是一样的.

public class Order implements Serializable {
    private static final long serialVersionUID = 950785587954473342L;
    /**
     * 订单号
     */
    private Long id;
    /**
     * 订单价格
     */
    private float price;

    public Order() {
    }

    public Order(Long id, float price) {
        this.id = id;
        this.price = price;
    }

}

创建一个Event

public class OrderEvent extends ApplicationEvent {

    private Order order;
    /**
     * Create a new ApplicationEvent.
     * @param source the object on which the event initially occurred (never {@code null})
     */
    public OrderEvent(Object source, Order order) {
        super(source);
        this.order = order;
    }

    public Order getOrder() {
        return order;
    }
}

创建监听,当订单过来时打印出订单信息

@Component
public class OrderListener1 {

    @EventListener
    public void listener(OrderEvent orderEvent){
        System.out.println(orderEvent.getOrder().getId() + ":" + orderEvent.getOrder().getPrice());
    }
}

这个使用注解方式实现监听,再创建一个监听者继承ApplicationListener实现监听功能.
Spring提供了四种实现监听的方式,点击查看

@Component
public class OrderListener2 implements ApplicationListener<OrderEvent> {

    @Override
    public void onApplicationEvent(OrderEvent event) {
        Order order = event.getOrder();
        System.out.println(order.getId() + ":" + order.getPrice());
    }
}

创建一个controller, 模式生成订单

@RestController
public class TestController {

    @Autowired
    private ApplicationContext applicationContext;

    @RequestMapping("/demo")
    public void demo(){
        applicationContext.publishEvent(new OrderEvent(this, new Order(1L, 1.2f)));
    }
}

运行结果

spring监听浏览器关闭 spring监听机制_设计模式

简单的类图

spring监听浏览器关闭 spring监听机制_观察者模式_02

源码具体实现

spring监听浏览器关闭 spring监听机制_设计模式_03


spring监听浏览器关闭 spring监听机制_观察者模式_04


ApplicationListener泛型就是订阅的事件

最重要的触发事件的过程,可以看到上面是通过ApplicationContext发布的事件.

spring监听浏览器关闭 spring监听机制_spring_05


因为继承了ApplicationEventPublisher,所以调用的是ApplicationEventPublisher的publishEvent()方法

spring监听浏览器关闭 spring监听机制_设计模式_06


真正调用的是AbstractApplicationContext的publishEvent()方法,在AbstractApplicationContext维护了监听者的Set,有publishEvent的默认实现.

spring监听浏览器关闭 spring监听机制_事件监听_07


事件的发布又由SimpleApplicationEventMulticaster进行代理播放

spring监听浏览器关闭 spring监听机制_设计模式_08


spring监听浏览器关闭 spring监听机制_事件监听_09

到这里大概就知道了,Spring的监听机制是观察者模式的实践,并且以很优雅的方式.可以方便的扩展多个监听器或事件.对我们程序来说也是耦合大大降低.