上一篇讲了spring默认的一些事件。其实,spring的事件机制还支持我们自定义事件类型。
1.事件
凡是自定义事件需要继承ApplicationEvent.
spring的几个默认事件也属于该类的子类。
public class testEvent extends ApplicationEvent {
public testEvent(Object source) {
super(source);
}
public String toString(){
return "My test Event";
}
}
2.事件的发布
涉及到两个重要的类似:ApplicationEventPublisher及ApplicationEventMulticaster
发布事件时,调用
@Autowired
private FileService fileService;
@Autowired
public ApplicationEventPublisher applicationEventPublisher;
//invokeAl
@RequestMapping(value = "/eventTest", method = RequestMethod.GET)
public String test3() {
StopWatch sw=new StopWatch( );
sw.start();
applicationEventPublisher.publishEvent( new testEvent( "I tested event!" ) );
sw.stop();
System.out.print( "cost time:"+sw.prettyPrint() );
return "event tested";
}
通过publishEvent的源码可以发现,protected void publishEvent(Object event, ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
if(this.logger.isTraceEnabled()) {
this.logger.trace("Publishing event in " + this.getDisplayName() + ": " + event);
}
Object applicationEvent;
if(event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent)event;
} else {
applicationEvent = new PayloadApplicationEvent(this, event);
if(eventType == null) {
eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
}
}
if(this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
} else {
this.getApplicationEventMulticaster().multicastEvent((ApplicationEvent)applicationEvent, eventType);
}
if(this.parent != null) {
if(this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext)this.parent).publishEvent(event, eventType);
} else {
this.parent.publishEvent(event);
}
}
他其实是将事件交给ApplicationEventMultiCaster去处理。再通过multiCastEvent源码可以发现:
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = eventType != null?eventType:this.resolveDefaultEventType(event);
Iterator var4 = this.getApplicationListeners(event, type).iterator();
while(var4.hasNext()) {
final ApplicationListener listener = (ApplicationListener)var4.next();
Executor executor = this.getTaskExecutor();
if(executor != null) {
executor.execute(new Runnable() {
public void run() {
SimpleApplicationEventMulticaster.this.invokeListener(listener, event);
}
});
} else {
this.invokeListener(listener, event);
}
}
如果给MultiCasterEvent设置了executor,可以实现多线程,如果为null,则是单线程处理。所以,我们可以注入自定义的ApplicationMultiCaster来实现异步的事物处理:
@Configuration public class AsynConfigure { @Bean(name = "applicationEventMulticaster") public ApplicationEventMulticaster simpleApplicationEventMulticaster() { SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster(); eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor()); return eventMulticaster; } }这里重新注入了一个SimpleApplicationEventMulticaster,并为他设置了executor.所以事物会异步处理。但是这样的异步是全局异步,有时候,有些事件可能不需要异步,有些事件需要。这种方式就不太灵活。下面会介绍另外一种方式。
三 事件监听
定义自己的事件监听(处理)类,需要实现ApplicationListener接口。他只有一个方法,就是void onApplicationEvent(E event); 如果一个事件有几个监听器呢,又想指定他们的顺序,此时,可以实现SmartApplicationListener 接口。他有一个方法getOrder可以返回监听器的执行顺序,值越小,则优先级越高。
@Component
public class testEventListener implements ApplicationListener<testEvent> {
public void onApplicationEvent(testEvent event) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(event.toString());
}
}
上面提到了,给SimpleApplicationEventMulticaster设置executor可以实现全局的异步。还有一种更灵活的方式,spring3提供了@Aync注解来完成异步调用。此时我们可以使用这个新特性来完成异步调用。不仅支持异步调用,还支持简单的任务调度。直接在
onApplicationEvent方法上加上该注解即可。
其实我在思考这种机制跟使用其他消息队列实现的事物机制有何异同,例如rabbitMq 实现pub/sub等
1.简单,不需要再维护rabbitMq?
2.rabbitMq那种用于事件的发布者和处理者属于分布与不同的服务中,此时,spring的这种机制显然不支持。spring的事件机制仅支持在本服务内呢。但是,如果本服务内的,还有必要用事物吗?发生的时候直接写处理逻辑就可以了呀,可能还是会提高一些事物处理性能吧。
我只想到以上两点,不知道理解的对不对呢。