在上文中講了Spring的事件監聽機制,流程是:定義事件、監聽器,發佈事件,控制檯輸出監聽到的事件內容。html
在上文的擴展中 使用 @EventListener 註解來自定義監聽器,監聽指定的事件,好比下面的案例:spring
@Component public class UserManagerListener { //ApplicationEvent能監聽到全部的事件,若是爲EmailEvent.class則只能監聽到關於郵件的事件 //EventListener有兩個參數(能夠不寫,直接在方法參數裏面寫上要監聽的事件便可): // classes:表示哪個事件類 // condition:當知足什麼條件是會調用該方法 @EventListener(classes = ApplicationEvent.class) public void listen(ApplicationEvent event){ System.out.println("用戶管理功能監聽到的事件。。。。"+event); } }
經過上面的案例發現代碼比實現 ApplicationListener 接口更簡潔,那這個註解爲何功能這麼強大呢,接下來咱們來分析它的源碼:bootstrap
/** * @author Stephane Nicoll * @author Sam Brannen * @since 4.2 * @see EventListenerMethodProcessor */ @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface EventListener { ....... }
經過源碼發現是經過使用 EventListenerMethodProcessor 處理器來解析該註解,將標註了 @EventListener 的方法進行解析, 獲取攔截方法,對攔截方法進行轉換,變成 ApplicationListener 然app
後放入到 IOC 容器中,在publishEvent 時,經過 getApplicationEventMulticaster().multicastEvent(aide
pplicationEvent, eventType)方法,獲取到 ApplicationListener 對象,經過反射調用方法。下面是 EventListenerMethodProcessor 處理器的類圖關係:post
能夠看到 EventListenerMethodProcessor 是實現了 BeanFactoryPostProcessor 和 SmartInitializingSingleton 這兩個接口。在前文 Spring的BeanFactoryPostProcessor探究 中講述了ui
BeanFactoryPostProcessor 的執行時機,在 refresh 容器的時候, 調用 invokeBeanFactoryPostProcethis
ssors() 方法時, 會執行 BeanFactoryPostProcessor#postProcessBeanFactory() 方法設置一個默認的監聽器工廠 :DefaultEventListenerFactory。lua
/** * Registers {@link EventListener} methods as individual {@link ApplicationListener} instances. * Implements {@link BeanFactoryPostProcessor} (as of 5.1) primarily for early retrieval, * avoiding AOP checks for this processor bean and its {@link EventListenerFactory} delegates. * * @author Stephane Nicoll * @author Juergen Hoeller * @since 4.2 * @see EventListenerFactory * @see DefaultEventListenerFactory */ public class EventListenerMethodProcessor implements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor { ...... @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { this.beanFactory = beanFactory; Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false); List<EventListenerFactory> factories = new ArrayList<>(beans.values()); AnnotationAwareOrderComparator.sort(factories); //DefaultEventListenerFactory this.eventListenerFactories = factories; } ....... }
而SmartInitializingSingleton 這個接口只有一個方法 afterSingletonsInstantiated(),這個方法在所有單實例建立完成以後執行,接下來對這個方法進行深刻探討,咱們對 EventListenerMethodProcessor裏面的實現方法 afterSingletonsInstantiated 打一個斷點 debug 運行下:url
從中咱們能夠看到,流程是: IOC容器建立對象 --> refresh() --> finishBeanFactoryInitialization(beanFactory)(初始化剩下的全部單實例bean) --> beanFactory.preInstantiateSingletons()(初始化剩下的全部單實例bean)--> smartSingleton.afterSingletonsInstantiated()
@Override public void preInstantiateSingletons() throws BeansException { if (logger.isTraceEnabled()) { logger.trace("Pre-instantiating singletons in " + this); } // Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap, it does otherwise work fine. //獲取全部的註冊bean名稱 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... //先建立全部的單實例bean for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { final FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName);//建立bean實例 } } } else { getBean(beanName);//建立bean實例 } } } // Trigger post-initialization callback for all applicable beans... //建立完成後進行遍歷,若是bean是SmartInitializingSingleton類型,執行afterSingletonsInstantiated方法 for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } }
從上面能夠看出其調用時機是,遍歷容器中註冊的 BeanDefinition, 調用全部 getBean() 方法建立實例以後, 纔會開始遍歷執行 afterSingletonsInstantiated() 方法。
接下來詳細解析下 EventListenerMethodProcessor 的 afterSingletonsInstantiated 方法,重點看 processBean 方法:
@Override public void afterSingletonsInstantiated() { ConfigurableListableBeanFactory beanFactory = this.beanFactory; Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set"); String[] beanNames = beanFactory.getBeanNamesForType(Object.class); for (String beanName : beanNames) { if (!ScopedProxyUtils.isScopedTarget(beanName)) { Class<?> type = null; try { type = AutoProxyUtils.determineTargetClass(beanFactory, beanName); } catch (Throwable ex) { // An unresolvable bean type, probably from a lazy bean - let's ignore it. if (logger.isDebugEnabled()) { logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex); } } if (type != null) { if (ScopedObject.class.isAssignableFrom(type)) { try { Class<?> targetClass = AutoProxyUtils.determineTargetClass( beanFactory, ScopedProxyUtils.getTargetBeanName(beanName)); if (targetClass != null) { type = targetClass; } } catch (Throwable ex) { // An invalid scoped proxy arrangement - let's ignore it. if (logger.isDebugEnabled()) { logger.debug("Could not resolve target bean for scoped proxy '" + beanName + "'", ex); } } } try { processBean(beanName, type); } catch (Throwable ex) { throw new BeanInitializationException("Failed to process @EventListener " + "annotation on bean with name '" + beanName + "'", ex); } } } } } private void processBean(final String beanName, final Class<?> targetType) { //不包含沒有註解的class,註解是EventListener的類型,是Spring容器的類型 if (!this.nonAnnotatedClasses.contains(targetType) && AnnotationUtils.isCandidateClass(targetType, EventListener.class) && !isSpringContainerClass(targetType)) { Map<Method, EventListener> annotatedMethods = null; try { //獲取標註了 @EventListener 註解的監聽方法 annotatedMethods = MethodIntrospector.selectMethods(targetType, (MethodIntrospector.MetadataLookup<EventListener>) method -> AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class)); } catch (Throwable ex) { // An unresolvable type in a method signature, probably from a lazy bean - let's ignore it. if (logger.isDebugEnabled()) { logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex); } } //監聽方法添加到沒有註解的集合 if (CollectionUtils.isEmpty(annotatedMethods)) { this.nonAnnotatedClasses.add(targetType); if (logger.isTraceEnabled()) { logger.trace("No @EventListener annotations found on bean class: " + targetType.getName()); } } else { // Non-empty set of methods ConfigurableApplicationContext context = this.applicationContext; Assert.state(context != null, "No ApplicationContext set"); List<EventListenerFactory> factories = this.eventListenerFactories; Assert.state(factories != null, "EventListenerFactory List not initialized"); for (Method method : annotatedMethods.keySet()) { for (EventListenerFactory factory : factories) { // 判斷是否支持該方法 在DefaultEventListenerFactory中寫死的返回true if (factory.supportsMethod(method)) { //選擇方法 beanName 這裏是AddDataEventListener的beanName 默認是addDataEventListener Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName)); //將監聽方法轉換爲ApplicationListener(ApplicationListenerMethodAdapter)對象 ApplicationListener<?> applicationListener = factory.createApplicationListener(beanName, targetType, methodToUse); // 若是是ApplicationListenerMethodAdapter對象 就把context和evaluator傳進去 if (applicationListener instanceof ApplicationListenerMethodAdapter) { ((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator); } //將建立的 ApplicationListener 加入到容器中 context.addApplicationListener(applicationListener); break; } } } if (logger.isDebugEnabled()) { logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" + beanName + "': " + annotatedMethods); } } } } //class是在org.springframework包下,註解類型不是組件 private static boolean isSpringContainerClass(Class<?> clazz) { return (clazz.getName().startsWith("org.springframework.") && !AnnotatedElementUtils.isAnnotated(ClassUtils.getUserClass(clazz), Component.class)); }
後面就是添加listener到Context中:
1)若是有applicationEventMulticaster,添加到ApplicationContext.applicationEventMulticas
ter中;
2)若是沒有applicationEventMulticaster,添加到ApplicationContext.applicationListeners中;
最後是觸發事件監聽了 AbstractApplicationContext.publishEvent --> SimpleApplicationEventMulticaster.multicastEvent --> invokeListener --> doInvokeListener --> ApplicationListenerMethodAdapter.onApplicationEvent
@Override public void onApplicationEvent(ApplicationEvent event) { processEvent(event); } ApplicationListenerMethodAdapter#processEvent public void processEvent(ApplicationEvent event) { Object[] args = resolveArguments(event); if (shouldHandle(event, args)) { // 反射執行真正的方法 Object result = doInvoke(args); if (result != null) { handleResult(result); } else { logger.trace("No result object given - no result to handle"); } } }
在ApplicationListenerMethodAdapter.doInvoke中會反射執行真正的方法:
protected Object doInvoke(Object... args) { //獲取目標對象 Object bean = getTargetBean(); ReflectionUtils.makeAccessible(this.method); try { //反射執行監聽方法 return this.method.invoke(bean, args); } catch (IllegalArgumentException ex) { assertTargetBean(this.method, bean, args); throw new IllegalStateException(getInvocationErrorMessage(bean, ex.getMessage(), args), ex); } catch (IllegalAccessException ex) { throw new IllegalStateException(getInvocationErrorMessage(bean, ex.getMessage(), args), ex); } catch (InvocationTargetException ex) { // Throw underlying exception Throwable targetException = ex.getTargetException(); if (targetException instanceof RuntimeException) { throw (RuntimeException) targetException; } else { String msg = getInvocationErrorMessage(bean, "Failed to invoke event listener method", args); throw new UndeclaredThrowableException(targetException, msg); } } }