目录

流程

容器的刷新流程如下:

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();

}

finally {

// Reset common introspection caches in Spring's core, since we

// might not ever need metadata for singleton beans anymore...

resetCommonCaches();

}

}

}

其中与EventListener有关联的步骤

initApplicationEventMulticaster(); 初始化事件多播器

registerListeners(); 注册Listener到多播器

finishBeanFactoryInitialization(beanFactory); 涉及将@EventListener转为普通Listener

finishRefresh(); 发布容器刷新完成事件ContextRefreshedEvent

initApplicationEventMulticaster()

protected void initApplicationEventMulticaster() {

ConfigurableListableBeanFactory beanFactory = getBeanFactory();

//找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

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 + "]");

}

}

}

registerListeners()

protected void registerListeners() {

// Register statically specified listeners first.

for (ApplicationListener> listener : getApplicationListeners()) {

getApplicationEventMulticaster().addApplicationListener(listener);

}

// Do not initialize FactoryBeans here: We need to leave all regular beans

// uninitialized to let post-processors apply to them!

String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);

for (String listenerBeanName : listenerBeanNames) {

getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);

}

// Publish early application events now that we finally have a multicaster...

Set earlyEventsToProcess = this.earlyApplicationEvents;

this.earlyApplicationEvents = null;

if (earlyEventsToProcess != null) {

for (ApplicationEvent earlyEvent : earlyEventsToProcess) {

getApplicationEventMulticaster().multicastEvent(earlyEvent);

}

}

}

finishRefresh()

protected void finishRefresh() {

// Clear context-level resource caches (such as ASM metadata from scanning).

clearResourceCaches();

// 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() 发布事件,我们也可以手动调用容器的publishEvent() 方法来发布事件

ApplicationContext.publishEvent(new MyEvent("test"));

publishEvent()

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {

// 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 {

//获取多播器

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);

}

}

}

@EventListener处理

原理:通过EventListenerMethodProcessor来处理@Eventlstener

public class EventListenerMethodProcessor implements SmartInitializingSingleton, ApplicationContextAware

EventListenerMethodProcessor 是一个 SmartInitializingSingleton。

SmartInitializingSingleton什么时候执行呢?

在Refresh()

​ -> finishBeanFactoryInitialization(beanFactory);

​ -> DefaultListableBeanFactory#preInstantiateSingletons

public void preInstantiateSingletons() throws BeansException {

// 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.

List beanNames = new ArrayList<>(this.beanDefinitionNames);

// Trigger initialization of all non-lazy singleton beans...

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)

((SmartFactoryBean>) factory)::isEagerInit,

getAccessControlContext());

}

else {

isEagerInit = (factory instanceof SmartFactoryBean &&

((SmartFactoryBean>) factory).isEagerInit());

}

if (isEagerInit) {

getBean(beanName);

}

}

}

else {

// 创建bean

getBean(beanName);

}

}

}

// Trigger post-initialization callback for all applicable beans...

for (String beanName : beanNames) {

Object singletonInstance = getSingleton(beanName);

if (singletonInstance instanceof SmartInitializingSingleton) {

final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;

if (System.getSecurityManager() != null) {

AccessController.doPrivileged((PrivilegedAction) () -> {

smartSingleton.afterSingletonsInstantiated();

return null;

}, getAccessControlContext());

}

else {

smartSingleton.afterSingletonsInstantiated();

}

}

}

}

preInstantiateSingletons 前半部分主要是遍历beanNames 创建Bean。创建完bean后判断各bean是不是SmartInitializingSingleton,如果是则执行 smartSingleton.afterSingletonsInstantiated()方法。

//org.springframework.context.event.EventListenerMethodProcessor#afterSingletonsInstantiated

public void afterSingletonsInstantiated() {

List factories = getEventListenerFactories();

ConfigurableApplicationContext context = getApplicationContext();

String[] beanNames = context.getBeanNamesForType(Object.class);

for (String beanName : beanNames) {

if (!ScopedProxyUtils.isScopedTarget(beanName)) {

Class> type = null;

try {

type = AutoProxyUtils.determineTargetClass(context.getBeanFactory(), beanName);

}

if (type != null) {

if (ScopedObject.class.isAssignableFrom(type)) {

try {

Class> targetClass = AutoProxyUtils.determineTargetClass(

context.getBeanFactory(), ScopedProxyUtils.getTargetBeanName(beanName));

if (targetClass != null) {

type = targetClass;

}

}

}

try {

//处理bean

processBean(factories, beanName, type);

}

}

}

}

}

protected void processBean(

final List factories, final String beanName, final Class> targetType) {

//没有注解的class

if (!this.nonAnnotatedClasses.contains(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 = getApplicationContext();

for (Method method : annotatedMethods.keySet()) {

for (EventListenerFactory factory : factories) {

if (factory.supportsMethod(method)) {

Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));

//创建applicationListener,通过Adapter将注解形式的listener转换为普通的listener

ApplicationListener> applicationListener =

factory.createApplicationListener(beanName, targetType, methodToUse);

if (applicationListener instanceof ApplicationListenerMethodAdapter) {

((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);

}

//添加listner到applicationContext

context.addApplicationListener(applicationListener);

break;

}

}

}

if (logger.isDebugEnabled()) {

logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +

beanName + "': " + annotatedMethods);

}

}

}

}

查找类中标注@EventListener的方法

EventListenerFactory.createApplicationListener(beanName, targetType, methodToUse) 构造listener

添加listener到Context中

如果有applicationEventMulticaster,添加到ApplicationContext.applicationEventMulticaster中

如果没有applicationEventMulticaster,添加到ApplicationContext.applicationListeners中。

转载至链接:https://my.oschina.net/u/1245414/blog/1926461

eventlistener java_EventListener原理相关推荐

  1. SpringBoot中@EventListener注解的使用

    一:背景 在开发工作中,会遇到一种场景,做完某一件事情以后,需要广播一些消息或者通知,告诉其他的模块进行一些事件处理,一般来说,可以一个一个发送请求去通知,但是有一种更好的方式,那就是事件监听,事件监 ...

  2. SpringBoot 使用注解实现消息广播功能

    背景 在开发工作中,会遇到一种场景,做完某一件事情以后,需要广播一些消息或者通知,告诉其他的模块进行一些事件处理,一般来说,可以一个一个发送请求去通知,但是有一种更好的方式,那就是事件监听,事件监听也 ...

  3. 回炉Spring--事务及Spring源码

    声明式事务 配置文件信息: /*** @EnableTransactionManagement 开启基于注解的事务管理功能* 1.配置数据源* 2.配置事务管理器来管理事务* 3.给方法上标注 @Tr ...

  4. 论如何优雅地知道OkHttp的请求时间

    /   今日科技快讯   / 虾米音乐宣布2021年2月5日0点停止服务,停止所有歌曲试听.下载.评论等所有音乐内容消费场景,停止个人资料导出或下载,仅保留账号资产处理.网页端音乐人提现服务.3月5日 ...

  5. OkHttp3详细使用教程

    OkHttp介绍 OkHttp官网地址:http://square.github.io/okhttp/ OkHttp GitHub地址:https://github.com/square/okhttp ...

  6. 【spring】Spring事件监听器ApplicationListener的使用与源码分析

    ApplicationEvent以及Listener是Spring为我们提供的一个事件监听.订阅的实现,内部实现原理是观察者设计模式,设计初衷也是为了系统业务逻辑之间的解耦,提高可扩展性以及可维护性. ...

  7. java signature 性能_Java常见bean mapper的性能及原理分析

    背景 在分层的代码架构中,层与层之间的对象避免不了要做很多转换.赋值等操作,这些操作重复且繁琐,于是乎催生出很多工具来优雅,高效地完成这个操作,有BeanUtils.BeanCopier.Dozer. ...

  8. SpringCloudAlibaba:Nacos实现原理详解

    欢迎关注方志朋的博客,回复"666"获面试宝典 Nacos 架构 Provider APP:服务提供者 Consumer APP:服务消费者 Name Server:通过VIP(V ...

  9. Nacos实现原理详解

    欢迎关注方志朋的博客,回复"666"获面试宝典 来源:https://blog.csdn.net/cold___play/article/details/108032204 Nac ...

最新文章

  1. OpenCV常遇问题解决方法汇总
  2. web页面事件无响应,元素点击不到
  3. 一次完整的HTTP事务是怎样一个过程
  4. 非静态成员函数的非法调用错误
  5. 自定义注解与validation结合使用案例
  6. dedecms织梦仿麦站网模板源码下载站源码
  7. android 应用区高度,Android创建显示区高度可以调整的ScrollView
  8. Linux 五种I/O模型
  9. python中文视频教程-中谷教育python中文视频教程(全38集)
  10. MySQL存储过程(四)——存储过程循环流控语句
  11. 余额宝宣布开放 中欧基金首批入驻
  12. 《机会的数学》--陈希孺
  13. 手机wap网站制作教程
  14. 解决github下载及访问不稳定问题
  15. java 实心圆,如何用css3实现实心圆
  16. mysql字符集校对_MySQL字符集与校对
  17. 跳跃表(SkipList)
  18. html效果浮窗效果,jQuery简单实现中间浮窗效果
  19. SpringMVC Web实现文件上传下载功能实例解析
  20. 微信小程序模仿拼多多APP地址选择样式

热门文章

  1. SignalR 聊天室实例详解(服务器端推送版)
  2. discuz自动添加兼容html5标签的音乐播放器
  3. FFmpeg和WebRTC
  4. SurfaceFlinger与Hardware Composer
  5. Android Debug方法
  6. android -- 蓝牙 bluetooth (四)OPP文件传输
  7. linux strace调试用法
  8. springboot之mybatis分页查询
  9. YOLO: Real-Time Object Detection 遇到的问题
  10. python-《Python发展前景》