Spring:ApplicationListener用法及原理

ApplicationListener

监听容器中发布的事件,时间驱动模型开发。

//监听ApplicationEvent事件
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
	//容器中发布此事件后,此方法会触发
	void onApplicationEvent(E event);

}

代码:

@Component
public class MyApplicationListener implements ApplicationListener {

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("收到事件:"+ event);
    }
}

@ComponentScan
@Configuration
public class ExtConfig {
}

测试方法:

public class MainTest {
    public static void main(String[] args) {

        ApplicationContext applicationContext  = new AnnotationConfigApplicationContext(ExtConfig.class);
        ((AnnotationConfigApplicationContext) applicationContext).close();
    }
}

image-20210315212133605

收到两个事件:容器刷新和容器关闭事件。

步骤:1.写一个监听器来监听某个事件

2.把监听器加入到容器

3.容器只要发布相关事件,我们就能监听到该事件

用法有点像mq,不过是spring容器内的监听。

ApplicationContext applicationContext  = new AnnotationConfigApplicationContext(ExtConfig.class);

applicationContext.publishEvent(new ApplicationEvent("hello") {
    @Override
    public Object getSource() {
        return super.getSource();
    }
});

((AnnotationConfigApplicationContext) applicationContext).close();

image-20210315212729768

实现原理

ContextRefreshedEvent事件

创建容器时,会调用容器的refresh方法:

@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.
            finishRefresh();
        }

        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();

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

            // Propagate exception to caller.
            throw ex;
        }

        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}

最后一步:finishRefresh

	protected void finishRefresh() {
		// Initialize lifecycle processor for this context.
		initLifecycleProcessor();

		// Propagate refresh to lifecycle processor first.
		getLifecycleProcessor().onRefresh();

		// Publish the final event.
		publishEvent(new ContextRefreshedEvent(this));

		// Participate in LiveBeansView MBean, if active.
		LiveBeansView.registerApplicationContext(this);
	}

publishEvent方法的最终实现:

	protected void publishEvent(Object event, ResolvableType eventType) {
		Assert.notNull(event, "Event must not be null");
		if (logger.isTraceEnabled()) {
			logger.trace("Publishing event in " + getDisplayName() + ": " + event);
		}

		// Decorate event as an ApplicationEvent if necessary
		ApplicationEvent applicationEvent;
		if (event instanceof ApplicationEvent) {
			applicationEvent = (ApplicationEvent) event;
		}
		else {
			applicationEvent = new PayloadApplicationEvent<Object>(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 {
            //获取到事件的派发器,调用multicastEvent方法派发事件
			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);
			}
		}
	}

派发方法源码:

@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    //获取所有事件监听器
    for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        Executor executor = getTaskExecutor();
        if (executor != null) {
            //异步处理
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    invokeListener(listener, event);
                }
            });
        }
        else {
            //直接调用invokeListener
            invokeListener(listener, event);
        }
    }
}

invokeListener方法:调用doInvokeListener方法

image-20210315213705786

image-20210315213818939

手动发布事件

还是调用publishEvent方法

image-20210315214116567

容器关闭

调用doClose方法:

image-20210315214227817

image-20210315214259652

事件派发器的创建

容器启动时,调用refresh方法,其中有一步就初始化好了一些事件派发器

image-20210315214510810

initApplicationEventMulticaster()方法:

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    //先去容器中查找是否存在id=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 {
        //如果没有,就直接创建一个简单事件派发器
        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 + "]");
        }
    }
}

ApplicationListener

refresh方法会有一步注册监听器

image-20210315215145510

registerListeners方法:

image-20210315215457069

@EventListener用法和原理

通过标注在方法上的@EventListener注解,一旦监听到指定事件后,就会调用该方法。

@Component
public class MyApplicationListener implements ApplicationListener {

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("收到事件:"+ event);
    }

    @EventListener(ApplicationEvent.class)
    public void listener(ApplicationEvent event){
        System.out.println("listener:"+event);
    }
}

image-20210315220219223

EventListener原理:EventListenerMethodProcessor处理器

public class EventListenerMethodProcessor implements SmartInitializingSingleton, ApplicationContextAware

该类实现了SmartInitializingSingleton接口,afterSingletonsInstantiated方法会在所有单实例bean创建完成后调用

public interface SmartInitializingSingleton {

	/**
	 * Invoked right at the end of the singleton pre-instantiation phase,
	 * with a guarantee that all regular singleton beans have been created
	 * already. {@link ListableBeanFactory#getBeansOfType} calls within
	 * this method won't trigger accidental side effects during bootstrap.
	 * <p><b>NOTE:</b> This callback won't be triggered for singleton beans
	 * lazily initialized on demand after {@link BeanFactory} bootstrap,
	 * and not for any other bean scope either. Carefully use it for beans
	 * with the intended bootstrap semantics only.
	 */
	void afterSingletonsInstantiated();

}

具体实现:容器创建调用refresh时,调用了finishBeanFactoryInitialization方法

image-20210315220613173

调用了beanFactory.preInstantiateSingletons()方法

image-20210315220655428

该方法前面在创建所有的单实例bean,该方法的最后:

image-20210315221116124

因为EventListenerMethodProcessor实现了SmartInitializingSingleton接口,所以被调用了afterSingletonsInstantiated方法,该方法最主要调用了processBean方法:

image-20210315222149336

processBean方法实现如下:

protected void processBean(final List<EventListenerFactory> factories, final String beanName, final Class<?> targetType) {
    if (!this.nonAnnotatedClasses.contains(targetType)) {
        Map<Method, EventListener> annotatedMethods = null;
        try {
            //获取方法上标注了EventListener注解的方法
            annotatedMethods = MethodIntrospector.selectMethods(targetType,
                                                                new MethodIntrospector.MetadataLookup<EventListener>() {
                                                                    @Override
                                                                    public EventListener inspect(Method method) {
                                                                        return 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
            for (Method method : annotatedMethods.keySet()) {
                for (EventListenerFactory factory : factories) {
                    if (factory.supportsMethod(method)) {
                        Method methodToUse = AopUtils.selectInvocableMethod(
                            method, this.applicationContext.getType(beanName));
                        //创建ApplicationListenerMethodAdapter适配器
                        ApplicationListener<?> applicationListener =
                            factory.createApplicationListener(beanName, targetType, methodToUse);
                        if (applicationListener instanceof ApplicationListenerMethodAdapter) {
                            //设置适配器的一些属性
                            ((ApplicationListenerMethodAdapter) applicationListener)
                            .init(this.applicationContext, this.evaluator);
                        }
                        //IOC容器中添加该时适配器(该适配器已经实现了ApplicationListener接口)					
                        this.applicationContext.addApplicationListener(applicationListener);
                        break;
                    }
                }
            }
            if (logger.isDebugEnabled()) {
                logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
                             beanName + "': " + annotatedMethods);
            }
        }
    }
}
原文地址:https://www.cnblogs.com/wwjj4811/p/14540493.html