ApplicationListener介绍

115 阅读2分钟

7jG8JJ8bkG.jpg

常言道,此处无声更胜有声。看似无关联,实际千丝万缕。事件驱动让你的代码充分解耦,让我们一起看看Spring提供的事件驱动吧❤️

是什么

  • 监听容器中发布的事件,事件驱动模型开发
  • public interface ApplicationListener<E extends ApplicationEvent> 意思是监听ApplicationEvent及其下面的子事件

示例

  • 写一个监听器来监听某个事件(ApplicationEvent及其下面的子事件)
  • 把监听器加入容器
  • 只要容器中有相关事件的发布,我们就能监听到这个事件,例如ContextRefreshedEvent:容器刷新完成(所有bean都完全创建)会发布这个事件
//接收事件方式
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent>{
    //当容器中发布此事件之后,方法会被触发
    @Override
    public void onApplicationEvent(ApplicationEvent event){
        System.out.println("收到事件:"+event);
    }
}

//发送事件方式
applicationContext.publishEvent(new ApplicationEvent(new Stirng("我发布的事件..")))

原理解析

  • 容器创建对象,refresh()
  • finishRefresh() 容器刷新完成
  • publishEvent(new ContextRefreshedEvent(this))
  • 事件发布流程:
    • 获取事件的多播器(派发器),getApplicationEventMulticaster()
    • multicastEvent派发事件
    • 获取到所有的ApplicationListener for(final ApplicationListener<?> listener:getApplicationListeners(event, type))
    • 如果有Executor 可以支持使用Executor 进行异步派发 Executor executor = getTaskExecutor()
    • 否则,同步的方式直接执行listener方法 invokeListener(listener, event)
  • 可以用来监听容器创建好之后执行一些操作,比如初始化数据,初始化缓存 等等。
  • 除了采用实现接口的方式创建自己的监听器,还可以采用注解的方式
@Component
public class Test{
    @EventListener(classes=ApplicationEvent.class)
    public void test1(ApplicationEvent e){
        System.out.println("收到事件:"+e);
    }
}

自定义事件发布

  • 自定义事件,继承ApplicationContextEvent 抽象类
public class MyApplicationEvent extends ApplicationEvent{
    private static final long serialVersionUID = 1L;
    
    public MyApplicationEvent(ApplicationContext source){
        super(source)
    }
}
  • 写个实现了ApplicationListener接口的监听器 监听我们自定义的事件(加在ioc容器中)
@Component
public class MyApplicationListener implements ApplicationListener<MyApplicationEvent>{
    public void onApplicationEvent(MyApplicationEvent event){
        System.out.println("收到事件"+event);
        System.out.println("收到事件"+event.getTimestamp());
        System.out.println("收到事件"+event.getSource());
    }
}
  • 发布事件
@SpringBootTest 
@RunWith(SpringRunner.class) 
public class Test { 
    @Autowired 
    private ApplicationContext applicationContext; 
    
    @Test 
    public void test1() { 
        applicationContext.publishEvent(new MyApplicationEvent(new Stirng("我发布的事件.."))); 
    } 
}