zoukankan      html  css  js  c++  java
  • (二)扩展原理:【3】ApplicationListener

    一、ApplicationListener 接口

      ApplicationListener:监听容器中发布的事件。事件驱动模型开发;

    public interface ApplicationListener<E extends ApplicationEvent>
    监听 ApplicationEvent 及其下面的子事件
    

      

    二、步骤

      1、写一个监听器(ApplicationListener实现类)来监听某个事件(ApplicationEvent及其子类)

      2、把监听器加入到容器;

      3、只要容器中有相关事件的发布,我们就能监听到这个事件;

    ContextRefreshedEvent:容器刷新完成(所有bean都完全创建)会发布这个事件;
    ContextClosedEvent:关闭容器会发布这个事件;
    

      

      4、发布一个事件:

    applicationContext.publishEvent();
    

      

    三、案例

      1、自定义一个监听器实现类

    @Component
    public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
    
        //当容器中发布此事件以后,方法触发
        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            System.out.println("收到事件:" + event);
        }
    }

      2、加入到配置文件中

    @ComponentScan(value = {"com.njf.ext", "com.njf.bean"})
    @Configuration
    public class ExtConfig {
    
        @Bean
        public Blue Blue() {
            return new Blue();
        }
    }

      3、测试

        @Test
        public void test01() {
            AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(ExtConfig.class);
    
            System.out.println("IOC容器创建完毕!");
    
            //发布事件
            ioc.publishEvent(new ApplicationEvent(new String("我发布的事件")) {});
    
            ioc.close();
        }

      测试结果:

    四、原理

      事件监听器原理:

        ContextRefreshedEvent、IOCTest_Ext$1[source=我发布的时间]、ContextClosedEvent;
        1)、ContextRefreshedEvent事件:
            1)、容器创建对象:refresh();
            2)、finishRefresh(); 容器刷新完成会发布ContextRefreshedEvent事件
            3)、参看下面的:【事件发布流程】
                【事件发布流程】:publishEvent(new ContextRefreshedEvent(this));
                  1)、获取事件的多播器(派发器):getApplicationEventMulticaster()
                  2)、multicastEvent派发事件:
                  3)、获取到所有的ApplicationListener;
                      for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
                      1)、如果有Executor,可以支持使用Executor进行异步派发;
                          Executor executor = getTaskExecutor();
                      2)、否则,同步的方式直接执行 listener 方法;invokeListener(listener, event);
                           拿到 listener 回调 onApplicationEvent 方法;
    
        2)、自己发布事件;【参照上面的事件发布流程】
        3)、容器关闭会发布ContextClosedEvent;
    

      

      【事件多播器(派发器)】

        1)、容器创建对象:refresh();
        2)、initApplicationEventMulticaster();初始化ApplicationEventMulticaster;
              1)、先去容器中找有没有id=“applicationEventMulticaster”的组件;
              2)、如果没有this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
                  并且加入到容器中,我们就可以在其他组件要派发事件,自动注入这个applicationEventMulticaster;
    

      

      【容器中有哪些监听器】

        1)、容器创建对象:refresh();
        2)、registerListeners();
            从容器中拿到所有的监听器,把他们注册到applicationEventMulticaster中;
            String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
            //将listener注册到ApplicationEventMulticaster中
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);

    五、使用 @EvenListener 实现监听事件

      在方法上面使用 @EvenListener 注解,可以获取到监听的事件:

    @Service
    public class UserService {
    
        @EventListener(classes={ApplicationEvent.class})
        public void listen(ApplicationEvent event){
            System.out.println("UserService。。监听到的事件:"+event);
        }
    }

      运行结果:

      使用 @EventListener 注解实现监听事件
      @EventListener
      原理:使用EventListenerMethodProcessor处理器来解析方法上的 @EventListener;

    SmartInitializingSingleton 原理:-> afterSingletonsInstantiated();
    1、ioc容器创建对象并refresh();
    2、finishBeanFactoryInitialization(beanFactory);初始化剩下的单实例bean;
        (1)先创建所有的单实例bean;getBean();
        (2)获取所有创建好的单实例bean,判断是否是SmartInitializingSingleton类型的;
        如果是就调用afterSingletonsInstantiated();
    

      

  • 相关阅读:
    点击添加,上面div获取到值
    解决ios浏览器视频无法播放问题
    jquery中使用$(#form).submit()提交表单无效原因分析及解决Script
    html页面,css引用外部字体
    当页面信息填写不完整,点击提交后,直接跳转到未填写位置
    layui日历控件添加js校验后 页面点击提交后,点击日历插件不起作用
    jquery在线引用
    左侧导航高度,自适应右侧内容高度
    Mysql
    Linux文件编辑器,链接,及常用系统命令
  • 原文地址:https://www.cnblogs.com/niujifei/p/15563913.html
Copyright © 2011-2022 走看看