当时学习Spring,看到Spring提供了各式各样的接口来让程序员们对Spring进行扩展,并且没有任何侵入性,我不得不佩服Spring的开发者们。这里也是,我们可以看到在客户端找不到任何关于“订阅事件”的影子。
这种实现方式不是太好,可以看到我们在方法内部做了一个判断:接收到的事件是否为ContextRefreshedEvent。
伟大的Spring还提供了泛型的ApplicationListener,我们可以通过泛型的ApplicationListener来完善上面的代码:
@Component public class MyListener implements ApplicationListener<ContextRefreshedEvent> { @Override public void onApplicationEvent(ContextRefreshedEvent event) { System.out.println("刷新了"); } }我们还可以利用Spring中的事件编程模型来自定义事件,并且发布事件:
首先,我们需要定义一个事件,来实现ApplicationEvent接口,代表这是一个Application事件,其实上面所说的四个内置的事件也实现了ApplicationEvent接口:
public class MyEvent extends ApplicationEvent { public MyEvent(Object source) { super(source); } }还需要定义一个监听器,当然,在这里需要监听MyEvent事件:
@Component public class MyListener implements ApplicationListener<MyEvent> { @Override public void onApplicationEvent(MyEvent event) { System.out.println("我订阅的事件已经到达"); } }现在有了事件,也有了监听器,是不是还少了发布者,不然谁去发布事件呢?
@Component public class MyEventPublish implements ApplicationEventPublisherAware { private ApplicationEventPublisher publisher; @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.publisher = applicationEventPublisher; } public void publish(Object obj) { this.publisher.publishEvent(obj); } }发布者,需要实现ApplicationEventPublisherAware 接口,重写publish方法,顾名思义,这就是发布方法,那么方法的参数obj是干嘛的呢,作为发布者,应该需要知道我要发布什么事件,以及事件来源(是谁触发的)把,这个obj就是用来存放这样的数据的,当然,这个参数需要我们手动传入进去。setApplicationEventPublisher是Spring内部主动调用的,可以简单的理解为初始化发布者。
现在就剩最后一个角色了,监听器有了,发布者有了,事件也有了,对,没错,还少一个触发者,毕竟要有触发者去触发事件啊:
@Component public class Service { @Autowired private MyEventPublish publish; public void publish() { publish.publish(new MyEvent(this)); } }其中publish方法就是给客户端调用的,用来触发事件,可以很清楚的看到传入了new MyEvent(this),这样发布者就可以知道我要触发什么事件和是谁触发了事件。
当然,还需要把一切交给Spring管理:
@Configuration @ComponentScan public class AppConfig { }客户端:
public static void main(String[] args) { AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(AppConfig.class); context.getBean(Service.class).publish();; }运行结果:
这一篇博客比较简单,只是简单的应用,但是只有会了应用,才能谈源码。
这篇博客到这里就结束了,谢谢大家。