您的位置:首页 > 编程语言 > Java开发

观察者模式在Spring中的应用

2019-07-16 23:16 676 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/CoffeeAndMilk123/article/details/96200357

观察者模式在Spring中的主要体现在事件监听,事件机制的实现需要三个部分,事件源,事件,事件监听器;
1 ApplicationEvent抽象类作为事件的父类,通过source获取事件源。

public abstract class ApplicationEvent extends EventObject {
private static final long serialVersionUID = 7099057708183571937L;
private final long timestamp = System.currentTimeMillis();

public ApplicationEvent(Object source) {
super(source);
}

public final long getTimestamp() {
return this.timestamp;
}
}

2 ApplicationListener接口作为事件监听器,继承自EventListener

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}

3 ApplicationContext接口作为事件源,在这里可以将监听器注册进应用上下文中,也可以触发指定的事件。在ApplicationContext的父类ApplicationEventPublisher中有这样一个方法publishEvent,用以发布事件,具体的实现类在AbstractApplicationContext中。

default void publishEvent(ApplicationEvent event) {
this.publishEvent((Object)event);
}

void publishEvent(Object var1);

同样在AbstractApplicationContext中有方法registerListeners,可以注册监听器。

protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String lisName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(lisName);
}
}

下面模拟Spring的监听器原理自己实现一个登陆登出事件的监听机制。
1 事件类(ApplicationEvent)

@Data
public class Event implements Serializable {
//事件源,谁触发的
private Object source;
//触发类型的标记
private String trigger;
//通知的目标对象
private Object  target;
//通知的目标的方法
private Method callback;

//触发时间
private long time;

public Event() {
}

public Event(Object target, Method callback) {
this.target = target;
this.callback = callback;
}
}

2 事件监听抽象类,或者接口(ApplicationListener)

/**
* 事件监听器
*/
@Slf4j
public abstract class EventListener {
/**
* 存放事件
*/
private List<Event> eventList = new ArrayList<>();

/**
* 添加事件监听
*/
public void addEvent(Object target, Method method) {
Event event = new Event(target, method);
eventList.add(event);
}

/**
* 删除事件监听
*/
public void removeEvent(Event e) {
eventList.remove(e);
}

/**
* 通过事件触发
*/
public void trigger(Event event) {
event.setSource(this);
event.setTime(System.currentTimeMillis());
try {
//调用指定的方法
event.getCallback().invoke(event.getTarget(), event);
} catch (Exception e) {
log.info(e.getMessage());
}
}

/**
* 通过事件 类型出发,存储事件的集合可以使用Map,自定义类型属性
*/
}

3 具体事件,继承自事件监听抽象类(ApplicationContext)

/**
* 实例对象,具体的被观察者,即被监听的事件实现类
*/
public class ConcreteSubject extends EventListener {

/**
* 模拟登陆推出,异常事件监听
*/
public void login(Event loginEvent) {
System.out.println("登陆事件");
super.trigger(loginEvent);
}

public void logout(Event logoutEvent) {
System.out.println("登出事件");
super.trigger(logoutEvent);
}

public void exception(Event exceptionEvent) {
System.out.println("异常事件");
super.trigger(exceptionEvent);
}

}

4 对于监听到指定事件给出相应的反馈类

/**
* 观察者方法,模拟观察者观察到指定事件后相应的动作
*/
public class LogEventCallback {

public void login(Event event) {
System.out.println("=======用户登陆======" + event);
}

public void logout(Event event) {
System.out.println("=======用户登出======" + event);
}

public void exception(Event event) {
System.out.println("=======异常======" + event);
}
}

5 测试类,测试登陆事件的监听机制

public class LogEventTest {

public static void main(String[] args) throws NoSuchMethodException {
LogEventCallback target = new LogEventCallback();
//通过反射获取指定的方法
Method login = target.getClass().getDeclaredMethod("login", Event.class);
Method logout = target.getClass().getDeclaredMethod("logout", Event.class);
Method exception = target.getClass().getDeclaredMethod("exception", Event.class);
ConcreteSubject object = new ConcreteSubject();
//将监听事件放进监听类中,与Spring中的ApplicationContext功能相同
object.addEvent(target, logout);
object.addEvent(target, login);
object.addEvent(target, exception);

object.trigger(new Event(target, login));

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