Spring4.0.4java
Spring 事件機制採用的是觀察者模型(又叫訂閱發佈模型)spring
有如下角色緩存
這裏,觀察者就是監聽者,被觀察者就是事件對象。app
事件發佈流程以下異步
下面以ClassPathXmlApplicationContext初始化完後,發佈,容器完成事件,爲例說明ide
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("xxx.xml");
執行以上模板代碼,啓動Spring容器時,會調用post
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); setConfigLocations(configLocations); if (refresh) { refresh();//在父類AbstractApplicationContext中實現 } }
AbstractApplicationContext類方法this
@Override 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. //spring完成了容器啓動。就發了一個事件通知監聽者 finishRefresh(); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } }
以上即便Spring啓動流程,也是Spring模板方法模式的體現線程
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Initialize other special beans in specific context subclasses.
onRefresh();//都是在子類實現的,,題外話。接着,看finishRefresh()debug
protected void finishRefresh() { // Initialize lifecycle processor for this context. initLifecycleProcessor(); // Propagate refresh to lifecycle processor first. getLifecycleProcessor().onRefresh(); // Publish the final event.//發送一個完成事件ContextRefreshedEvent //ContextRefreshedEvent 繼承自 ApplicationContextEvent //ApplicationContextEvent 繼承自 ApplicationEvent //因爲AbstractApplicationContext實現了ApplicationEventPublisher接口,因此它自己就是發佈者 publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active. LiveBeansView.registerApplicationContext(this); }
再看publishEvent實現
@Override public void publishEvent(ApplicationEvent event) { Assert.notNull(event, "Event must not be null"); if (logger.isTraceEnabled()) { logger.trace("Publishing event in " + getDisplayName() + ": " + event); } getApplicationEventMulticaster().multicastEvent(event);//得到事件廣播器,廣播事件。 if (this.parent != null) { this.parent.publishEvent(event);//調用父類發佈方法向上傳播 } } /** * Return the internal ApplicationEventMulticaster used by the context. * @return the internal ApplicationEventMulticaster (never {@code null}) * @throws IllegalStateException if the context has not been initialized yet */ ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException { if (this.applicationEventMulticaster == null) { throw new IllegalStateException("ApplicationEventMulticaster not initialized - " + "call 'refresh' before multicasting events via the context: " + this); } return this.applicationEventMulticaster;//廣播器了已提早初始化好,前面refresh()方法裏調用initApplicationEventMulticaster()實現。 } //具體 /** * Initialize the ApplicationEventMulticaster. * Uses SimpleApplicationEventMulticaster if none defined in the context. * @see org.springframework.context.event.SimpleApplicationEventMulticaster */ protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {//能夠自定義廣播器,名字要取applicationEventMulticaster this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);//記得實現ApplicationEventMulticaster if (logger.isDebugEnabled()) { logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);//沒有就默認這個,Spring 自實現的,是個內部類,下面會看到它的multicastEvent(final ApplicationEvent event)方法 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 + "]"); } } }
//看看multicastEvent方法 public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster { //..... @Override @SuppressWarnings({ "unchecked", "rawtypes" }) public void multicastEvent(final ApplicationEvent event) { //getApplicationListeners(event),獲取listeners 調用listener.onApplicationEvent(event);通知 //getApplicationListeners方法在AbstractApplicationEventMulticaster類實現 for (final ApplicationListener listener : getApplicationListeners(event)) { Executor executor = getTaskExecutor(); if (executor != null) {//有線程池,還能異步執行。 executor.execute(new Runnable() { @Override public void run() { listener.onApplicationEvent(event); } }); } else { listener.onApplicationEvent(event); } } } }
//AbstractApplicationEventMulticaster類中的實現
* Return a Collection of ApplicationListeners matching the given * event type. Non-matching listeners get excluded early. * @param event the event to be propagated. Allows for excluding * non-matching listeners early, based on cached matching information. * @return a Collection of ApplicationListeners * @see org.springframework.context.ApplicationListener */ protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event) { Class<? extends ApplicationEvent> eventType = event.getClass(); Object source = event.getSource(); Class<?> sourceType = (source != null ? source.getClass() : null); ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType); ListenerRetriever retriever = this.retrieverCache.get(cacheKey);//這裏用到了cache //全部的listener對象,都放在retriever裏的, if (retriever != null) {//有緩存,就直接返回。 return retriever.getApplicationListeners(); } else { retriever = new ListenerRetriever(true); LinkedList<ApplicationListener<?>> allListeners = new LinkedList<ApplicationListener<?>>(); Set<ApplicationListener<?>> listeners; Set<String> listenerBeans; synchronized (this.defaultRetriever) { //開始疑惑this.defaultRetriever.applicationListeners從哪來,其實這個是 //AbstractApplicationContext經過addApplicationListener方法手動加進來的,這是個public方法,爲配置監聽器提供了更大的靈活性 listeners = new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners); listenerBeans = new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans); } for (ApplicationListener<?> listener : listeners) { //這裏要注意下,有個驗證監聽者和事件類型匹配操做 //具體驗證法就是 監聽器的接收事件類型是否是與當前類型匹配,用的是Class.isAssignableFrom這個方法。 if (supportsEvent(listener, eventType, sourceType)) { retriever.applicationListeners.add(listener); allListeners.add(listener); } } if (!listenerBeans.isEmpty()) { BeanFactory beanFactory = getBeanFactory(); for (String listenerBeanName : listenerBeans) { try { Class<?> listenerType = beanFactory.getType(listenerBeanName); //驗證 if (listenerType == null || supportsEvent(listenerType, event)) { ApplicationListener<?> listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class); //驗證 if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) { retriever.applicationListenerBeans.add(listenerBeanName); allListeners.add(listener); } } } catch (NoSuchBeanDefinitionException ex) { // Singleton listener instance (without backing bean definition) disappeared - // probably in the middle of the destruction phase } } } OrderComparator.sort(allListeners); if (this.beanClassLoader == null || (ClassUtils.isCacheSafe(eventType, this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) { this.retrieverCache.put(cacheKey, retriever); } return allListeners; } }