观察者模式可以理解为, 订阅某种行为后, 当执行该行为时, 会向订阅者发布事件, 接收该事件的订阅者,就会各自去做自己需要做的事, 以此完成系统的解耦.
如用户注册会员后, 可能需要发送短信通知, 发送优惠券等一些常见的操作.
如果把这些业务处理都写在一块就容易造成代码的耦合, 并且还会影响主流程的进行.
例如我注册会员后, 你因为发送优惠券的问题导致会员注册失败, 这不就扯淡嘛!
所以流程上来说, 应该是 我注册会员就只注册会员, 我跟需要配合的业务通知一下,这个人注册好了!你们爱怎么样就怎么样, 出问题自己解决自己的问题, 不要影响到我们尊贵的会员用户!
so, 看看spring怎么处理的.
//TODO 补充类图
全局事件接口
package com.linnine.spring.context;
/**
* 11 定义一个具有时间功能的抽象类
*/
public abstract class ApplicationEvent extends EventObject {
/**
* Constructs a prototypical Event.
*
* @param source the object on which the Event initially occurred
* @throws IllegalArgumentException if source is null
*/
public ApplicationEvent(Object source) {
super(source);
}
}
几个实现类,一般情况下把事件需要用到的参数丢到这个构造方法的参数即可
ApplicationContextEvent
package com.linnine.spring.context.event;
public class ApplicationContextEvent extends ApplicationEvent {
/**
* Constructs a prototypical Event.
*
* @param source the object on which the Event initially occurred
* @throws IllegalArgumentException if source is null
*/
public ApplicationContextEvent(Object source) {
super(source);
}
public final ApplicationContext getApplicationContext(){
return (ApplicationContext) getSource();
}
}
ContextClosedEvent
package com.linnine.spring.context.event;
/**
* 监听关闭
*/
public class ContextClosedEvent extends ApplicationEvent {
/**
* Constructs a prototypical Event.
*
* @param source the object on which the Event initially occurred
* @throws IllegalArgumentException if source is null
*/
public ContextClosedEvent(Object source) {
super(source);
}
}
ContextRefreshedEvent
package com.linnine.spring.context.event;
/**
* 监听刷新
*/
public class ContextRefreshedEvent extends ApplicationEvent {
/**
* Constructs a prototypical Event.
*
* @param source the object on which the Event initially occurred
* @throws IllegalArgumentException if source is null
*/
public ContextRefreshedEvent(Object source) {
super(source);
}
}
事件发布者ApplicationEventPublisher
专门用来推送事件的接口类
package com.linnine.spring.context;
/**
* 11 事件发布者
*/
public interface ApplicationEventPublisher {
void publishEvent(ApplicationEvent event);
}
事件监听者ApplicationListener
暂时还没有操作,后面可能有坑要填
package com.linnine.spring.context;
public class ApplicationListener<T> {
}
事件广播器 ApplicationEventMulticaster
用于添加和删除事件监听者
package com.linnine.spring.context.event;
/**
* 11 事件广播器
*/
public interface ApplicationEventMulticaster {
void addApplicationListener(ApplicationListener<?> listener);
void removeApplicationListener(ApplicationListener<?> listener);
void multicastEvent(ApplicationEvent event);
}
事件广播器简单实现 SimpleApplicationEventMulticaster
还没有具体实现,后面慢慢填坑
package com.linnine.spring.context.event;
/**
* 简单事件广播器
*/
@Data
@AllArgsConstructor
public class SimpleApplicationEventMulticaster implements ApplicationEventMulticaster{
private BeanFactory beanFactory;
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
}
@Override
public void removeApplicationListener(ApplicationListener<?> listener) {
}
@Override
public void multicastEvent(ApplicationEvent event) {
}
}
改造原来的流程
AbstractApplicationContext
package com.linnine.spring.context.support;
主要是在刷新容器和关闭时发布对应的事件
/**
* 应用上下文 抽象类实现
*/
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
private ApplicationEventMulticaster applicationEventMulticaster;
@Override
public void refresh() throws BeansException {
//11新增 初始化事件发布者
initApplicationEventMulticaster();
// 11新增 注册事件监听器
registerListeners();
// 11新增 发布容器刷新完成事件
finishRefresh();
//...旧的省略掉
}
private void initApplicationEventMulticaster(){
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
//11又要往这个类里加个方法
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, applicationEventMulticaster);
}
private void registerListeners(){
Collection<ApplicationListener> applicationListeners = getBeansOfType(ApplicationListener.class).values();
for (ApplicationListener listener : applicationListeners) {
applicationEventMulticaster.addApplicationListener(listener);
}
}
/**
* 发送刷新事件
*/
private void finishRefresh(){
publishEvent(new ContextRefreshedEvent(this));
}
/**
* 发布事件
* @param event
*/
private void publishEvent(ApplicationEvent event) {
applicationEventMulticaster.multicastEvent(event);
}
//...
/**
* 关闭
*/
@Override
public void close(){
//11 新增 发布 关闭容器 事件
publishEvent(new ContextClosedEvent(this));
getBeanFactory().destroySingletons();
}
}
加了个 beanFactory.registerSingleton方法, 还有掰正destroySingletons方法
一层一层往上走吧
ConfigurableListableBeanFactory
之前临时把destroySingletons丢在这里面了,现在干掉他!
package com.linnine.spring.beans.factory;
ConfigurableBeanFactory
应该在这里定义方法,并改了个继承
package com.linnine.spring.beans.factory.config;
SingletonBeanRegistry
在这里定义一个注册单例的方法
package com.linnine.spring.beans.factory.config;
DefaultSingletonBeanRegistry
在这里实现注册单例的方法,一开始这里面就是原来管理那些单例类
package com.linnine.spring.beans.factory.support;
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
@Override
public void registerSingleton(String name,Object singletonBean){
singletonObjects.put(name,singletonBean);
}
//... 其他
}
spring代码准备工作做好了, 开始整测试类
ListableBeanFactory
继承 BeanFactory,因为AbstractApplicationContext里有个getBeanFactory()方法返回的是ConfigurableListableBeanFactory, 这个类就是继承自ListableBeanFactory 所以让他爹来继承BeanFactory,这样他也就跟BeanFactory通了!
package com.linnine.spring.beans.factory;
public interface ListableBeanFactory extends BeanFactory{
<T> Map<String, T> getBeansOfType(@Nullable Class<T> var1) throws BeansException;
<T> Map<String, T> getBeansOfType(@Nullable Class<T> var1, boolean var2, boolean var3) throws BeansException;
}
AutowireCapableBeanFactory
这个类也要实现BeanFactory 主要是因为AbstractAutowireCapableBeanFactory继承过来的,同上,
在这里需要
CustomEvent
外部实现自定义事件
package com.linnine.spring.event;
@Getter
@Setter
public class CustomEvent extends ApplicationEvent {
private Long id;
private String message;
/**
* Constructs a prototypical Event.
*
* @param source the object on which the Event initially occurred
* @throws IllegalArgumentException if source is null
*/
public CustomEvent(Object source, Long id, String message) {
super(source);
this.id = id;
this.message = message;
}
}
CustomEventListener
外部事件对应的时间监听器
package com.linnine.spring.event;
public class CustomEventListener implements ApplicationListener<CustomEvent> {
@Override
public void onApplicationEvent(CustomEvent event) {
System.out.println("收到:" + event.getSource() + "消息;时间:" + new Date());
System.out.println("消息:" + event.getId() + ":" + event.getMessage());
}
}
ApplicationListener
反手完善这个类
package com.linnine.spring.context;
public interface ApplicationListener<T extends ApplicationEvent> {
void onApplicationEvent(T event);
}
两个监听类
CustomClosedEventListener
package com.linnine.spring.event;
public class CustomClosedEventListener implements ApplicationListener<ContextClosedEvent> {
@Override
public void onApplicationEvent(ContextClosedEvent event) {
System.out.println("收到:" + event.getSource() + "销毁消息;时间:" + new Date());
}
}
CustomRefreshedEventListener
package com.linnine.spring.event;
public class CustomRefreshedEventListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("收到:" + event.getSource() + "刷新消息;时间:" + new Date());
}
}
spring.xml
注册这三个bean
<bean class="com.linnine.spring.event.CustomEventListener" />
<bean class="com.linnine.spring.event.CustomRefreshedEventListener" />
<bean class="com.linnine.spring.event.CustomClosedEventListener" />
测试代码
@Test
public void test_event() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
applicationContext.publishEvent(new CustomEvent(applicationContext, 1019129009086763L, "成功了!"));
applicationContext.registerShutdownHook();
}
果然第一遍跑完屁事没有! 就是什么异常也没有, 但什么日志也都没有打印 坑爹啊!
就是我的事件监听器没有监听到,因为压根就没塞到spring的代码里!
应该是在SimpleApplicationEventMulticaster里面处理了!
搬源码搬的有点麻了, 歇会儿, 后面自己想办法简化一下, 就是差一个 判断 class类型 与泛型是否匹配.
ok啦! 通过java的反射机制 简单的判断了一下!
改了挺多代码的!
AbstractApplicationContext
前面在刷新的方法中加入了 事件相关的代码, 但是顺序不对 得放到后面
前面思考的是SimpleApplicationEventMulticaster 里面没有做实现, 然后看了一下源码 上面还封装了一蹭抽象类,对监听器进行管理.
发现spring的又一个小细节, 在抽象类中管理一些类, 具体的实现方式再让下级自己去处理.
一般也都是这种思想
接口 I 有三个抽象方法, X,Y,Z 要去实现它, 但是I的抽象方法中有两个方法 不管是X,Y,Z的实现方式都是一样的, 只有最后一个抽象方法处理不同.
这个时候就可以给X,Y,Z找个大爹A(Abstract).统一帮他们处理好前面两个方法, 再让他们去继承, 各自实现方法三就行了.
假设 方法一 中有些步骤是灵活的情况下, A还可以用模板模式, 在方法一中调用一些抽象方法, 再让他的儿子们自己做主,去实现这些抽象方法,也是可以的嘛!
这就是抽象类的妙了!
回到主题
原先SimpleApplicationEventMulticaster是直接实现ApplicationEventMulticaster 就需要实现他的三个方法, 现在交个父类来管理监听器集合, 顺便实现了里面的两个接口
AbstractApplicationEventMulticaster
package com.linnine.spring.context.event;
/**
* 在这个类里管理监听器
*/
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanFactoryAware {
private final Set<ApplicationListener<?>> applicationListeners =new HashSet<>();
private ConfigurableBeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory){
if (!(beanFactory instanceof ConfigurableBeanFactory)){
throw new IllegalStateException("Not running in a ConfigurableBeanFactory: " + beanFactory);
}
this.beanFactory = (ConfigurableBeanFactory) beanFactory;
}
public ConfigurableBeanFactory getBeanFactory(){
return this.beanFactory;
}
Set<ApplicationListener<?>> getApplicationListeners(){
return applicationListeners;
}
/**
* 根据事件 获取对应的事件监听器
* @param event
* @return
*/
Set<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event) {
Set<ApplicationListener<?>> resultSet = new HashSet<>();
for (ApplicationListener<?> applicationListener : applicationListeners) {
Class<? extends ApplicationListener> aClass = applicationListener.getClass();
Method method = null;
try {
//判断其方法的 参数类型 是否匹配
method = aClass.getMethod("onApplicationEvent", event.getClass());
} catch (NoSuchMethodException ignored) { }
//如果匹配就加入
if (method!=null){
resultSet.add(applicationListener);
}
}
return resultSet;
}
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
applicationListeners.add(listener);
}
@Override
public void removeApplicationListener(ApplicationListener<?> listener) {
applicationListeners.remove(listener);
}
}
ApplicationListener
这个补个继承,看源码上有 跟着加了一下
package com.linnine.spring.context;
public interface ApplicationListener<T extends ApplicationEvent> extends EventListener {
void onApplicationEvent(T event);
}
SimpleApplicationEventMulticaster
这个改造就简单了, 管理数据父类已经解决了, 我们直接获取过来调用一下就Ok了!
package com.linnine.spring.context.event;
/**
* 简单事件广播器
*/
@Data
@AllArgsConstructor
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster{
public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
setBeanFactory(beanFactory);
}
public void multicastEvent(ApplicationEvent event) {
for (ApplicationListener<?> listener : getApplicationListeners(event)) {
invokeListener(listener,event);
}
}
private void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
doInvokeListener(listener,event);
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
listener.onApplicationEvent(event);
}
}
最后的运行结果:完美!