TreeviewCopyright @doctording all right reserved, powered by aleen42
事件发布和监听机制
在一个完整的事件体系中,除了事件和监听器以外,还应该有3个概念;
- 事件源:事件的产生者,任何一个event都必须有一个事件源;
- 事件广播器:它是事件和事件监听器之间的桥梁,负责把事件通知给事件监听器;
- 事件监听器注册表:就是spring框架为所有的监听器提供了一个存放的地方;
事件类:ApplicationEvent
ApplicationEvent唯一的构造函数是ApplicationEvent(Object source),通过source指定事件源
/**
* Class to be extended by all application events. Abstract as it
* doesn't make sense for generic events to be published directly.
*
* @author Rod Johnson
* @author Juergen Hoeller
*/
public abstract class ApplicationEvent extends EventObject {
/** use serialVersionUID from Spring 1.2 for interoperability. */
private static final long serialVersionUID = 7099057708183571937L;
/** System time when the event happened. */
private final long timestamp;
/**
* Create a new ApplicationEvent.
* @param source the object on which the event initially occurred (never {@code null})
*/
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
/**
* Return the system time in milliseconds when the event happened.
*/
public final long getTimestamp() {
return this.timestamp;
}
}
abstract class ApplicationContextEvent 容器事件(事件源是ApplicationContext)
public abstract class ApplicationContextEvent extends ApplicationEvent {
/**
* Create a new ContextStartedEvent.
* @param source the {@code ApplicationContext} that the event is raised for
* (must not be {@code null})
*/
public ApplicationContextEvent(ApplicationContext source) {
super(source);
}
/**
* Get the {@code ApplicationContext} that the event was raised for.
*/
public final ApplicationContext getApplicationContext() {
return (ApplicationContext) getSource();
}
}
class RequestHandledEvent extends ApplicationEvent
一个与Web应用相关的事件,当一个请求被处理后,才会产生该事件
public class RequestHandledEvent extends ApplicationEvent {
/** Session id that applied to the request, if any. */
@Nullable
private String sessionId;
/** Usually the UserPrincipal. */
@Nullable
private String userName;
/** Request processing time. */
private final long processingTimeMillis;
/** Cause of failure, if any. */
@Nullable
private Throwable failureCause;
/**
* Create a new RequestHandledEvent with session information.
* @param source the component that published the event
* @param sessionId the id of the HTTP session, if any
* @param userName the name of the user that was associated with the
* request, if any (usually the UserPrincipal)
* @param processingTimeMillis the processing time of the request in milliseconds
*/
public RequestHandledEvent(Object source, @Nullable String sessionId, @Nullable String userName,
long processingTimeMillis) {
super(source);
this.sessionId = sessionId;
this.userName = userName;
this.processingTimeMillis = processingTimeMillis;
}
/**
* Create a new RequestHandledEvent with session information.
* @param source the component that published the event
* @param sessionId the id of the HTTP session, if any
* @param userName the name of the user that was associated with the
* request, if any (usually the UserPrincipal)
* @param processingTimeMillis the processing time of the request in milliseconds
* @param failureCause the cause of failure, if any
*/
public RequestHandledEvent(Object source, @Nullable String sessionId, @Nullable String userName,
long processingTimeMillis, @Nullable Throwable failureCause) {
this(source, sessionId, userName, processingTimeMillis);
this.failureCause = failureCause;
}
public long getProcessingTimeMillis() {
return this.processingTimeMillis;
}
@Nullable
public String getSessionId() {
return this.sessionId;
}
@Nullable
public String getUserName() {
return this.userName;
}
public boolean wasFailure() {
return (this.failureCause != null);
}
@Nullable
public Throwable getFailureCause() {
return this.failureCause;
}
public String getShortDescription() {
StringBuilder sb = new StringBuilder();
sb.append("session=[").append(this.sessionId).append("]; ");
sb.append("user=[").append(this.userName).append("]; ");
return sb.toString();
}
public String getDescription() {
StringBuilder sb = new StringBuilder();
sb.append("session=[").append(this.sessionId).append("]; ");
sb.append("user=[").append(this.userName).append("]; ");
sb.append("time=[").append(this.processingTimeMillis).append("ms]; ");
sb.append("status=[");
if (!wasFailure()) {
sb.append("OK");
}
else {
sb.append("failed: ").append(this.failureCause);
}
sb.append(']');
return sb.toString();
}
@Override
public String toString() {
return ("RequestHandledEvent: " + getDescription());
}
}
事件监听器接口(ApplicationListener)
监听器都需要实现该接口,该接口只定义了一个方法:onApplicationEvent (E event)
,该方法接收事件对象,在该方法中编写事件的响应处理逻辑。
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
例子
- 具体事件,继承
ApplicationContextEvent
public class MailSendEvent extends ApplicationContextEvent {
private static final long serialVersionUID = 1L;
private String to; //目的地
public MailSendEvent(ApplicationContext source, String to) {
super(source);
this.to = to;
}
public String getTo(){
return this.to;
}
}
- 构造事件实例,并发送事件
实现了ApplicationContextAware
能获取到ApplicationContext
,则能进行事件的发布
@Component
public class MailSender implements ApplicationContextAware {
@Autowired
private ApplicationContext applicationContext; // 容器事件由容器触发
public void sendMail(String to){
System.out.println("...ApplicationContextAware");
MailSendEvent event = new MailSendEvent(applicationContext, to);
applicationContext.publishEvent(event);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
- 监听到具体事件
@Component
public class MailSendListener implements ApplicationListener<MailSendEvent> {
@Override
public void onApplicationEvent(MailSendEvent mailSendEvent) {
System.out.println("...onApplicationEvent");
MailSendEvent event = mailSendEvent;
System.out.println("MailSender向"+ event.getTo()+ "发送了邮件");
}
}