3.2.6.4. Events
Events
bean 封装了应用程序范围内的事件发布功能。应用程序事件可用于在松耦合的组件之间交换信息。Events
bean 是 Spring Framework 的 ApplicationEventPublisher
的简单外观设计模式实现。
public interface Events {
String NAME = "cuba_Events";
void publish(ApplicationEvent event);
}
此接口只有接收一个事件对象作为参数的 publish()
方法。Events.publish()
会通知所有应用程序内注册的匹配的监听器。可以使用 PayloadApplicationEvent
将任何对象发布为事件。
另请参阅 Spring 框架入门
bean 中的事件处理
首先,创建一个新的事件类,继承 ApplicationEvent
类。事件类可以包含任何其它数据。例如:
package com.company.sales.core;
import com.haulmont.cuba.security.entity.User;
import org.springframework.context.ApplicationEvent;
public class DemoEvent extends ApplicationEvent {
private User user;
public DemoEvent(Object source, User user) {
super(source);
this.user = user;
}
public User getUser() {
return user;
}
}
Bean 对象可以使用 Events
bean 发布事件:
package com.company.sales.core;
import com.haulmont.cuba.core.global.Events;
import com.haulmont.cuba.core.global.UserSessionSource;
import com.haulmont.cuba.security.global.UserSession;
import org.springframework.stereotype.Component;
import javax.inject.Inject;
@Component
public class DemoBean {
@Inject
private Events events;
@Inject
private UserSessionSource userSessionSource;
public void demo() {
UserSession userSession = userSessionSource.getUserSession();
events.publish(new DemoEvent(this, userSession.getUser()));
}
}
默认情况下,所有事件都是同步处理的。
处理事件有两种方法:
实现
ApplicationListener
接口。方法使用
@EventListener
注解。
在第一种情况下,必须创建一个实现 ApplicationListener
接口的 bean,以需要事件类型作为泛型参数:
@Component
public class DemoEventListener implements ApplicationListener<DemoEvent> {
@Inject
private Logger log;
@Override
public void onApplicationEvent(DemoEvent event) {
log.debug("Demo event is published");
}
}
第二种方法可用于隐藏实现接口的细节并在单个 bean 中监听多个事件:
@Component
public class MultipleEventListener {
@Order(10)
@EventListener
protected void handleDemoEvent(DemoEvent event) {
// handle event
}
@Order(1010)
@EventListener
protected void handleUserLoginEvent(UserLoggedInEvent event) {
// handle event
}
}
如果确实需要在带有接口的 bean 中监听事件,可以通过实现 |
可以使用 Spring 框架的 Ordered
接口和 @Order
注解来对事件处理方法排序。框架中所有 bean 和事件处理方法使用的是 100 到 1000 之间的 order
值,因此可以在框架的 order 值之前或之后添加自定义的处理顺序。如果要在平台 bean 之前添加 bean 或事件处理程序,可使用小于 100 的值。
另请参阅登录事件.
UI 界面中的事件处理
通常,Events
将事件的发布委托给 ApplicationContext
执行。在 Web 层,可以为事件类使用特殊的接口 - UiEvent
。这是一个事件的标记接口,实现这个接口的事件被发送到当前 UI 实例中的 UI 界面(当前 Web 浏览器标签页)。请注意,UiEvent
实例不会发送到 Spring bean。
示例事件类:
package com.company.sales.web;
import com.haulmont.cuba.gui.events.UiEvent;
import com.haulmont.cuba.security.entity.User;
import org.springframework.context.ApplicationEvent;
public class UserRemovedEvent extends ApplicationEvent implements UiEvent {
private User user;
public UserRemovedEvent(Object source, User user) {
super(source);
this.user = user;
}
public User getUser() {
return user;
}
}
可以在窗口的控制器中使用 Events
bean 触发事件,使用方式和在 bean 中一样:
@Inject
Events events;
// ...
UserRemovedEvent event = new UserRemovedEvent(this, removedUser);
events.publish(event);
为了处理事件,必须在 UI 界面中使用注解 @EventListener
定义方法(不支持 ApplicationListener
接口):
@Order(15)
@EventListener
protected void onUserRemove(UserRemovedEvent event) {
notifications.create()
.withCaption("User is removed " + event.getUser())
.show();
}
可以使用 @Order
注解为事件监听器设定执行顺序。
如果一个事件是 UiEvent
并使用来自 UI 线程的 Events
bean 触发,那么带有 @EventListener
方法的打开的窗口或 frame 将接收到该事件。事件处理是同步的。只有用户打开的当前 Web 浏览器标签页中 UI 界面才会收到该事件。