Spring和JDK中观察者设计模式 Event事件监听

观察者设计模式特性

被观察者有观察者的引用
观察者不能主动发起操作, 需要等被观察者通知

在JDK中通过继承Observable类作为一个被观察者, 实现Observer接口作为一个观察者

模拟场景 天气变化, 任何狗做出不同反应

public class WeatherObservable extends Observable {

    private int temperature;

    public int getTemperature() {
        return temperature;
    }

    public void setTemperature(int temperature) {
        this.temperature = temperature;

        setChanged();
        notifyObservers();
    }
}

public class DogObserver implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof WeatherObservable) {
            WeatherObservable weatherObservable = (WeatherObservable) o;
            if (weatherObservable.getTemperature() < 0) {
                System.out.println("狗不出窝");
            } else if (weatherObservable.getTemperature() > 24) {
                System.out.println("狗吐口水");
            } else {
                System.out.println("狗正常活动");
            }
        }
    }
}


public class PersonObserver implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof WeatherObservable) {
            WeatherObservable weatherObservable = (WeatherObservable) o;
            if (weatherObservable.getTemperature() < 10) {
                System.out.println("人穿羽绒服");
            } else if (weatherObservable.getTemperature() > 24) {
                System.out.println("人穿短袖");
            } else {
                System.out.println("人正常活动");
            }
        }
    }
}


public class Test {

    public static void main(String[] args) {
        WeatherObservable weatherObservable = new WeatherObservable();
        weatherObservable.addObserver(new PersonObserver());
        weatherObservable.addObserver(new DogObserver());
        for (int i = -8; i < 30; i = i + 3) {
            System.out.println("当前温度: " + i + " 度");
            weatherObservable.setTemperature(i);
            System.out.println("--------------------------");
            try {
                Thread.sleep(800);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

运行结果

当前温度: -8 度
狗不出窝
人穿羽绒服
--------------------------
当前温度: -3 度
狗不出窝
人穿羽绒服
--------------------------
当前温度: 2 度
狗正常活动
人穿羽绒服
--------------------------
当前温度: 7 度
狗正常活动
人穿羽绒服
--------------------------
当前温度: 12 度
狗正常活动
人正常活动
--------------------------
当前温度: 17 度
狗正常活动
人正常活动
--------------------------
当前温度: 22 度
狗正常活动
人正常活动
--------------------------
当前温度: 27 度
狗吐口水
人穿短袖
--------------------------

Spring中Event使用

通过继承ApplicationEvent即可完成一个事件的封装, 然后实现ApplicationListener对事件作出反馈

public class FinishEvent extends ApplicationEvent {

    private String message;

    public FinishEvent(Object source, String message) {
        super(source);
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

}

@Component
public class FinishEventListener implements ApplicationListener<FinishEvent> {

    @Override
    public void onApplicationEvent(FinishEvent event) {
        System.out.println("监听者收到信息: " + event.getMessage());
    }

}


@Autowired
private ApplicationEventPublisher applicationEventPublisher;

@ResponseBody
@GetMapping("/finish")
public String finish() {
	applicationEventPublisher.publishEvent(new FinishEvent(applicationEventPublisher, "已完成"));
	return null;
}

调用finish接口, 直接打印 监听者收到信息: 已完成

Spring中也有一些已经定义好的Event, 可以添加监听器, 在条件满足时, 触发listener执行相关操作

@Component
public class ContextRefreshEventListener implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        System.out.println("容器刷新完成....");
        System.out.println(((ApplicationContext) event.getSource()).getBean(TestController.class));
    }
}

运行结果

容器刷新完成....
com.cloud.demo.controller.TestController@46fb0c33

源码分析

Spring容器初始化

org.springframework.context.support.AbstractApplicationContext#refresh

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		prepareRefresh();

		// Tell the subclass to refresh the internal bean factory.
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare the bean factory for use in this context.
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			postProcessBeanFactory(beanFactory);

			// Invoke factory processors registered as beans in the context.
			invokeBeanFactoryPostProcessors(beanFactory);

			// Register bean processors that intercept bean creation.
			registerBeanPostProcessors(beanFactory);

			// Initialize message source for this context.
			initMessageSource();

			// Initialize event multicaster for this context.
			// 初始化
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			onRefresh();

			// Check for listener beans and register them.
			registerListeners();

			// Instantiate all remaining (non-lazy-init) singletons.
			finishBeanFactoryInitialization(beanFactory);

			// Last step: publish corresponding event.
			finishRefresh();
		}
		catch (BeansException ex) {
			...
		}
		finally {
			...
		}
	}
}

ApplicationEventMulticaster监听器的持有和事件的发起都是靠通过此对象完成的

org.springframework.context.support.AbstractApplicationContext#initApplicationEventMulticaster

public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";

protected void initApplicationEventMulticaster() {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	
	// 判断容器内是有有对应的bean 名称 applicationEventMulticaster
	if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
		this.applicationEventMulticaster =
				beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
		if (logger.isTraceEnabled()) {
			logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
		}
	}
	else {
	
		// 没有就新建一个放入容器内
		this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
		beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
		if (logger.isTraceEnabled()) {
			logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
					"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
		}
	}
}

org.springframework.context.support.AbstractApplicationContext#registerListeners

protected void registerListeners() {
	// Register statically specified listeners first.
	// 首先从容器中获取直接存放各ApplicationListener 通过ac.addApplicationListener()方法存入
	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!
	// 通过类型从容器中获取ApplicationListener
	String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
	for (String listenerBeanName : listenerBeanNames) {
		getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
	}

	// Publish early application events now that we finally have a multicaster...
	// 对earlyApplicationEvents发起事件通知
	Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
	this.earlyApplicationEvents = null;
	if (earlyEventsToProcess != null) {
		for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
			getApplicationEventMulticaster().multicastEvent(earlyEvent);
		}
	}
}

Spring在初始化前后都有对监听器的事件通知, 最后都会调用multicastEvent方法

org.springframework.context.event.SimpleApplicationEventMulticaster

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
	// 获取通知类型
	ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
	// 根据类型查找监听器 并循环调用
	for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
		Executor executor = getTaskExecutor();
		// 如果有线程池执行器 则放入到执行器中
		if (executor != null) {
			executor.execute(() -> invokeListener(listener, event));
		}
		else {
			// 同步调用
			invokeListener(listener, event);
		}
	}
}

protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
	// 获取异常处理
	ErrorHandler errorHandler = getErrorHandler();
	if (errorHandler != null) {
		try {
			// 调用
			doInvokeListener(listener, event);
		}
		catch (Throwable err) {
			// 执行异常
			errorHandler.handleError(err);
		}
	}
	else {
		// 直接执行
		doInvokeListener(listener, event);
	}
}

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
	try {
		// 调用onApplicationEvent方法
		listener.onApplicationEvent(event);
	}
	catch (ClassCastException ex) {
		String msg = ex.getMessage();
		if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
			// Possibly a lambda-defined listener which we could not resolve the generic event type for
			// -> let's suppress the exception and just log a debug message.
			Log logger = LogFactory.getLog(getClass());
			if (logger.isDebugEnabled()) {
				logger.debug("Non-matching event type for listener: " + listener, ex);
			}
		}
		else {
			throw ex;
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值