`

Spring 使用的设计模式(二) Observer(观察者)

阅读更多

spring在容器中使用了观察者模式:

  spring事件:ApplicationEvent, 事件,该抽象类继承了EventObject,jdk建议所有的事件都应该继承自EventObject

  spring事件监听器:ApplicationLisener

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	/**
	 * Handle an application event.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}

   该接口继承了EventListener接口,jdk建议所有的事件监听器都应该继承EventListener

 

  spring事件发布:ApplicationEventPublisher , ApplicationContext继承了该接口,在ApplicationContext的抽象类AbstractApplicationContext中做了实现

public interface ApplicationEventPublisher {

	/**
	 * Notify all listeners registered with this application of an application
	 * event. Events may be framework events (such as RequestHandledEvent)
	 * or application-specific events.
	 * @param event the event to publish
	 * @see org.springframework.web.context.support.RequestHandledEvent
	 */
	void publishEvent(ApplicationEvent event);

}

  

  AbstractApplicationContext类中publishEvent方法实现:

 

	public void publishEvent(ApplicationEvent event) {
		Assert.notNull(event, "Event must not be null");
		if (logger.isTraceEnabled()) {
			logger.trace("Publishing event in " + getDisplayName() + ": " + event);
		}
                //事件广播委托给ApplicationEventMulticaster来进行
		getApplicationEventMulticaster().multicastEvent(event);
		if (this.parent != null) {
			this.parent.publishEvent(event);
		}
	}

   由上代码可知,AbstractApplicationContext类并没有具体的做事件广播,而是委托给ApplicationEventMulticaster来进行,ApplicationEventMulticaster的multicastEvent()方法实现如下:

	public void multicastEvent(final ApplicationEvent event) {
		for (final ApplicationListener listener : getApplicationListeners(event)) {
			Executor executor = getTaskExecutor();
			if (executor != null) {
				executor.execute(new Runnable() {
					public void run() {
						listener.onApplicationEvent(event);
					}
				});
			}
			else {
				listener.onApplicationEvent(event);
			}
		}
	}

 获得listener集合,遍历listener触发事件Executor接口有多个实现类,可以支持同步或异步广播事件

 

现在大家可能有个疑问,spring容器是怎么根据事件去找到事件对应的事件监听器呢?

在spring容器初始化的时候,

 

	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) {
				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}
		}
	}
 initApplicationEventMulticaster()方法代码为:

 

 

	protected void initApplicationEventMulticaster() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
                //先查找BeanFactory配置文件中是否有ApplicationEventMulticaster
		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
			this.applicationEventMulticaster =
					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
			}
		}
		else {//如果beanFactory中没有,则创建一个SimpleApplicationEventMulticaster
			this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
			beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
			if (logger.isDebugEnabled()) {
				logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
						APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
						"': using default [" + this.applicationEventMulticaster + "]");
			}
		}
	}
 spring先从beanFactory中获取ApplicationEventMulticaster,如果没有自定义,则创建一个SimpleApplicationEventMulticaster

 

 

ApplicationEventMulticaster包含以下属性:defaultRetriever即为注册表,注册监听事件的相关消息,retrieverCache用来做defaultRetriever的缓存

 

public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanFactoryAware {

	private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);

	private final Map<ListenerCacheKey, ListenerRetriever> retrieverCache =
			new ConcurrentHashMap<ListenerCacheKey, ListenerRetriever>(64);

	private BeanFactory beanFactory;
 ListenerRetriever的数据结构如下:applicationListeners用来存放监听事件, applicationListenerBeans为存放监听事件的类名称
	private class ListenerRetriever {

		public final Set<ApplicationListener> applicationListeners;

		public final Set<String> applicationListenerBeans;

		private final boolean preFiltered;
 

 

初始化注册表以后,则把事件注册到注册表中,registerListeners():

 

	protected void registerListeners() {
		// Register statically specified listeners first.
                //获取所有的listener, 把事件的bean放到ApplicationEventMulticaster中的
		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);
                //把事件的名称放到ApplicationListenerBean里去
		for (String lisName : listenerBeanNames) {
			getApplicationEventMulticaster().addApplicationListenerBean(lisName);
		}
	}
 spring根据反射机制,通过方法getBeansOfType()获取所有继承了ApplicationListener接口的监听器,然后把监听器全放到注册表里,所以我们可以在spring配置文件中配置自定义的监听器,在spring初始化的时候会把监听器自动注册到注册表中。

 在applicationContext发布事件的时候,

 

	public void publishEvent(ApplicationEvent event) {
		Assert.notNull(event, "Event must not be null");
		if (logger.isTraceEnabled()) {
			logger.trace("Publishing event in " + getDisplayName() + ": " + event);
		}
                //调用ApplicationEventMulticaster的multicastEvent()方法
		getApplicationEventMulticaster().multicastEvent(event);
		if (this.parent != null) {
			this.parent.publishEvent(event);
		}
	}
 ApplicationEventMulticaster的方法multicastEvent()为:

 

 

	public void multicastEvent(final ApplicationEvent event) {
                //获取对应的listener,触发事件
		for (final ApplicationListener listener : getApplicationListeners(event)) {
			Executor executor = getTaskExecutor();
			if (executor != null) {
				executor.execute(new Runnable() {
					public void run() {
						listener.onApplicationEvent(event);
					}
				});
			}
			else {
				listener.onApplicationEvent(event);
			}
		}
	}
 getApplicationListeners()方法的实现为:

 

 

	protected Collection<ApplicationListener> getApplicationListeners(ApplicationEvent event) {
                //获取事件类型
		Class<? extends ApplicationEvent> eventType = event.getClass();
                //获取事件源类型
		Class sourceType = event.getSource().getClass();
		ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
                //从缓存里查找ListenerRetriever                  
		ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
                //如果不为空,则返回对应的listener
		if (retriever != null) {
			return retriever.getApplicationListeners();
		}
		else {//如果缓存里不存在,则去获得
                        //先创建要返回对象
			retriever = new ListenerRetriever(true);
			LinkedList<ApplicationListener> allListeners = new LinkedList<ApplicationListener>();
			Set<ApplicationListener> listeners;
			Set<String> listenerBeans;
                        //获取注册表里所有的listener
			synchronized (this.defaultRetriever) {
				listeners = new LinkedHashSet<ApplicationListener>(this.defaultRetriever.applicationListeners);
				listenerBeans = new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans);
			}
                        //根据事件类型,事件源类型,获取所需要的监听事件
			for (ApplicationListener listener : listeners) {
				if (supportsEvent(listener, eventType, sourceType)) {
					retriever.applicationListeners.add(listener);
					allListeners.add(listener);
				}
			}
			if (!listenerBeans.isEmpty()) {
				BeanFactory beanFactory = getBeanFactory();
				for (String listenerBeanName : listenerBeans) {
					ApplicationListener listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);
					if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
						retriever.applicationListenerBeans.add(listenerBeanName);
						allListeners.add(listener);
					}
				}
			}
			OrderComparator.sort(allListeners);
			this.retrieverCache.put(cacheKey, retriever);
			return allListeners;
		}
	}
 配合上面的注解,即可理解,根据事件类型找到对应的监听器,那么如何根据事件类型找到对应的监听器呢?

 上面方法中的supportsEvent(listener, eventType, sourceType)方法实现了根据事件类型查找对应的监听器,代码具体实现为:

	protected boolean supportsEvent(
			ApplicationListener listener, Class<? extends ApplicationEvent> eventType, Class sourceType) {

		SmartApplicationListener smartListener = (listener instanceof SmartApplicationListener ?
				(SmartApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
		return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
	}

 如上可知:上面方法的返回结果跟方法smartListener.supportsEventType(eventType)和smartListener.supportsSourceType(sourceType)有关

smartListener.supportsEventType(eventType)方法实现为:

	public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
		Class<?> typeArg = GenericTypeResolver.resolveTypeArgument(this.delegate.getClass(), ApplicationListener.class);
		if (typeArg == null || typeArg.equals(ApplicationEvent.class)) {
			Class<?> targetClass = AopUtils.getTargetClass(this.delegate);
			if (targetClass != this.delegate.getClass()) {
				typeArg = GenericTypeResolver.resolveTypeArgument(targetClass, ApplicationListener.class);
			}
		}
		return (typeArg == null || typeArg.isAssignableFrom(eventType));
	}

 该方法主要的逻辑就是根据事件类型判断是否和监听器参数泛型的类型是否一致,可还记得监听器ApplicationListener的代码?

 

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	/**
	 * Handle an application event.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}

 在定义自己的监听器要明确指定参数泛型,表明该监听器支持的事件,如果不指明具体的泛型,则没有监听器监听事件

smartListener.supportsSourceType(sourceType)方法的实现为:

    public boolean supportsSourceType(Class<?> sourceType) {
        return true;
    }

 

默认返回true

 

以上是spring的事件体系,

 

我们可以使用spring的事件广播体系,自定义自己的事件:

自定义事件,继承ApplicationEvent:

public class DIYEvent extends ApplicationEvent {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1540593978873145453L;

	public DIYEvent(String content) {
		super(content);
	}

}

 

自定义listener,继承ApplicationListener

public class Test1Listener implements ApplicationListener<DIYEvent> {

	public void onApplicationEvent(DIYEvent event) {
		System.out.println(event.getSource());
	}

}

 在spring的配置文件中配置此listener

<!-- 自定义监听器 -->
   <bean id="test1Listener" class="test.obsever.listener.Test1Listener"></bean>

 

测试触发事件:

public class TestDemo {
	
	private ApplicationContext context;
	
	private MessageSource resources;
	
	@Before
	public void before() {
		context = new FileSystemXmlApplicationContext("WebRoot/WEB-INF/spring/spring.xml");
	}

	public static void main(String[] args) {
		
	}
	
	@Test
	public void testA() {
		context.publishEvent(new DIYEvent("test data!"));
	}
	
	@After
	public void after() {
		
	}
}

 获取ApplicationContext,发布事件

 

调试结果:test data!

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics