Spring源码 --- 监听器的原理 (下)

本文涉及的产品
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
简介: Spring源码 --- 监听器的原理 (下)

2.2 初始化bean工厂


我们现在经常使用的beanFactory有两种,一种是xml方式的, 另一种是注解方式的. 其实使用注解的更多一些. xml和注解方式的bean工厂在初始化的时候也是有区别的.

1187916-20201123095933233-305702361.png

从上图可以看出, 获取两种方式的bean工厂的区别

1. AbstractRefreshableApplicationContext: 基于xml配置文件的方式
2. GenericApplicationContext: 基于注解的方式.
基于注解实现的里面代码很简单, 只是刷新的beanFactory. 没有耦合加载beanDefinition的流程.
基于xml实现的代码, 里面耦合了加载beanDefinition

先来看看基于注解方式的, 基于注解方式只是指定了bean工厂的序列化ID

@Override
    protected final void     refreshBeanFactory() throws IllegalStateException {
        if (!this.refreshed.compareAndSet(false, true)) {
            throw new IllegalStateException(
                    "GenericApplicationContext does not support multiple refresh attempts:                 just call 'refresh' once");
        }
        // 指定bean工厂的序列化ID
        this.beanFactory.setSerializationId(getId());
    }

再来看看基于xml方式的, 基于xml方式的 除了指定了bean工厂的序列化id, 还耦合加载了beanDefinition

@Override
    protected final void refreshBeanFactory() throws BeansException {
        // 判断bean工厂是否初始化过, 如果已经初始化过那么销毁并关闭
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            // 重新创建一个bean工厂
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            // 设置序列化id
            beanFactory.setSerializationId(getId());
            // 设置个性化属性
            customizeBeanFactory(beanFactory);
            // 加载BeanDefinition
            loadBeanDefinitions(beanFactory);
            this.beanFactory = beanFactory;
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " +               getDisplayName(), ex);
        }
    }

看上面的步骤.

1. 先看看是否已经有过工厂了, 如果已经有了,那么销毁,关闭

2. 重新创建了一个空的新的工厂

3. 设置新工厂的序列化id

4. 设置个性化属性bean

5. 加载bean定义. 我们看到, 使用xml方式会加载bean定义

6. 返回bean工厂对象

这一步: 主要是初始化了bean工厂

 

2.3 对bean工厂进行填充属性prepareBeanFactory(beanFactory);

1187916-20201123101612319-2007486317.png

这一步是和监听器有关系的. 我们先来看看源码

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        // 设置bean工厂的类加载器为当前的application应用的加载器
        beanFactory.setBeanClassLoader(getClassLoader());
        // 为bean工厂设置标准的SPEL表达式解析器对象(StandardBeanExpressionResolver)
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        // 为bean工厂设置一个PropertiesEditor属性资源编辑器(用于后面给bean对象赋值)
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
        // Configure the bean factory with context callbacks.
        /**
         * 注册一个完整的ApplicationContextAwareProcessor后置处理器, 用来处理ApplicationContextAware
         * ApplicationContextAwareProcessor是一个bean的后置处理器. 怎么使用呢?
         *
         * 在bean初始化完成以后, 会调用一堆的bean后置处理器.
         * 在初始化的地方,其实只调用了三个bean后置处理器. 那么其他的后置处理器是什么时候调用的呢?
         * 就是在这里, 这里注册了 ApplicationContextAwareProcessor.
         * 在ApplicationContextAwareProcessor#invokeAwareInterfaces方法里调用了其他的aware
         * 那么invokeAwareInterfaces方法是在哪里调用呢?
         * 是在ApplicationContextAwareProcessor#postProcessBeforeInitialization调用的
         * postProcessBeforeInitialization是在bean初始化之前会调用的后置处理器
         *
         * 然后在通过addBeanPostProcessor()方法, 将bean的后置处理器添加到beanPostProcessors集合中
         */
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        /**
         * 忽略部分接口的函数方法, 在populateBean(创建bean的第二步:属性赋值)时
         * 因为下面接口都有set***方法, 这些方法不特殊处理将会自动注入到容器中.
         *
         * 忽略了这么多的Aware, 这是怎么回事呢? 因为Aware里面的方法都是以set开头的. 当在创建bean, 设置属性的时候,
         * 会给带有set+属性名的方法赋值. 而Aware的这些方法要忽略掉, 为什么忽略掉呢?
         *
         * 比如:EnvironmentAware 里面设置了一些环境变量, 这些环境变量是不需要进行属性装配的, 所以要把他们排除掉
         */
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
        // BeanFactory interface not registered as resolvable type in a plain factory.
        // MessageSource registered (and found for autowiring) as a bean.
        /**
         * 将beanFactory类型的实例注册解析
         *
         * 当注册了依赖解析以后, 例如当注册了对BeanFactory.class的解析依赖后,
         * 当bean属性注入的时候, 一旦检测到属性为beanFactory类型. 便会将BeanFactory的实例注册解析
         * 为什么呢?
         * 比如:
         * @Autowired
         * ApplicationContext applicationContext 为什么能够自动装配, 通过@Autowired引入呢? 就是在这里装配的.
         * 这个也是在注入属性popularBean的时候体现的
         *
         */
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);
        // Register early post-processor for detecting inner beans as ApplicationListeners.
        // 注册事件监听器探测器后置处理器接口, ApplicationListenerDetector 解析接口方式的监听器
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // Set a temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
        // Register default environment beans.
        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
        }
    }

1. 设置bean工厂的类加载器为: 当前的application应用的加载器


2. 为bean工厂设置标准的SPEL表达式解析器对象, 这个解析器对象是谁呢? 就是StandardBeanExpressionResolver


3. 为bean工厂设置一个PropertiesEditor属性资源编辑器, 用于后面给bean对象赋值


4. 给bean工厂注册了一个ApplicationContextAwareProcessor后置处理器. 这里说说这个后置处理器类. 这个类有什么作用呢?


在bean初始化完成以后, 会调用一堆的bean后置处理器

在doCreateBean()中找到第三步: 初始化bean

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                // 在初始化完成以后, 调用aware
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            // 在初始化的时候, 会调用很多的aware.
            invokeAwareMethods(beanName, bean);
        }
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // 在初始化之前调用bean的后置处理器
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }
        try {
            // 调用初始化方法
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            // 再初始化之后调用bean的后置处理器
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }

我们看到, 在初始化bean的时候, 调了很多Aware, invokeAwareMethods(beanName, bean);

/**
     * 这里主要有三类aware
     * @param beanName
     * @param bean
     */
    private void invokeAwareMethods(final String beanName, final Object bean) {
        /**
         * 在这里调用的aware只有三类, 我们去BeanFactory中看, 他有一大堆的aware要调用,
         * 那么其他的aware是在哪里调用的呢?
         */
        if (bean instanceof Aware) {
            // 实现了BeanNameAware的bean
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
            // 实现了BeanClassLoaderAware接口
            if (bean instanceof BeanClassLoaderAware) {
                ClassLoader bcl = getBeanClassLoader();
                if (bcl != null) {
                    ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
                }
            }
            // 实现了BeanFactoryAware
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
            }
        }
    }

如上代码, 我们看到, 其实知道用了3中类型的Aware. 分别是BeanNameAware, BeanClassLoaderAware 和 BeanFactoryAware.


那么其他的Aware呢? 我们看beanFactory接口的注释可以看到, 会调用很多Aware

1187916-20201123103016267-1652483337.png

在初始化的地方,其实只调用了三个bean后置处理器. 那么其他的后置处理器是什么时候调用的呢?


就是在这里, 这里注册了 ApplicationContextAwareProcessor.


在ApplicationContextAwareProcessor#invokeAwareInterfaces方法里调用了其他的aware


/**
     * 判断bean是否实现了各种Aware
     * @param bean
     */
    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof EnvironmentAware) {
            ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
        }
        if (bean instanceof EmbeddedValueResolverAware) {
            ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
        }
        if (bean instanceof ResourceLoaderAware) {
            ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
        }
        if (bean instanceof ApplicationEventPublisherAware) {
            ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
        }
        if (bean instanceof MessageSourceAware) {
            ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
        }
        if (bean instanceof ApplicationContextAware) {
            ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
        }
    }

而这个方法, 什么时候执行呢? 在初始化之前调用Bean的后置处理器执行的ApplicationContextAwareProcessor#postProcessBeforeInitialization

@Override
    @Nullable
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
            return bean;
        }
        AccessControlContext acc = null;
        if (System.getSecurityManager() != null) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }
        if (acc != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareInterfaces(bean);
                return null;
            }, acc);
        }
        else {
            invokeAwareInterfaces(bean);
        }
        return bean;
    }

然后在通过addBeanPostProcessor()方法, 将bean的后置处理器添加到beanPostProcessors集合中.


5. 忽略部分接口的函数方法. 这些接口主要是Aware.  

beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);


忽略了这么多的Aware, 这是怎么回事呢?为什么忽略掉呢? 因为Aware里面的方法都是以set开头的. 当在创建bean, 设置属性的时候,


会给带有set+属性名的方法赋值.在populateBean(创建bean的第二步:属性赋值)时 因为下面接口都有set***方法, 这些方法不特殊处理将会自动注入到容器中.

比如:EnvironmentAware 里面设置了一些环境变量, 这些环境变量是不需要进行属性装配的, 所以要把他们排除掉


6. 将beanFactory类型的实例注册解析


beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

当注册了依赖解析以后, 例如当注册了对BeanFactory.class的解析依赖后,

当bean属性注入的时候, 一旦检测到属性为beanFactory类型. 便会将BeanFactory的实例注册解析


为什么呢?


比如:

@Autowired
ApplicationContext applicationContext; .

为什么能够自动装配, 通过@Autowired引入呢? 就是在这里装配的


这个也是在注入属性popularBean的时候体现的


7. 注册了一个解析接口方式的监听器的 BeanPostProcessor.


beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

我们来看看ApplicationListenerDetector 类, 其下的 postProcessAfterInitialization方法, 是在createBean的第三步初始化之后执行的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
                /*
                 * 注册接口类型的监听器. 将其添加到applicationContext中
                 * 之所以要在这里在加一次, 是为了处理懒加载情况
                 */
                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;
    }


我们看这个方法, 方法一进来就判断,是否是实现了ApplicationListener接口. 也就是说, 上面我们输了注册监听器有两种方式, 一种是接口方式, 另一种是注解方式. 这里解析的是实现接口的方式.


在这里,我们要先建立一个印象, 因为后面还会说到他. 为什么呢? 因为接口方式的监听器在两个地方被调用, 一个是这里, 另一个是在refresh()后面的流程registerListener()的时候. 那么, 为什么要有两次调用监听器呢? 我们后面再说


2.4 postProcessBeanFactory(beanFactory); 这是一个扩展方法, 可以初始化剩余的Aware.


我们是AbstractApplicationContext没有实现, 但AbstractRefreshableWebApplicationContext类. 里面就定义了postProcessBeanFactory(beanFactory)

在里面注册了ServletContextAwareProcessor

beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));

beanFactory.ignoreDependencyInterface(ServletContextAware.class);

beanFactory.ignoreDependencyInterface(ServletConfigAware.class);

上面我们知道在 BeanFactory 里定义了需要调用的很多Aware. 但是有几个Aware还没有说到.


比如: ServletContextAware's {@code setServletContext} : ServletContextAware, 可以获得当前的ServletContextAware

添加了这个Aware以后, 我们就可以实现一个ServletContextAware的接口.

到这里, 我们就知道所有的aware都在哪里被调用了.


2.5 调用bean工厂的后置处理器, 解析配置类


这一步就略过了,之前重点说过这一步


2.6 registerBeanPostProcessors(beanFactory); 注册bean后置处理器, 这里主要是和AOP有关系


这里和监听器关系不太大, 也暂时略过


2.7  initMessageSource(); 初始化国际化资源处理器


2.8 initApplicationEventMulticaster();创建事件多播器


事件多播器管理所有的事件监听器. 并广播事件给对应的监听器


当我们调用ctx.publishEvent(new OrderEvent(order, "减库存"))的时候. 就会去通知所有监听了OrderEvent事件的事件监听器,

那么, 是由谁去负责通知呢?


就是由EventMulticaster(事件多播器)将事件播报出去的.

1187916-20201123110049478-110706610.png

首先, 判断有没有最定义的事件多播器. 如果有, 那么直接将其添加到容器中. 如果没有, 就新建一个SimpleApplicationEventMulticaster类型的事件多播器, 然后将其添加到beanFactory中.


那么, 事件多播器都做了什么事情呢? 具体来看一看SimpleApplicationEventMulticaster类.

1187916-20201123203736236-851573418.png

这是SimpleApplicationEventMulticaster的继承结构. 继承了AbstractApplicationEventMulticaster, 而AbstractApplicationEventMulticaster又实现了ApplicationEventMulticaster. 我们看看在ApplicationEventMulticaster中都对应了哪些接口

public interface ApplicationEventMulticaster {
    void addApplicationListener(ApplicationListener<?> listener);
    void addApplicationListenerBean(String listenerBeanName);
    void removeApplicationListener(ApplicationListener<?> listener);
    void removeApplicationListenerBean(String listenerBeanName);
    void removeAllListeners();  
    void multicastEvent(ApplicationEvent event);
    void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
}

看名字就知道了, 做了两件事, 一个是管理事件监听器, 另一个是广播事件.

我们看AbstractApplicationEventMulticaster如何实现这几个接口的

/**
     * AbstractApplicationEventMulticaster管理了所有的监听器.
     * 当我们注册一个监听器以后, 就会通过addApplicationListener方法添加到事件多播器中.
     * @param listener the listener to add
     */
    @Override
    public void addApplicationListener(ApplicationListener<?> listener) {
        synchronized (this.retrievalMutex) {
            // Explicitly remove target for a proxy, if registered already,
            // in order to avoid double invocations of the same listener.
            Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
            if (singletonTarget instanceof ApplicationListener) {
                this.defaultRetriever.applicationListeners.remove(singletonTarget);
            }
            this.defaultRetriever.applicationListeners.add(listener);
            this.retrieverCache.clear();
        }
    }


这是添加事件监听器.

在SimpleApplicationEventMulticaster里面, 定义了广播事件监听器

@Override
    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        //获取线程池
        Executor executor = getTaskExecutor();
        // 从多播器中获取所有的监听器
        for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            // 拿到了监听器
            if (executor != null) {
                // 异步调用广播事件
                executor.execute(() -> invokeListener(listener, event));
            }
            else {
                // 同步调用广播事件
                invokeListener(listener, event);
            }
        }
    }

这里有两种方式, 一种是同步的方式, 另一种是异步的方式. 根据设置的eventType来决定的. 其实异步的方式就是建立了一个新的线程


我么你来看一下调用事件监听器广播事件


invokeListener#doInvokeListener

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
        try {
            // 最终调用的是监听器的onApplicationEvent方法. 这个方法就是每一个监听器都会自定义的方法.
            listener.onApplicationEvent(event);
        }
        catch (ClassCastException ex) {
            String msg = ex.getMessage();
            if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
                // 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.isTraceEnabled()) {
                    logger.trace("Non-matching event type for listener: " + listener, ex);
                }
            }
            else {
                throw ex;
            }
        }
    }

最终调用的是监听器的onApplicationEvent方法. 这个方法就是每一个监听器都会自定义的方法.


listener.onApplicationEvent(event);


2.9 onRefresh();这是一个扩展方法. 这里没有具体实现.spring boot也是从这个方法进行启动


2.10 注册监听器registerListeners();

1187916-20201124041937782-2099893620.png

注册监听器这里一共做了三件事:


1. 将事件监听器注册到多播器上

2. 广播早期的事件

3. 清空早期事件.


到此步骤之前, 上面都是有早期事件的, 后面就没有早期事件了,因为这一步就都清空了. 后面也不会在进行自动广播了, 自动广播的就是早期事件.

protected void registerListeners() {
        // Register statically specified listeners first.
        /**
         * 第一步, 获取所有的事件监听器集合.
         * 通常, 这个时候, 事件监听器集合是空的, 除非手动调用allApplicationListeners()注册事件监听器
         */
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            // 将监听器注册到多播器上
            getApplicationEventMulticaster().addApplicationListener(listener);
        }
        /**
         * 第二步: 注册接口方式的监听器
         * 获取beanDefinition中 ApplicationListener 类型的监听器. 也就是说, 使用接口方式定义的监听器      * 就可以在这里被注册到多播器的
         * 这里是从BeanDefinition中拿的, 我们自定义了 OrderEventListenter 监听器, 那么会不会拿到呢?
         * 我们知道监听器的实现有两种方式, 一种是接口方式, 一种是注解方式.
         * 如果OrderEventListenter采用的是接口方式, 那么就可以拿到. 因为它实现了ApplicationListener.拿到了,       * 就把监听器注册到多播器上.
         * 如果是注解方式, 那就拿不到了
         *
         */
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
            // 把监听器注册到多播器上
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }
        /**
         * 第三步: 获取早期的事件, 然后广播早期事件. 
         * 这些早期事件是在第一步 prepareRefresh 注册的.
         * 
         */
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        // 在这里将早期事件清空, 清空完以后, 就没有早期事件了.
        this.earlyApplicationEvents = null;
        if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }

如上源码所示:


第一步. 获取所有的事件监听器集合, 通常这个时候, 事件监听器的集合都是空的, 除非我们手动调用allApplicationListeners()注册事件监听器

第二步: 注册接口方式的监听器. 注意,是接口方式的. 通常我们自定义的监听器.  有两种类型, 接口方式和注解方式. 如果使用的是接口方式. 那么就是在这里被注册的.如果是注解方式.不在这里注册.

getBeanNamesForType(ApplicationListener.class, true, false);
扫描获取ApplicationListener类型的监听器.

然后将其注册到多播器上. 我们知道多播器的两个主要功能, 管理监听器和广播事件.

getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);

第三步: 获取早期事件, 然后广播早期事件. 早期事件我们之前已经说过了, 是在第一步prepareRefresh()方法里注册的.


随后, 立即清空早期事件集合. 然后广播事件. 这样早期定义好的事件就都被广播出去了, 并且只能执行一次, 不会被再次执行.


/**
 * 第三步: 获取早期的事件, 然后广播早期事件. 
 * 这些早期事件是在第一步 prepareRefresh 注册的.
 * 
 */
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
// 在这里将早期事件清空, 清空完以后, 就没有早期事件了.
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
    for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
        getApplicationEventMulticaster().multicastEvent(earlyEvent);
    }
}


2.11 实例化剩余的单实例bean


这个方法就是循环遍历BeanDefinitionMap, 调用getBean, 去生产剩余的bean, 之前详细研究过这个步骤, 这里就不说了


2.12 完成refresh()操作, 发布刷新事件


protected void finishRefresh() {
    // Clear context-level resource caches (such as ASM metadata from scanning).
    // 清除上下文缓存
    clearResourceCaches();
    // Initialize lifecycle processor for this context.
    // 注册lifecycleProcessor声明周期处理器
    // 作用: 当ApplicationContext启动或停止时, 他会通过LifecycleProcessor来与所有声明的bean进行交互
    initLifecycleProcessor();
    // Propagate refresh to lifecycle processor first.
    // 为实现了SmartLifeCycle并且isAutoStartup, 自动启动的Lifecycle调用start()方法
    getLifecycleProcessor().onRefresh();
    // Publish the final event.
    // 发布容器refresh完毕的事件.
    // 发布的是什么事件呢? 是ContextRefreshedEvent事件.
    publishEvent(new ContextRefreshedEvent(this));
    // Participate in LiveBeansView MBean, if active.
    LiveBeansView.registerApplicationContext(this);
}

在这一步: 发布了容器Refreshed事件. 也就是容器启动完成的事件.

到这里, 我们来看看publicshEvent的具体实现


/**
     * 发布事件给所有的监听器
     * Publish the given event to all listeners.
     * @param event the event to publish (may be an {@link ApplicationEvent}
     * or a payload object to be turned into a {@link PayloadApplicationEvent})
     * @param eventType the resolved event type, if known
     * @since 4.2
     */
    protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
        Assert.notNull(event, "Event must not be null");
        // Decorate event as an ApplicationEvent if necessary
        ApplicationEvent applicationEvent;
        /**
         * 第一步: 获取事件
         */
        if (event instanceof ApplicationEvent) {
            // 处理接口类型的事件
            applicationEvent = (ApplicationEvent) event;
        }
        else {
            applicationEvent = new PayloadApplicationEvent<>(this, event);
            if (eventType == null) {
                eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
            }
        }
        /**
         * 第二步: 发布事件
         */
        // Multicast right now if possible - or lazily once the multicaster is initialized
        if (this.earlyApplicationEvents != null) {
            this.earlyApplicationEvents.add(applicationEvent);
        }
        else {
            /*
             * 调用事件多播器, 将这个事件发布出去
             * 事件多播器是什么时候注册的呢?         * 就是在refresh()初始化的时候, 调用initApplicationEventMulticaster(); 初始化的事件多播器
             */
            getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
        }
        /**
         * 第三步: 发布事件给父类容器
         */
        // Publish event via parent context as well...
        // 发布事件给父类容器
        if (this.parent != null) {
            if (this.parent instanceof AbstractApplicationContext) {
                ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
            }
            else {
                this.parent.publishEvent(event);
            }
        }
    }

这里做了如下几件事

1. 获取事件

2. 广播事件

3. 广播事件给父类监听器.

详细代码可以看注释

接下来看一下,具体的multicastEvent(...)

@Override
    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        //获取线程池
        Executor executor = getTaskExecutor();
        // 从多播器中获取所有的监听器
        for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            // 拿到了监听器
            if (executor != null) {
                // 异步调用广播事件
                executor.execute(() -> invokeListener(listener, event));
            }
            else {
                // 同步调用广播事件
                invokeListener(listener, event);
            }
        }
    }

这里首先会去获取线程池. 看看有没有重新定义线程池, 如果有这里executor就不是空的.

广播事件有两种形式, 一种是同步, 一种是异步. 如果executor线程池不空, 就以异步的形式广播, 否则就以同步的形式广播.


那么,我们如何自定义同步或者异步呢? 也是有两种方式


第一种方式: 自定义事件多波器, 并指定taskExcutor

@Bean(name = "applicationEventMulticaster")
    public ApplicationEventMulticaster simpleApplicationEventMulticaster() {
        SimpleApplicationEventMulticaster eventMulticaster
                = new SimpleApplicationEventMulticaster();
        //ThreadPoolTaskExecutor
      // 这里指定了 taskExecutor, 就会使用异步的方式去执行
        eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
        return eventMulticaster;
    }


第二种方式, 在事件监听器上使用注解@Async

@Component
@Async
public class OrderEventListenter implements ApplicationListener<OrderEvent> {
    /**
     * 当某一个事件发布的时候, 就会触发事件监听器
     * @param event the event to respond to
     */
    @Override
    public void onApplicationEvent(OrderEvent event) {
        if (event.getName().equals("减库存")) {
            System.out.println("事件监听器  监听到  减库存");
        }
    }
}

接下来看看如何广播事件的.

/**
     * Invoke the given listener with the given event.
     * @param listener the ApplicationListener to invoke
     * @param event the current event to propagate
     * @since 4.1
     */
    protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
        ErrorHandler errorHandler = getErrorHandler();
        if (errorHandler != null) {
            try {
                doInvokeListener(listener, event);
            }
            catch (Throwable err) {
                errorHandler.handleError(err);
            }
        }
        else {
            doInvokeListener(listener, event);
        }
    }
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
        try {
            // 最终调用的是监听器的onApplicationEvent方法. 这个方法就是每一个监听器都会自定义的方法.
            listener.onApplicationEvent(event);
        }
        catch (ClassCastException ex) {
            String msg = ex.getMessage();
            if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
                // 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.isTraceEnabled()) {
                    logger.trace("Non-matching event type for listener: " + listener, ex);
                }
            }
            else {
                throw ex;
            }
        }
    }

其实,具体执行的逻辑, 就是我们在监听器中定义的onApplicationEvent(event)方法中的逻辑实现.

 

三. 注册接口方式的监听器



在上面的源码分析中, 注册接口方式的监听器, 其实是由两个地方.


第一个: 在第十步registerListener()

protected void registerListeners() {
        .....
        /**
         * 第二步: 注册接口方式的监听器
         * 获取beanDefinition中 ApplicationListener 类型的监听器.       * 也就是说, 使用接口方式定义的监听器就可以在这里被注册到多播器的
         * 这里是从BeanDefinition中拿的, 我们自定义了 OrderEventListenter 监听器, 那么会不会拿到呢?
         * 我们知道监听器的实现有两种方式, 一种是接口方式, 一种是注解方式.
         * 如果OrderEventListenter采用的是接口方式, 那么就可以拿到. 因为它实现了ApplicationListener.      * 拿到了, 就把监听器注册到多播器上.
         * 如果是注解方式, 那就拿不到了
         *
         */
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
            // 把监听器注册到多播器上
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }
       .....
    }


另一个: 是在第三步进行属性填充的时候注册的


protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        ......
        /**
         * 注册事件监听器探测器后置处理器接口, ApplicationListenerDetector 解析接口方式的监听器
         */
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
        ......
    }

在准备属性的方法里, 有一个注册时间监听器探测器后置处理. 在这个监听器的探测器里面, 进行了注册.


来看看ApplicationListenerDetector

class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor {
    ....../**
     * 初始化后的bean后置处理器
     *
     * 这个方法是在 registerListener 之后执行的, 在registerListener()方法里注册过一次接口方式的监听器.
     * 在这里还会在注册一次.
     *
     * 问题: 为什么同一个监听器, 要在两个地方注册呢?
     * 第一次添加的是监听器的名字, 第二次添加的是bean实体. 那为什么要添加两次呢?
     * 这是为了处理带有@Lazy懒加载方式的bean. 懒加载的bean是不会在初始化容器的时候创建bean的.
     *
     * 比如, 我给监听器类加上一个@Lazy, 那么他就不会走bean的后置处理器, 因为bean的后置处理器, 是在bean创建过程中调用的.
     * 那什么时候会被调用呢? 在真正使用的时候. 比如调用 ctx.publishEvent(new OrderEvent(order, "减库存"));
     * 马上就要用到了, 所以, 这时候回去调bean的后置处理器. 执行代码看一下效果
     *
     *
     * @param bean the new bean instance
     * @param beanName the name of the bean
     * @return
     */
    @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
                /*
                 * 注册接口类型的监听器. 将其添加到applicationContext中
                 * 之所以要在这里在加一次, 是为了处理懒加载情况
                 */
                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;
    }
.......
}

我们看到在ApplicationListenerDetector中定义了方法postProcessAfterInitialization. 这个方法会在创建属性的第三步执行完以后调用. 第三步是初始化. 看名字也知道是初始化之后调用的后置处理器. 在这里, 注册了接口类型的监听器

this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);


那么, 为什么要有两次注册呢?


其实这里是为了解决懒加载的问题. 因为,如果一个类是懒加载的类, 那么他只有真正被调用的时候才回去加载. 所以, 也就是在类进行初始化以后才会被调用. 因此在初始化之后再次加载了接口类型的监听器.


四. 解析注解方式的监听器


整个流程走完, 我们都只看到接口方式的监听器注册的地方. 那么注解类型的监听器是什么时候被创建的呢?


首先, 注解是何时被解析的? 我们知道BeanDefinitionReader在解析创世纪的类的时候, 注册了很多创世纪的类.其中就有两个是用于负责处理@EventListener注解的

再来回顾一下这段代码

public static Set<BeanDefinitionHolder>  registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, @Nullable Object source) {
        // 获取到beanFactory
        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
        /**
         * 判断beanFactory中是否有AnnotationAwareOrderComparator和ContextAnnotationAutowireCandidateResolver
         * 没有则添加
         */
        if (beanFactory != null) {
            if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
            }
            if (!(beanFactory.getAutowireCandidateResolver() instanceof                   ContextAnnotationAutowireCandidateResolver)) {
                beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
            }
        }
        // BeanDefinitionHolder: 为BeanDefinition设置名字和别名
        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
        // 如果registry中没有ConfigurationClassPostProcessor配置类后置处理器, 就添加一个
        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            // 构建BeanDefinitionHolder, 并添加到beanDefs
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
        // 如果rigistry中, 没有AutowiredAnnotationBeanPostProcessor  Autowired注解bean的后置处理器, 则添加一个
        if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            // 构建BeanDefinitionHolder, 并添加到beanDefs
            beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
        // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
        // 检查对JSR-250的支持, 如果rigistry中没有 CommonAnnotationBeanPostProcessor 通用注解后置处理器, 则添加一个
        if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
            def.setSource(source);
            // 构建BeanDefinitionHolder, 并添加到beanDefs
            beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
        // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
        // 检查对jpa的支持, 如果不包含 internalPersistenceAnnotationProcessor, 持久化注解处理器, 就添加一个
        if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition();
            try {
                def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                        AnnotationConfigUtils.class.getClassLoader()));
            }
            catch (ClassNotFoundException ex) {
                throw new IllegalStateException(
                        "Cannot load optional framework class: " +                     PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
            }
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
        /**
         * 下面这两个注解是用来解析@EventListener的
         */
        // 检查对事件监听的支持, 如果不包含事件监听处理器 internalEventListenerProcessor, 就添加一个
        /*
         * EventListenerMethodProcessor : 既不是bean的后置处理器, 也不是bean工厂的后置处理器
         * 那么EventListenerMethodProcessor是在哪里被调用,并且解析注解方式的监听器呢?
         *
         * 下面看一下EventListenerMethodProcessor的继承结构图.
         * 1. 实现了SmartInitializingSingleton接口 :
         * 2. 实现了ApplicationContextAware接口 :  因为要往容器中注入bean, 所以,里面要使用容器的上下文,       * 将容器以Aware的方式set进来
         * 3. 实现了BeanFactoryPostProcessor接口 :
         *
         *
         */
        if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
        }
        // 如果不包含事件监听工厂处理器 internalEventListenerFactory , 就添加一个
        if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
        }
        return beanDefs;
    }


1187916-20201124054401387-1943000414.png

如上图就是注册的创世纪的处理器. 最后两个就是用来处理@EventListener注解的.

下面来看看EventListenerMethodProcessor事件监听器处理器,


首先, 看一下EventListenerMethodProcessor的继承结构图.

1187916-20201124054826012-992650495.png

EventListenerMethodProcessor实现了三个接口.

1.实现了SmartInitializingSingleton接口

2. 实现了ApplicationContextAware接口 : 因为要往容器中注入bean, 所以,里面要使用容器的上下文, 将容器以Aware的方式set进来

3. 实现了BeanFactoryPostProcessor接口

SmartInitializingSingleton接口在哪里被用到了呢?

在refresh()#finishBeanFactoryInitialization(beanFactory); 实例化剩余的单例bean的过程中

在DefaultListableBeanFactory#preInstantiateSingletons()方法. 有两次循环遍历beanNames

@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定义的name, 创建bean
          */
        for (String beanName : beanNames) {
            // 获取bean定义
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            // 生产bean定义的条件: 不是抽象的, 是单例的, 不是懒加载的. 符合这个标准的, 最后才会调用getBean()生产bean
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                // 这里判断是不是工厂bean, 这里和BeanFactory不是一个意思, 判断当前这个bean是否实现了beanFactory的接口
                if (isFactoryBean(beanName)) {
                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                    if (bean instanceof FactoryBean) {
                        // 将bean转换为FactoryBean 工厂bean
                        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) {
                            // 获取bean
                            getBean(beanName);
                        }
                    }
                }
                else {
                    // 第二步: 调用getBean
                    getBean(beanName);
                }
            }
        }
        // Trigger post-initialization callback for all applicable beans...
        /**
         * 第二步: 循环bean定义的name, 解析是否有实现了SmartInitializingSingleton接口的类
         * 到这里, bean都已经被创建完了
         */
        for (String beanName : beanNames) {
            // 从缓存中得到实例instance
            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();
                }
            }
        }
    }


第一次循环, 是创建bean, 并获取bean


第二次循环, 是在所有的bean都已经创建完以后, 如果singletonInstance是SmartInitializingSingleton的实例, 则调用afterSingletonsInstantiated()方法.

以下是EventListenerMethodProcessor#afterSingletonsInstantiated()方法实现

@Override
    public void afterSingletonsInstantiated() {
        // 从spring容器中获取EventListenerFactoryBean
        ConfigurableListableBeanFactory beanFactory = this.beanFactory;
        Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set");
        // 获取所有类型的bean
        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);
                    }
                }
            }
        }
    }


这里主要看processBean(beanName, type) 处理bean


private void processBean(final String beanName, final Class<?> targetType) {
        // 1. 是否包含注解@EventListener
        if (!this.nonAnnotatedClasses.contains(targetType) &&
                AnnotationUtils.isCandidateClass(targetType, EventListener.class) &&
                !isSpringContainerClass(targetType)) {
            Map<Method, EventListener> annotatedMethods = null;
            try {
                // 2. 查找@EventListener注解, 如果有则拿到标注@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");
                // 3. 获取bean工厂. 这个bean工厂是我们在创世纪的时候注册的EventListenerFactory
                List<EventListenerFactory> factories = this.eventListenerFactories;
                Assert.state(factories != null, "EventListenerFactory List not initialized");
                // 4. 循环遍历有注解的方法
                for (Method method : annotatedMethods.keySet()) {
                    for (EventListenerFactory factory : factories) {
                        if (factory.supportsMethod(method)) {
                            Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
                            //5. 创建事件监听器
                            ApplicationListener<?> applicationListener =
                                    factory.createApplicationListener(beanName, targetType, methodToUse);
                            if (applicationListener instanceof ApplicationListenerMethodAdapter) {
                                ((ApplicationListenerMethodAdapter) applicationListener).                        init(context, this.evaluator);
                            }
                            // 6. 将监听器注入到多播器中
                            context.addApplicationListener(applicationListener);
                            break;
                        }
                    }
                }
                if (logger.isDebugEnabled()) {
                    logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
                            beanName + "': " + annotatedMethods);
                }
            }
        }
    }

. 首先判断, 是否包含@EventListener注解

2. 查找@EventListener注解, 如果有则拿到标注@EventListener的方法

3. 获取bean工厂. 这个bean工厂是我们在创世纪的时候注册的EventListenerFactory

4. 循环遍历有注解的方法

5. 创建事件监听器

6. 将监听器注入到多播器中

 

以上就是注解版的监听器是如何注入到多播器中的.


五. 怎样在所有的bean都创建完以后做扩展代码?



第一种方式, 添加内置的监听器, 类加载完以后, 调用监听器

第二种方法. 就是在使用注解方式的时候,  实现SmartInitializingSingleton接口. 然后在bean实例化完成以后, 在调用

相关文章
|
6天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
20 2
|
22天前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
6天前
|
XML Java 开发者
Spring Boot开箱即用可插拔实现过程演练与原理剖析
【11月更文挑战第20天】Spring Boot是一个基于Spring框架的项目,其设计目的是简化Spring应用的初始搭建以及开发过程。Spring Boot通过提供约定优于配置的理念,减少了大量的XML配置和手动设置,使得开发者能够更专注于业务逻辑的实现。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,为开发者提供一个全面的理解。
17 0
|
12天前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
38 9
|
1月前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
111 5
|
1月前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
1月前
|
Java Spring 容器
Spring底层原理大致脉络
Spring底层原理大致脉络
|
1月前
|
XML Java 数据格式
手动开发-简单的Spring基于注解配置的程序--源码解析
手动开发-简单的Spring基于注解配置的程序--源码解析
46 0
|
1月前
|
XML Java 数据格式
手动开发-简单的Spring基于XML配置的程序--源码解析
手动开发-简单的Spring基于XML配置的程序--源码解析
80 0
|
1月前
|
XML 前端开发 Java
拼多多1面:聊聊Spring MVC的工作原理!
本文详细剖析了Spring MVC的工作原理,涵盖其架构、工作流程及核心组件。Spring MVC采用MVC设计模式,通过DispatcherServlet、HandlerMapping、Controller和ViewResolver等组件高效处理Web请求。文章还探讨了DispatcherServlet的初始化和请求处理流程,以及HandlerMapping和Controller的角色。通过理解这些核心概念,开发者能更好地构建可维护、可扩展的Web应用。适合面试准备和技术深挖
42 0