`
cyril0513
  • 浏览: 15147 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

使用Spring的事件机制

阅读更多
最近一个项目,我们应用了Spring的事件机制,它是基于观察者设计模式的思想,但是有点差异的是还需要实现ApplicationContextAware,因为我们要拿到applicationContext来触发我们的事件,然后由Spring回调,将对象传进来,这样我们就可以很方便的访问所有的Bean,或者做一些其他的事情,比如发布事件。
还需要实现一个ApplicationListener,这个就是我们的观察者了,表示当某个事件被触发了,我们该做点什么。
其次就需要去定义事件,例如流程结束事件,一个购物系统当订单流程已经结束了,我们需要通知发货员发货,这个时候我们的这个通知发货,就是一个观察者,我们需要实现通知,比如短信,邮件通知,来告知物流
定制自己的事件,需要继承ApplicationEvent。
下面这幅图,是我画的很简单的一个图,这就是核心的方法和核心的类。

然后我们看看源代码是怎么做的:
//这个其实很简单,调用转交给multicastEvent方法。
public void publishEvent(ApplicationEvent event) {
		Assert.notNull(event, "Event must not be null");
		if (logger.isTraceEnabled()) {
			logger.trace("Publishing event in " + getDisplayName() + ": " + event);
		}
		getApplicationEventMulticaster().multicastEvent(event);
		if (this.parent != null) {
			this.parent.publishEvent(event);
		}
	}


//当某个事件被触发,这里会轮训的通知整个Application的观察者,所以我们在每个观察中都要判断一下,该事件源和事件,是不是我们需要关心的。否则每个都要跑一遍
@SuppressWarnings("unchecked")
	public void multicastEvent(final ApplicationEvent event) {
		for (final ApplicationListener listener : getApplicationListeners(event)) {
			Executor executor = getTaskExecutor();
			if (executor != null) {
				executor.execute(new Runnable() {
					public void run() {
	//这里回调我们的listener中的对应处理逻辑					listener.onApplicationEvent(event);
					}
				});
			}
			else {
				listener.onApplicationEvent(event);
			}
		}
	}

样例:
自定义的事件:
public class PersonFullEvent extends ApplicationEvent {

	public PersonFullEvent(Object source) {
		super(source);
	}

}

public class MessageService implements ApplicationListener,
		ApplicationContextAware {

	private ApplicationContext context;
	private List<Person> persons = new ArrayList<Person>(5);

	public void addMessage(Person p) {
		if (persons.size() > 5) {
			context.publishEvent(new PersonFullEvent(p));
			return;
		}
		persons.add(p);
	}

	public void onApplicationEvent(ApplicationEvent event) {

		Object eventSource = event.getSource();
                  //这里一定要判断事件源
		if (!(eventSource instanceof Person))
			return;
                  //判断事件源之后,还要判断是否是这个事件,因为一个事件源可能有多个事件。但我们这里只是关心这个事件

		if (event instanceof PersonFullEvent) {
			System.out.println("test event successful");
		}

	}

	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		context = applicationContext;

	}

测试代码:

ApplicationContext context = new ClassPathXmlApplicationContext(
				new String[]{"bean.xml"});
	MessageService ms = context.getBean(MessageService.class);
		Person p=new Person();
		for(int i=0;i<10;i++)
		{
			ms.addMessage(new Person());
		}


Spring的另一个对外接口非常好用,ApplicationListener,这个接口是当Spring做某些事情之后会发出一个对应的事件,其实就是一个观察者模式.
比如:我们判断整个Spring容器启动完毕之后,我们需要做一些相应的动作,例如校验集群中是否存在同名服务器等,如果存在则退出。

public class ClusterCheck implements ApplicationListener, DisposableBean{
   
    public void onApplicationEvent(ApplicationEvent event) {
      //Spring容器启动完毕会发出ContextRefreshedEvent事件
      if (event == null || !(event instanceof     ContextRefreshedEvent))
			return;
       //然后这里做相应的自身的逻辑

    }



}


  • 大小: 17.3 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics