spring IoC学习 ------IoC容器:ApplicationContext容器内部事件发布
javaSE的自定事件发布:说有的自定义事件类型可以通过拓展EventObject来实现,而事件的监听器则拓展自EventListener。
eg:自定义事件类继承EventObject的MethodExecutionEvent
public class MethodExecutionEvent extends EventObject{ private String methodName; /** * */ private static final long serialVersionUID = 1L; public MethodExecutionEvent(Object source) { super(source); // TODO Auto-generated constructor stub } public MethodExecutionEvent(Object source,String methodName){ super(source); this.methodName = methodName; } public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } }
定义事件监听接口MethodExecutionEventListener继承自EventListener
public interface MethodExecutionEventListener extends EventListener{ /** * 处理方法开始执行的时候发布的MethodExecutionEvent事件 * @param evt */ void onMethodBegin(MethodExecutionEvent evt); /** * 处理方法执行将结束时候发布的MethodExecutionEvent事件 * @param evt */ void onMehtodEnd(MethodExecutionEvent evt); }
MethodExecutionEventListener的实现类:
public class SimpleMethodExecutionEventListener implements MethodExecutionEventListener { public void onMethodBegin(MethodExecutionEvent evt) { // TODO Auto-generated method stub String methodName = evt.getMethodName(); System.out.println("start to ececute the method[" + methodName + "]."); } public void onMehtodEnd(MethodExecutionEvent evt) { // TODO Auto-generated method stub String methodName = evt.getMethodName(); System.out.println("finished to execute the method [" + methodName + "]."); } }
事件发布MethodExecutionEventPublisher:
public class MethodExecutionEventPublisher { private List<MethodExecutionEventListener> listeners = new ArrayList<MethodExecutionEventListener>(); public void methodToMonitor() { MethodExecutionEvent event2Publish = new MethodExecutionEvent(this, "methodToMonitor"); publishEvent(0, event2Publish); /** * 实际逻辑方法 */ System.out.println("this is what i want to do "); publishEvent(1, event2Publish); } protected void publishEvent(int status, MethodExecutionEvent methodExecutionEvent) { List<MethodExecutionEventListener> copyListeners = new ArrayList<MethodExecutionEventListener>( listeners); for (MethodExecutionEventListener listener : copyListeners) { if (status == 0) { listener.onMethodBegin(methodExecutionEvent); } else { listener.onMehtodEnd(methodExecutionEvent); } } } public void addMethodExecutionEventListener( MethodExecutionEventListener listener) { this.listeners.add(listener); } public void removeListener(MethodExecutionEventListener listener) { if (this.listeners.contains(listener)) this.listeners.remove(listener); } public void removeAllListeners() { this.listeners.clear(); } public static void main(String[] args) { MethodExecutionEventPublisher eventPublisher = new MethodExecutionEventPublisher(); eventPublisher .addMethodExecutionEventListener(new SimpleMethodExecutionEventListener()); eventPublisher.methodToMonitor(); } }
上面是javaSE原生的事件监听类。spring的容器内事件发布类允许以context.applicationEvent的形式的事件。容器内注册的context.applicationListener类型的bean定义会被ApplicationContext容器自动识别它们负责监听容器内发布的说有ApplicationEvent事件。
ApplicationEvent:它是一个抽象类,根据不同的情况提供不同的实现。
1.ContextClosedEvent:在ApplicationContext容器咋即将关闭的时候发布的事件类型。
2.ContextRefreshedEvent:在ApplicationContext容器在初始化或者刷新的时候发布的事件类型。
3.RequestHandledEvent:Web请求处理后发布的事件,有一子类ServletRequestHandledEvent提供特定于JavaEE的servlet事件
4.ContextStoppedEvent。
ApplicationListener:使用的自定义事件监听器接口定义,当容器启动时,会自动是被和加载EventListener类型bean定义,一旦容器有事件发布,将通知这些注册到容器的EventListener。
ApplicationContext容器的具体实现类在实现事件发布和事件监听器的注册方面,交给一个称作ApplicationEventMulticaster的接口,这个接口有一个抽象实现类,context.event.AbstractApplcationMulticaster.事件发布功能交给其子类SimpleApplicationEventMulticaster。
ApplicationContext主要用于单一容器内的简单消息通知和处理,并不适合分布式,多进程,多容器之间的事件处理。要让我们的业务类支持容器内的事务发布,需要它拥有ApplicationEventPublisher的事件发布类,有两种方式为我们业务对象注入ApplicationEventPublisher的依赖
1.ApplicationEventPublisherAware接口。
2.ApplicationContextAware接口。
下面是对上面原生的自定义事件处理进行的改造:
事件类:ApplicationContextMethodExecutionEvent
public class ApplicationContextMethodExecutionEvent extends ApplicationEvent{ private String methodName; private int status; /** * */ private static final long serialVersionUID = 1L; public ApplicationContextMethodExecutionEvent(Object source) { super(source); // TODO Auto-generated constructor stub } public ApplicationContextMethodExecutionEvent(Object source ,String methodName,int status){ super(source); this.methodName = methodName; this.status = status; } public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } }
监听器类:ApplicationContextMethodExecutionEventListener
public class ApplicationContextMethodExecutionEventListener implements ApplicationListener{ public void onApplicationEvent(ApplicationEvent evt){ if(evt instanceof ApplicationContextMethodExecutionEvent){ System.out.println("applicationEvent log : want to do something"); } } }
发布器类:ApplicationContextMethodExecutionEventPublisher
public class ApplicationContextMethodExecutionEventPublisher implements ApplicationEventPublisherAware{ private ApplicationEventPublisher eventPublisher; public void methodToMonitor(){ ApplicationContextMethodExecutionEvent beginEvt = new ApplicationContextMethodExecutionEvent(this,"methodToMoniter",0); this.eventPublisher.publishEvent(beginEvt); System.out.println("this is what i want to do"); ApplicationContextMethodExecutionEvent endEvt = new ApplicationContextMethodExecutionEvent(this,"methodToMoniter",1); this.eventPublisher.publishEvent(endEvt); } public void setApplicationEventPublisher( ApplicationEventPublisher applicationEventPublisher) { // TODO Auto-generated method stub this.eventPublisher = applicationEventPublisher; } }
通过xml为其注入容器
<bean id="methodExecListener" class="org.qbrightwork.studysource.springstudyIoc.ApplicationContextMethodExecutionEventListener"></bean> <bean id="evtPublish" class="org.qbrightwork.studysource.springstudyIoc.ApplicationContextMethodExecutionEventPublisher"></bean>
主程序:
public class SpringStudyIocEvent { @Test public void publishEvent(){ ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:config-example8.xml"); ApplicationContextMethodExecutionEventPublisher eventPublisher = (ApplicationContextMethodExecutionEventPublisher)ctx.getBean(ApplicationContextMethodExecutionEventPublisher.class); eventPublisher.methodToMonitor(); } }