java中的事件机制的参与者有3种角色
具体的事件源,比如说,你点击一个button,那么button就是event source,要想使button对某些事件进行响应,你就需要注册特定的listener。
事件状态对象,用于 listener 的相应的方法之中,作为参数,一般存在于listerner 的方法之中
当它监听到event object产生的时候,它就调用相应的方法,进行处理。
在这个环境中,可以添加事件监听器,可以产生事件,可以触发事件监听器。例如java对象,或者spring的AbstractApplicationContext
产生Event事件的对象,产生事件的根源。
所有事件对象都应该继承EventObject
package java.util;
import java.io.Serializable;
public class EventObject implements Serializable {
private static final long serialVersionUID = 5516075349620653480L;
protected transient Object source;
public EventObject(Object var1) {
if(var1 == null) {
throw new IllegalArgumentException("null source");
} else {
this.source = var1;
}
}
public Object getSource() {
return this.source;
}
public String toString() {
return this.getClass().getName() + "[source=" + this.source + "]";
}
}
所有事件侦听器接口必须扩展的标记接口。
package java.util;
public interface EventListener {
}
用户在网站注册,系统会发送邮件进行验证
public class User {
private String username;
private String password;
private String email;
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
public class UserEvent extends EventObject {
public UserEvent(Object source){
super(source);
}
}
public class SendEmailEvent extends UserEvent {
public SendEmailEvent(Object source) {
super(source);
}
}
public interface UserListener extends EventListener{
public void onRegister(UserEvent event);
}
public class SendEmailListener implements UserListener {
@Override
public void onRegister(UserEvent event) {
if (event instanceof SendEmailEvent) {
Object source = event.getSource();
User user = (User) source;
System.out.println("send email to " + user.getEmail());
}
}
}
上下文环境,注册监听器,当用户注册的时候,触发事件
public class UserService {
private List listeneres = new ArrayList();
//当用户注册的时候,触发发送邮件事件
public void register(User user){
System.out.println("save " + user.getUsername() + " : " + user.getPassword() + " to database");
UserEvent event = new UserEvent(user);
publishEvent(event);
}
public void publishEvent(UserEvent event){
for(UserListener listener : listeneres){
listener.onRegister(event);
}
}
public void addListeners(UserListener listener){
this.listeneres.add(listener);
}
}
public class Test {
public static void main(String[] args) {
UserService service = new UserService();
service.addListeners(new SendEmailListener());
//添加其他监听器 ...
User user = new User("zhangsan", "123456", "[email protected]");
service.register(user);
}
}
输出:
save zhangsan : 123456 to database
send email to [email protected]
所有的事件对象都要继承自java的EventObject。Spring中所有的事件父接口为ApplicationEvent
package org.springframework.context;
import java.util.EventObject;
public abstract class ApplicationEvent extends EventObject {
private static final long serialVersionUID = 7099057708183571937L;
private final long timestamp;
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
public final long getTimestamp() {
return this.timestamp;
}
}
所有的事件监听器都要实现java的EventListener接口,EventListener是一个标记接口。spring中
所有的事件监听器父接口为ApplicationListener,一般来说事件监听器的方法参数为事件对象。
package org.springframework.context;
import java.util.EventListener;
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}
spring的事件环境为AbstractApplicationContext,在事件环境中,可以注册事件(addApplicationListener),触发事件(publishEvent)
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean {
/** Helper class used in event publishing */
private ApplicationEventMulticaster applicationEventMulticaster;
/** Statically specified listeners */
private final Set> applicationListeners = new LinkedHashSet>();
/** ApplicationEvents published early */
private Set earlyApplicationEvents;
//触发事件
@Override
public void publishEvent(ApplicationEvent event) {
publishEvent(event, null);
}
//触发事件
@Override
public void publishEvent(Object event) {
publishEvent(event, null);
}
//触发事件
protected void publishEvent(Object event, ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
}
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent
sping容器启动的时候,会自动扫描所有实现applicationListener接口的类,并注册到容器中,
当特定事件发生时,会调用相应事件的监听器。
spring 容器启动的时候会调用AbstractApplicationContext的refresh方法,其中有一步为registerListeners()
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
//查找并注册监听器
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
//完成刷新,会触发相应事件
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
可以看到,在registerListeners();方法中将所有实现了ApplicationListener的类添加到了监听器集合中。
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
//查找所有ApplicationListener
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
Set earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
在finishRefresh方法后调用了publishEvent方法,触发了上下文更新事件。在AbstractApplicationContext类中的很多方法中都可以看到调用了publishEvent方法。
protected void finishRefresh() {
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
//触发ContextRefreshedEvent事件
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}