SpringApplicationEventExample
https://github.com/xiaoheike/SpringApplicationEventExample.git
package nd.esp.com.event; import org.springframework.context.ApplicationEvent; public class SportEvent extends ApplicationEvent { private static final long serialVersionUID = 1L; public SportEvent(Object source) { super(source); } }
SportEvent
是所有体育运动的父类,继承Spring ApplicationEvent
,必须实现带参数构造函数,如上述代码所示。带参数构造函数传入参数可用于携带其他的信息。具体在NBAEvent
中可以看到作用。
package nd.esp.com.event; public class NBAEvent extends SportEvent { private static final long serialVersionUID = 1L; private String text; public NBAEvent(Object source) { super(source); } public NBAEvent(String source, String text) { super(source); this.text = text; } public String news() { return text; } @Override public String getSource() { return String.class.cast(super.getSource()); } }
NBAEvent
主题,用于显示NBA相关信息,上述getSource()
方法重写了Spring ApplicationEvent 的父类EventObject
,可以用于获得构造函数传入的参数。
package nd.esp.com.event; public class SoccerEvent extends SportEvent { private static final long serialVersionUID = 1L; private String text; public SoccerEvent(String source) { super(source); } public SoccerEvent(Object source, String text) { super(source); this.text = text; } public String news() { return text; } @Override public String getSource() { return String.class.cast(super.getSource()); } }
SoccerEvent
主题,用于显示足球先关信息,和NBAEvent
功能类似。
package nd.esp.com.listener; import nd.esp.com.event.NBAEvent; import nd.esp.com.event.SoccerEvent; import nd.esp.com.event.SportEvent; import org.springframework.context.ApplicationListener; public class SportEventListener implements ApplicationListener<SportEvent> { public void onApplicationEvent(SportEvent event) { if (event instanceof NBAEvent) { System.out.println("SportEventListener1:" + NBAEvent.class.cast(event).getSource()); } if (event instanceof SoccerEvent) { SoccerEvent soccerEvent = SoccerEvent.class.cast(event); System.out.println("SportEventListener1:" + soccerEvent.getSource() + " " + soccerEvent.news()); } } }
package nd.esp.com.listener; import nd.esp.com.event.NBAEvent; import nd.esp.com.event.SoccerEvent; import nd.esp.com.event.SportEvent; import org.springframework.context.ApplicationListener; public class SportEventListener2 implements ApplicationListener<SportEvent> { public void onApplicationEvent(SportEvent event) { if (event instanceof NBAEvent) { System.out.println("SportEventListener2:" + NBAEvent.class.cast(event).getSource()); } if (event instanceof SoccerEvent) { SoccerEvent soccerEvent = SoccerEvent.class.cast(event); System.out.println("SportEventListener2:" + soccerEvent.getSource() + " " + soccerEvent.news()); } } }
SportEventListener
是观察者,当有新事件到来会被调用。SportEvent
的功能在这里得到体现,通过创建父类,可以同时监控一类相似的主题,比如NBA事件以及足球事件。这样可以少些监听者。可以有多个观察者监听相同的时间,这里是指SportEvent。
package nd.esp.com.publisher; import nd.esp.com.event.NBAEvent; import nd.esp.com.event.SoccerEvent; import nd.esp.com.event.SportEvent; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SportEventPublisher implements ApplicationContextAware { private ApplicationContext applicationEventPulisher = null; public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationEventPulisher = applicationContext; } public void publishEvent(SportEvent sportEvent) { applicationEventPulisher.publishEvent(sportEvent); } public static void main(String[] args) { String[] xmlConfig = new String[] { "applicationContext.xml" }; // 使用ApplicationContext来初始化系统 ApplicationContext context = new ClassPathXmlApplicationContext(xmlConfig); SportEventPublisher publisher = (SportEventPublisher) context.getBean("applicationContextAware"); publisher.publishEvent(new NBAEvent("NBA sport:骑士队获得总冠军")); publisher.publishEvent(new SoccerEvent("Scorrer sport:标题:中国获得世界杯冠军", "中国击败世界各国,取得10连冠")); } }
SportEventPublisher
当有新的时间时,由它发布,这个类继承Spring ApplicationContextAware
,能够自动注入ApplicationContext
对象。这个类实现了主题的通知功能。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="applicationContextAware" class="nd.esp.com.publisher.SportEventPublisher"></bean> <bean id="applicationListener1" class="nd.esp.com.listener.SportEventListener1"></bean> <bean id="applicationListener2" class="nd.esp.com.listener.SportEventListener2"></bean> </beans>
这两个bean是必须的,id可以任意,spring针对SportEventPublisher
肯定是有经过特殊处理的,要不然该类中的ApplicationEventPublisher
无法注入对应类。
这样的配置默认是采用单线程,为了提高效率可以使用多线程。修改application.xml
文件如下即可。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="applicationContextAware" class="nd.esp.com.publisher.SportEventPublisher"></bean> <bean id="applicationListener1" class="nd.esp.com.listener.SportEventListener1"></bean> <bean id="applicationListener2" class="nd.esp.com.listener.SportEventListener2"></bean> <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <property name="corePoolSize" value="5" /> <property name="keepAliveSeconds" value="30000" /> <property name="maxPoolSize" value="1000" /> <property name="queueCapacity" value="200" /> </bean> <bean id="applicationEventMulticaster" class="org.springframework.context.event.SimpleApplicationEventMulticaster"> <property name="taskExecutor" ref="taskExecutor" /> </bean> </beans>
idapplicationEventMulticaster
不能够改变,猜测是spring需要根据这个id注入对象。
多线程或者单线程可以通过该类中的方法
@SuppressWarnings("unchecked") public void multicastEvent(final ApplicationEvent event) { for (final ApplicationListener listener : getApplicationListeners(event)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { public void run() { listener.onApplicationEvent(event); } }); } else { listener.onApplicationEvent(event); } } }
多线程产经下变量executor
的值不为空,单线程则相反。
教程结束,感谢阅读。 欢迎转载,但请注明本文链接,谢谢。 2016.5.12 17:49
优质内容筛选与推荐>>