栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

ApplicationListener监听器使用介绍,@Order加载顺序无效解析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ApplicationListener监听器使用介绍,@Order加载顺序无效解析

ApplicationListener是Spring事件机制的一部分,与抽象类ApplicationEvent类配合来完成ApplicationContext的事件发布订阅机制。

ApplicationEvent
package com.example.demo.event;

import org.springframework.context.ApplicationEvent;


public class ObjectVo extends ApplicationEvent {
    private String message;

    
    public ObjectVo(Object source, String message) {
        super(source);
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

定义监听器处理类1,这里使用注解@EventListener
package com.example.demo.event;

import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;


@Component
@Order(2)
public class HandlerListener  {

    @EventListener
    public void listen(ObjectVo source) {
        System.out.println(this.getClass().getName() + " " + source.getMessage());
    }

}

定义监听器处理类2

package com.example.demo.event;

import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;


@Component
@Order(1)
public class HandlerListener2 {

    @EventListener
    public void listen(ObjectVo source) {
        System.out.println(this.getClass().getName() + " " + source.getMessage());
    }

}

发布事件处理类:

package com.example.demo.event;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;


@Component
public class ListenEventPubliserService {
    @Autowired
    private ApplicationEventPublisher publisher;

    public void publisher() {
        String message = "hello publisher";
        ObjectVo objectVo = new ObjectVo(this, message);

        publisher.publishEvent(objectVo);
    }
}

运行结果:

可以看到两个Listener都分别接收到了事件。

这里发现一个问题:我在两个Listener类加了@Order注解,理论上值越小的越应该先执行对吧?但是上面输出结果来看,并不是我们期望的这样,而是HandlerListener先输出了,Order不生效了?

经查阅文章后了解到,Spring中的Order接口只针对AOP切面和拦截器以及注入集合中的bean执行顺序,而对于bean加载顺序是不会干预的,也就是默认文件顺序了。

那么怎么办呢,如果我们一定要HandlerListener2先执行的话,怎么做?

上面说了,bean依赖注入集合执行顺序它能控制,那么我们使用集合的思路不就行了吗?
于是将上面代码做以下调整;

package com.example.demo.event;

import org.springframework.context.ApplicationListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;


@Service
@Order(1)
public class HandlerListener2 implements ApplicationListener {

    public HandlerListener2() {
        System.out.println("加载" + this.getClass().getName());
    }

    @Override
    public void onApplicationEvent(ObjectVo source) {
        System.out.println(this.getClass().getName() + " " + source.getMessage());
    }
}

package com.example.demo.event;

import org.springframework.context.ApplicationListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;


@Service
@Order(2)
public class HandlerListener implements ApplicationListener {

    public HandlerListener() {
        System.out.println("加载" + this.getClass().getName());
    }


    @Override
    public void onApplicationEvent(ObjectVo source) {
        System.out.println(this.getClass().getName() + " " + source.getMessage());
    }
}

再次执行结果:

可以看到HandlerListener2先执行了。

因为拿Listener时候,spring做了下排序,参考类的方法
org.springframework.context.event.AbstractApplicationEventMulticaster#retrieveApplicationListeners

private Collection> retrieveApplicationListeners(
			ResolvableType eventType, @Nullable Class sourceType, @Nullable ListenerRetriever retriever) {

		List> allListeners = new ArrayList<>();
		Set> listeners;
		Set listenerBeans;
		synchronized (this.retrievalMutex) {
			listeners = new linkedHashSet<>(this.defaultRetriever.applicationListeners);
			listenerBeans = new linkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
		}
		for (ApplicationListener listener : listeners) {
			if (supportsEvent(listener, eventType, sourceType)) {
				if (retriever != null) {
					retriever.applicationListeners.add(listener);
				}
				allListeners.add(listener);
			}
		}
		if (!listenerBeans.isEmpty()) {
			BeanFactory beanFactory = getBeanFactory();
			for (String listenerBeanName : listenerBeans) {
				try {
					Class listenerType = beanFactory.getType(listenerBeanName);
					if (listenerType == null || supportsEvent(listenerType, eventType)) {
						ApplicationListener listener =
								beanFactory.getBean(listenerBeanName, ApplicationListener.class);
						if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
							if (retriever != null) {
								if (beanFactory.isSingleton(listenerBeanName)) {
									retriever.applicationListeners.add(listener);
								}
								else {
									retriever.applicationListenerBeans.add(listenerBeanName);
								}
							}
							allListeners.add(listener);
						}
					}
				}
				catch (NoSuchBeanDefinitionException ex) {
					// Singleton listener instance (without backing bean definition) disappeared -
					// probably in the middle of the destruction phase
				}
			}
		}
		AnnotationAwareOrderComparator.sort(allListeners);
		if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
			retriever.applicationListeners.clear();
			retriever.applicationListeners.addAll(allListeners);
		}
		return allListeners;
	}

其中有一句:
AnnotationAwareOrderComparator.sort(allListeners);

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/462848.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号