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

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

ApplicationEvent

package com.example.demo.event;

import org.springframework.context.ApplicationEvent;

/**
 * @author huangd
 * @date 2021-11-09
 **/
public class ObjectVo extends ApplicationEvent {
    
    
    private String message;

    /**
     * Create a new ApplicationEvent.
     *
     * @param source the object on which the event initially occurred (never {@code null})
     */
    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;

/**
 * @author huangd
 * @date 2021-11-10
 **/
@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;

/**
 * @author huangd
 * @date 2021-11-10
 **/
@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;

/**
 * @author huangd
 * @date 2021-11-10
 **/
@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;

/**
 * @author huangd
 * @date 2021-11-10
 **/
@Service
@Order(1)
public class HandlerListener2 implements ApplicationListener<ObjectVo> {
    
    

    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;

/**
 * @author huangd
 * @date 2021-11-10
 **/
@Service
@Order(2)
public class HandlerListener implements ApplicationListener<ObjectVo> {
    
    

    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<ApplicationListener<?>> retrieveApplicationListeners(
			ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable ListenerRetriever retriever) {
    
    

		List<ApplicationListener<?>> allListeners = new ArrayList<>();
		Set<ApplicationListener<?>> listeners;
		Set<String> 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);

猜你喜欢

转载自blog.csdn.net/huangdi1309/article/details/121244596