(二)扩展原理:【3】ApplicationListener


一、ApplicationListener 接口

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

public interface ApplicationListener
监听 ApplicationEvent 及其下面的子事件

二、步骤

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

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

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

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

  

  4、发布一个事件:

applicationContext.publishEvent();

三、案例

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

@Component
public class MyApplicationListener implements ApplicationListener {

    //当容器中发布此事件以后,方法触发
    @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();

相关