Spring源码深度解析-IOC的初始化过程之refresh()--prepareBeanFactory--BeanPostProcessors--ApplicationListener

本篇文章我们接着上一篇的文章,简单回顾一下


上一篇文章主要是看到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;
	}


	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		this.singletonNames.put(beanName, beanDefinition.isSingleton());
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		if (bean instanceof ApplicationListener) {
			// potentially not detected as a listener by getBeanNamesForType retrieval
			Boolean flag = this.singletonNames.get(beanName);
			if (Boolean.TRUE.equals(flag)) {
				// singleton bean (top-level or inner): register on the fly
				this.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 events
					logger.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 这个接口的观察者,需要注入到容器中。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值