本篇文章我们接着上一篇的文章,简单回顾一下
上一篇文章主要是看到Spring中在执行prepareBeanFactory方法的时候
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
会往容器中添加两个BeanPostProcessor接口的实现类的实例对象。接口中都有一个postProcessBeforeInitialization待实现的方法。而这个方法会在spring进行初始化bean对象的时候,会先通过以下方法获取得到接口的所有实现类名称。然后获取到想要对应的对象,将该对象放入List数组中,最后进行调用postProcessBeforeInitialization方法。String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
所以总结起来BeanPostProcessor接口的实现类,就像一节一节的管道,每当创建了一个bean。这个bean都会通过BeanPostProcessor接口实现类的postProcessBeforeInitialization方法进行处理一下。是一个串行的动作。
本篇文章我们来看一下Spring中的事件以及监听器。为什么要分析事件和监听器,其实源于beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); 其中ApplicationListenerDetecto部分源码如下
代码块一
class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor {private static final Log logger = LogFactory.getLog(ApplicationListenerDetector.class);private final transient AbstractApplicationContext applicationContext;private final transient Map<String, Boolean> singletonNames = new ConcurrentHashMap<>(256);public ApplicationListenerDetector(AbstractApplicationContext applicationContext) {this.applicationContext = applicationContext;}@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {this.singletonNames.put(beanName, beanDefinition.isSingleton());}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {if (bean instanceof ApplicationListener) {// potentially not detected as a listener by getBeanNamesForType retrievalBoolean flag = this.singletonNames.get(beanName);if (Boolean.TRUE.equals(flag)) {// singleton bean (top-level or inner): register on the flythis.applicationContext.addApplicationListener((ApplicationListener<?>) bean);}else if (Boolean.FALSE.equals(flag)) {if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {// inner bean with other scope - can't reliably process eventslogger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +"but is not reachable for event multicasting by its containing ApplicationContext " +"because it does not have singleton scope. Only top-level listener beans are allowed " +"to be of non-singleton scope.");}this.singletonNames.remove(beanName);}}return bean;}
可以看到postProcessMergedBeanDefinition方法中先判断是不是监听器的实例。如果是的话就将其添加到一个list中,以备后用。
重点来了,Spring中监听器是监听事件的。而这个地方。使用到一种设计模式,叫观察者模式。本着能从Spring源码中学到更多的东西。所以我们先去分析一下观察者模式。
由于作者才疏学浅,对设计模式一知半解,如果读者想深入了解设计模式,推荐阅读设计模式之禅。我这里就简单的说一下这个设计模式自己的一些理解。
- 被观察者
也就是被观察的目标,目标对象。比如我们关注了某个公众号,那么这个公众号就是被观察者,我们自己就是观察者
- 观察者
关注公众号的读者,就是观察者
现在我们关注的公众号发布了一篇最新的文章,我们是怎么知道这发布了这篇最新的文章呢。其实有多种方式,
第一种:我们可以自己主动去浏览公众号发布的文章,可以找到最新发布的那一篇文章。(观察者主动)
第二种:公众号发布了最新的文章,然后微信通知了我们说你关注的公众号发布了最新的文章哟,请阅读。(观察者被动)
这里我们只讲解第二种方式
其实java jdk中已经提供了,观察者和被观察者的接口,我们可以看一下。
首先是被观察者,源码如下,首先这个被观察者有一个集合obs,其实是一个观察者的集合,也就类比,关注了公众号的读者集合。被观察者接口可以添加,删除观察者。最重要的是notifyObservers方法,这个方法是通知所有的观察者,通知说我已经有动作变更。(Observer)arrLocal[i]).update(this, arg)。可以看到notifyObservers这个方法当中,调用了观察者对象的update方法,将变更的消息传递过去。
public class Observable {private boolean changed = false;private Vector<Observer> obs;/** Construct an Observable with zero Observers. */public Observable() {obs = new Vector<>();}/*** Adds an observer to the set of observers for this object, provided* that it is not the same as some observer already in the set.* The order in which notifications will be delivered to multiple* observers is not specified. See the class comment.** @param o an observer to be added.* @throws NullPointerException if the parameter o is null.*/public synchronized void addObserver(Observer o) {if (o == null)throw new NullPointerException();if (!obs.contains(o)) {obs.addElement(o);}}/*** Deletes an observer from the set of observers of this object.* Passing <CODE>null</CODE> to this method will have no effect.* @param o the observer to be deleted.*/public synchronized void deleteObserver(Observer o) {obs.removeElement(o);}/*** If this object has changed, as indicated by the* <code>hasChanged</code> method, then notify all of its observers* and then call the <code>clearChanged</code> method to* indicate that this object has no longer changed.* <p>* Each observer has its <code>update</code> method called with two* arguments: this observable object and <code>null</code>. In other* words, this method is equivalent to:* <blockquote><tt>* notifyObservers(null)</tt></blockquote>** @see java.util.Observable#clearChanged()* @see java.util.Observable#hasChanged()* @see java.util.Observer#update(java.util.Observable, java.lang.Object)*/public void notifyObservers() {notifyObservers(null);}/*** If this object has changed, as indicated by the* <code>hasChanged</code> method, then notify all of its observers* and then call the <code>clearChanged</code> method to indicate* that this object has no longer changed.* <p>* Each observer has its <code>update</code> method called with two* arguments: this observable object and the <code>arg</code> argument.** @param arg any object.* @see java.util.Observable#clearChanged()* @see java.util.Observable#hasChanged()* @see java.util.Observer#update(java.util.Observable, java.lang.Object)*/public void notifyObservers(Object arg) {/** a temporary array buffer, used as a snapshot of the state of* current Observers.*/Object[] arrLocal;synchronized (this) {/* We don't want the Observer doing callbacks into* arbitrary code while holding its own Monitor.* The code where we extract each Observable from* the Vector and store the state of the Observer* needs synchronization, but notifying observers* does not (should not). The worst result of any* potential race-condition here is that:* 1) a newly-added Observer will miss a* notification in progress* 2) a recently unregistered Observer will be* wrongly notified when it doesn't care*/if (!changed)return;arrLocal = obs.toArray();clearChanged();}for (int i = arrLocal.length-1; i>=0; i--)((Observer)arrLocal[i]).update(this, arg);}/*** Clears the observer list so that this object no longer has any observers.*/public synchronized void deleteObservers() {obs.removeAllElements();}
}
我们看一下观察者类的源码 ,它是一个接口,只有一个方法,update方法。我们的观察者只需要实现这个方法,那么他就是一个观察者类了。
package java.util;/*** A class can implement the <code>Observer</code> interface when it* wants to be informed of changes in observable objects.** @author Chris Warth* @see java.util.Observable* @since JDK1.0*/
public interface Observer {/*** This method is called whenever the observed object is changed. An* application calls an <tt>Observable</tt> object's* <code>notifyObservers</code> method to have all the object's* observers notified of the change.** @param o the observable object.* @param arg an argument passed to the <code>notifyObservers</code>* method.*/void update(Observable o, Object arg);
}
观察者模式我们就简单讲解到这里。接下来我们说一下Spring中是怎么应用这个观察者模式,实现了事件和监听器机制
首先我们可以看到在代码块有以下代码,往容器的ApplicationListener 这个set中添加了观察者,那这个时候我们可以把容器想成一个被观察者对象。
this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
接着我们看一下我们的观察者ApplicationListener提供给被观察者调用的方法是哪一个。也就是传递消息到观察者的方法。源码如下可以看到有一个onApplicationEvent方法,也就是和上面的update方法一样,就是传递消息的。
/*** Interface to be implemented by application event listeners.* Based on the standard {@code java.util.EventListener} interface* for the Observer design pattern.** <p>As of Spring 3.0, an ApplicationListener can generically declare the event type* that it is interested in. When registered with a Spring ApplicationContext, events* will be filtered accordingly, with the listener getting invoked for matching event* objects only.** @author Rod Johnson* @author Juergen Hoeller* @param <E> the specific ApplicationEvent subclass to listen to* @see org.springframework.context.event.ApplicationEventMulticaster*/
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {/*** Handle an application event.* @param event the event to respond to*/void onApplicationEvent(E event);}
那么我们的被观察者,是在上面时候调用的呢。其实我们找到refresh()方法下面的 registerListeners()方法查看该方法的源码,首先把我们的所有已经创建好观察者遍历出来放入getApplicationEventMulticaster().addApplicationListener(listener);
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 listenerBeanName : listenerBeanNames) {getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);}// Publish early application events now that we finally have a multicaster...Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;this.earlyApplicationEvents = null;if (earlyEventsToProcess != null) {for (ApplicationEvent earlyEvent : earlyEventsToProcess) {getApplicationEventMulticaster().multicastEvent(earlyEvent);}}}
然后最终执行的代码是,可以看到我们的被观察者调用了观察的对象的onApplication方法通知观察者。
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {try {listener.onApplicationEvent(event);}catch (ClassCastException ex) {String msg = ex.getMessage();if (msg == null || matchesClassCastMessage(msg, event.getClass().getName())) {// 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;}}}
本篇文章我们先讲解到这里。简单总结一下
因为我们的观察者也是一个bean,所以在初始化这个bean的时候,也是会遍历的执行容器中定义的BeanPostProcessor的接口实现类,实现的postProcessBeforeInitialization。或者我们自己实现的接口实现类实现的postProcessBeforeInitialization这个方法。观察者bean在执行到这个方法的是,会被添加到容器的观察者集合中。然后我们后面registerListeners()中容器会调用这些容器内已有观察者定义的onApplication方法。或者我们自定义观察者的方法。前提也是我们的实现了ApplicationListener 这个接口的观察者,需要注入到容器中。