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提供了很多现成的模式让我们的系统更加的松耦合,给我们带来了很多便利。