spring中 EventPublisher

作用

这个其实就是一个设计模式中的观察者模式,广播推送消息

spring中怎么用?

  1. 客户端发布事件
public class IOCTest_Ext {
	
	@Test
	public void test01(){
		AnnotationConfigApplicationContext applicationContext  = new AnnotationConfigApplicationContext(ExtConfig.class);
		
		
		//发布事件;
		applicationContext.publishEvent(new ApplicationEvent(new String("我发布的时间")) {
		});
		
		applicationContext.close();
	}

}
  1. listen监听事件
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {

	//当容器中发布此事件以后,方法触发
	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		// TODO Auto-generated method stub
		System.out.println("收到事件:"+event);
	}

}
  1. 结果
收到事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@6d86b085: startup date [Wed Apr 10 06:59:46 CST 2019]; root of context hierarchy]
收到事件:com.atguigu.test.IOCTest_Ext$1[source=我发布的时间]
收到事件:org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@6d86b085: startup date [Wed Apr 10 06:59:46 CST 2019]; root of context hierarchy]

有三个结果:分别是容器刷新、关闭的事件,还有一个是我们自定义的。

  1. 也可以使用更方便的注解的方式,效果是一样的
@Service
public class UserService {
	
	@EventListener(classes={ApplicationEvent.class})
	public void listen(ApplicationEvent event){
		System.out.println("UserService。。监听到的事件:"+event);
	}

}

  1. 结果
UserService。。监听到的事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@6d86b085: startup date [Wed Apr 10 07:01:54 CST 2019]; root of context hierarchy]
UserService。。监听到的事件:com.atguigu.test.IOCTest_Ext$1[source=我发布的时间]
UserService。。监听到的事件:org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@6d86b085: startup date [Wed Apr 10 07:01:54 CST 2019]; root of context hierarchy]

源码分析

applicationContext.publishEvent(new ApplicationEvent(new String(“我发布的时间”)) {});
AbstractApplicationContext#publishEvent

this.getApplicationEventMulticaster().multicastEvent((ApplicationEvent)applicationEvent, eventType);

如果发现有任务执行器,就交给它处理,没有的话就直接处理。默认情况下是没有的

public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
        ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
        //得到容器中所有的listener
        Iterator var4 = this.getApplicationListeners(event, type).iterator();

        while(var4.hasNext()) {
            final ApplicationListener<?> listener = (ApplicationListener)var4.next();
            Executor executor = this.getTaskExecutor();
            if (executor != null) {
                executor.execute(new Runnable() {
                    public void run() {
                        SimpleApplicationEventMulticaster.this.invokeListener(listener, event);
                    }
                });
            } else {
                this.invokeListener(listener, event);
            }
        }

    }
 private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
        try {
            listener.onApplicationEvent(event);

问题:这些listen是什么时候注入的呢?
org.springframework.context.event.AbstractApplicationEventMulticaster#retrieveApplicationListeners

private Collection<ApplicationListener<?>> retrieveApplicationListeners(
			ResolvableType eventType, Class<?> sourceType, ListenerRetriever retriever) {

		LinkedList<ApplicationListener<?>> allListeners = new LinkedList<ApplicationListener<?>>();
		//1.所有实现ApplicationListener或者加@EventListener并且在容器中的都会自动注入进来
		Set<ApplicationListener<?>> listeners;
		Set<String> listenerBeans;
		synchronized (this.retrievalMutex) {
			listeners = new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners);
			listenerBeans = new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans);
		}
		//处理ApplicationListener这种类型的,都加入到listeners中
		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) {
								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
				}
			}
		}
		//2.排序
		AnnotationAwareOrderComparator.sort(allListeners);
		return allListeners;
	}

查看这个方法 this.getApplicationListeners(event, type)

扩展

  1. 异步方式来处理
    2
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot 实现发布订阅模式,可以使用 Spring 的事件机制来实现。下面是一个简单的示例: 1. 创建一个事件类,例如 `MyEvent`: ```java public class MyEvent { private String message; public MyEvent(String message) { this.message = message; } public String getMessage() { return message; } } ``` 2. 创建一个事件发布者,例如 `EventPublisher`: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; @Component public class EventPublisher { @Autowired private ApplicationContext applicationContext; public void publishEvent(String message) { MyEvent event = new MyEvent(message); applicationContext.publishEvent(event); } } ``` 3. 创建一个事件监听器,例如 `EventListener`: ```java import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; @Component public class EventListener { @EventListener public void handleEvent(MyEvent event) { String message = event.getMessage(); // 处理事件 System.out.println("收到事件:" + message); } } ``` 4. 在需要发布事件的地方注入 `EventPublisher`,并调用 `publishEvent` 方法来发布事件: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class MyApp { @Autowired private EventPublisher eventPublisher; public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } public void someMethod() { // 发布事件 eventPublisher.publishEvent("Hello, world!"); } } ``` 当调用 `someMethod` 方法时,会触发 `MyEvent` 事件的发布,然后 `EventListener` 的 `handleEvent` 方法会被自动调用,从而实现了发布订阅模式。 这是一个简单的示例,你可以根据具体需求进行扩展和定制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值