您的位置:首页 > 移动开发

Spring Application Event Example

2016-05-12 16:52 176 查看

Spring Application Event

项目结构



工程下载

https://github.com/xiaoheike/SpringApplicationEventExample.git

SportEvent

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
中可以看到作用。

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
,可以用于获得构造函数传入的参数。

SoccerEvent

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
功能类似。

SportEventListener

SportEventListener1

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());
}
}
}

SportEventListener2

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。

SportEventPublisher

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
对象。这个类实现了主题的通知功能。

appicationContext.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>
</beans>

这两个bean是必须的,id可以任意,spring针对
SportEventPublisher
肯定是有经过特殊处理的,要不然该类中的
ApplicationEventPublisher
无法注入对应类。

这样的配置默认是采用单线程,为了提高效率可以使用多线程。修改
application.xml
文件如下即可。

applicationContext.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>

id
applicationEventMulticaster
不能够改变,猜测是spring需要根据这个id注入对象。

SimpleApplicationEventMulticaster

多线程或者单线程可以通过该类中的方法

@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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: