EventListenerMethodProcessor 是 BeanFactory 的一个后置处理器, 用来对 @EventListener 提供支持.
主要是标注了 @EventListener 的方法进行解析, 然后转换为一个 ApplicationListener.
1. 在 refresh 容器的时候, 调用 invokeBeanFactoryPostProcessors() 方法时, 会执行 BeanFactoryPostProcessor#postProcessBeanFactory() 方法.
此方法中, 他只是设置了一个默认的监听器工厂 : DefaultEventListenerFactory
2. 他实现了 SmartInitializingSingleton 接口, 会在
org.springframework.context.support.AbstractApplicationContext#refresh
\|/
org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
\|/
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons 方法中调用其 afterSingletonsInstantiated() 方法.
其调用时机是, 遍历容器中注册的 BeanDefinition, 调用所有 getBean() 方法之后, 才会开始遍历执行 afterSingletonsInstantiated() 方法.
这里最终会调用 processBean() 方法.
此方法中, 就会去容器中查找标注了 @EventListener 注解的方法, 然后进行转换.
/** * 这个后置处理器, 主要是处理 @EventListener 注解的. * 1. 解析 @EventListener , 获取拦截方法 * 2. 对拦截方法进行转换, 变成 ApplicationListener * 3. 将转换的 ApplicationListener, 放到spring容器中 * 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 { protected final Log logger = LogFactory.getLog(getClass()); @Nullable private ConfigurableApplicationContext applicationContext; @Nullable private ConfigurableListableBeanFactory beanFactory; @Nullable private ListeventListenerFactories; private final EventExpressionEvaluator evaluator = new EventExpressionEvaluator(); private final Set > nonAnnotatedClasses = Collections.newSetFromMap(new ConcurrentHashMap<>(64)); @Override public void setApplicationContext(ApplicationContext applicationContext) { Assert.isTrue(applicationContext instanceof ConfigurableApplicationContext, "ApplicationContext does not implement ConfigurableApplicationContext"); this.applicationContext = (ConfigurableApplicationContext) applicationContext; } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { this.beanFactory = beanFactory; Map beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false); List factories = new ArrayList<>(beans.values()); AnnotationAwareOrderComparator.sort(factories); //DefaultEventListenerFactory this.eventListenerFactories = factories; } @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) { if (!this.nonAnnotatedClasses.contains(targetType) && !targetType.getName().startsWith("java") && !isSpringContainerClass(targetType)) { Map annotatedMethods = null; try { //获取标注了 @EventListener 注解的监听方法 annotatedMethods = MethodIntrospector.selectMethods(targetType, (MethodIntrospector.MetadataLookup ) 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 factories = this.eventListenerFactories; Assert.state(factories != null, "EventListenerFactory List not initialized"); for (Method method : annotatedMethods.keySet()) { for (EventListenerFactory factory : factories) { if (factory.supportsMethod(method)) { Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName)); //为监听方法创建 ApplicationListener ApplicationListener> applicationListener = factory.createApplicationListener(beanName, targetType, methodToUse); 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); } } } } /** * Determine whether the given class is an {@code org.springframework} * bean class that is not annotated as a user or test {@link Component}... * which indicates that there is no {@link EventListener} to be found there. * @since 5.1 */ private static boolean isSpringContainerClass(Class> clazz) { return (clazz.getName().startsWith("org.springframework.") && !AnnotatedElementUtils.isAnnotated(ClassUtils.getUserClass(clazz), Component.class)); } }