Spring提供了事件机制,实现了观察者模式,可以让事件发布者和事件监听者解耦,事件发布者可以发布时间而不需要知道谁会监听,如果实现了异步事件还不会影响主流业务逻辑。
Spring的事件机制,最常用在系统状态监测,系统日志等不影响主线业务的逻辑处理。
例子:
登录事件
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.springframework.context.ApplicationEvent;
public class LoginEvent extends ApplicationEvent {
private static final long serialVersionUID = 7574015506926006629L;
private final Map<String, Object> params = new HashMap<String, Object>();
public LoginEvent(Object source) {
super(source);
}
public void addParam(String key, Object value) {
this.params.put(key, value);
}
public Map<String, Object> getParams() {
return Collections.unmodifiableMap(params);
}
}
登录处理类,例如将登录人数加1
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
public class LoginCounterHandler implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent arg0) {
if (arg0 instanceof LoginEvent) {
// TODO refresh login count
System.out.println("a user login to system");
}
}
}
发布事件
LoginEvent event = new LoginEvent(this);
event.addParam("name", "foo");
ApplicationContextProvider.getApplicationContext().publishEvent(event);
为了实现异步事件处理,这里需要重新实现SimpleApplicationEventMulticaster
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.core.task.TaskExecutor;
public class AsyncApplicationEventMulticaster extends SimpleApplicationEventMulticaster {
private TaskExecutor taskExecutor = new TaskExecutor() {
ExecutorService exeserv = Executors.newCachedThreadPool();
public void execute(Runnable task) {
exeserv.execute(task);
}
};
protected TaskExecutor getTaskExecutor() {
return this.taskExecutor;
}
}
另外为了容易获取applicationContext,加了一个ApplicationContextProvider
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext ctx = null;
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
ctx = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return ctx;
}
}
bean配置
<bean name="applicationEventMulticaster" class="org.jamie.domo.spring.context.AsyncApplicationEventMulticaster" ></bean> <bean id="applicationContextProvider" class="org.jamie.domo.spring.context.ApplicationContextProvider"></bean> <bean name="loginCounterHandler" class="org.jamie.domo.spring.context.LoginCounterHandler"></bean>
总结:真是要感谢Spring提供了很多现成的模式让我们的系统更加的松耦合,给我们带来了很多便利。