spring源码学习之容器监听器篇

一、监听器相关接口

1、ApplicationEventPublisher容器的事件发布者

//该接口规范了发布事件的基本功能
public interface ApplicationEventPublisher {

    /**
     * 发布事件
     */
    void publishEvent(ApplicationEvent event);

    /**
     * 发布事件
     */
    void publishEvent(Object event);
}

2、ApplicationEvent事件基类

//不同的事件继承自这个类 通过instanceof运算符来区分到底产生的是什么事件
public abstract class ApplicationEvent extends EventObject {
...
}

3、ApplicationEventMulticaster事件传播者

//该接口定义了一些监听器的增删改的方法可以参考下jdk的java.util.Observable很相像
public interface ApplicationEventMulticaster {
    ...
}

4、ApplicationListener事件监听器接口

//实现了该接口 就可以监听容器产生的相关事件了
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

    /**
     * 当容器中发布事件时,其实就是通过ApplicationEventMulticaster的实现类遍历监听器调用的该方法
     */
    void onApplicationEvent(E event);

}

5、事件类型

二、容器中监听器相关接口的实现

1、ApplicationEventPublisher事件发布者ApplicationContext
spring在AbstractApplicationContext中实现了ApplicationEventPublisher相关功能
通过下面的代码可以看出其实ApplicationEventPublisher中的事件最终是由ApplicationEventMulticaster
来实现事件发布的

public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext, DisposableBean {
    ...
    @Override
    public void publishEvent(ApplicationEvent event) {
        publishEvent(event, null);
    }
    @Override
    public void publishEvent(Object event) {
        publishEvent(event, null);
    }
    protected void publishEvent(Object event, ResolvableType eventType) {
        Assert.notNull(event, "Event must not be null");
        if (logger.isTraceEnabled()) {
            logger.trace("Publishing event in " + getDisplayName() + ": " + event);
        }

        // 在这里确定要发布的事件对象
        ApplicationEvent applicationEvent;
        if (event instanceof ApplicationEvent) {
            applicationEvent = (ApplicationEvent) event;
        }
        else {
            applicationEvent = new PayloadApplicationEvent<Object>(this, event);
            if (eventType == null) {
                eventType = ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass());
            }
        }

        // 在这里委托ApplicationEventMulticaster进行事件发布
        if (this.earlyApplicationEvents != null) {
            //在注册完毕监听器时会将这里的事件发布出去然后置为null(防止publish的事件在注册监听器之前广播)
            this.earlyApplicationEvents.add(applicationEvent);
        }
        else {
            //获取容器的广播者进行事件广播
            getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
        }

        // Publish event via parent context as well...
        if (this.parent != null) {
            if (this.parent instanceof AbstractApplicationContext) {
                ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
            }
            else {
                this.parent.publishEvent(event);
            }
        }
    }
}

2、ApplicationEvent实现

//从这里可以看出事件的实现并没有定义太多功能,更多的只是作为一种标示,利用类来表示是什么事件而已
//当然也可以定义一些字段来传递信息
public class ContextStartedEvent extends ApplicationContextEvent {
    public ContextStartedEvent(ApplicationContext source) {
        super(source);
        } 
}

3、ApplicationEventMulticaster的实现AbstractApplicationEventMulticaster、SimpleApplicationEventMulticaster
AbstractApplicationEventMulticaster提供一个基本的事件广播的监听器的增删功能,而广播事件
multicastEvent(ApplicationEvent event)
multicastEvent(ApplicationEvent event, ResolvableType eventType)
的方法交给交给了子类SimpleApplicationEventMulticaster来实现
ResolvableType 这个类其实就是封装的java.lang.reflect.Type

//实现事件广播
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
    ...
    @Override
    public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
        //如果定义了事件类型则只判断支持该类型的监听器进行广播事件(判断是否支持通过子接口里的supportsEventType(ResolvableType eventType)进行判断的)
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            Executor executor = getTaskExecutor();
            if (executor != null) {
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        //在这里就是调用listener.onApplicationEvent(event)方法通知监听器
                        invokeListener(listener, event);
                    }
                });
            }
            else {

                invokeListener(listener, event);
            }
        }
    }
...
}

4、ApplicationListener的实现
其实到这里 就是可以任意扩展的地方啦,只要你的对象是交给Spring容器管理的,在容器
初始化时就会注册监听器,然后在容器发布事件的时候就能接收到相应的事件了
这里看一下SqlSessionFactoryBean的实现:

public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
      ...
      @Override
      public void onApplicationEvent(ApplicationEvent event) {
         //这里由于容器产生任何事件都会调用该方法,所以使用instanceof 来区分是什么事件。
        if (failFast && event instanceof ContextRefreshedEvent) {
          // fail-fast -> check all statements are completed
          this.sqlSessionFactory.getConfiguration().getMappedStatementNames();
        }
      }
      ...
}

总结:

其实监听器就是观察者模式的实现,可以参考jdk提供的java.util.Observable,java.util.Observer
就更能理解spring在这里的设计,spring将各个环节都进行了接口抽象,而且在实现时也会使用abstract类进行具有通用性的方法进行分层实现,使得很多方法就更具有复用性,当然这样扩展性也提现出来了,如果有特殊需求,可以继承一下就得到了很多基本功能,很好的提现了从抽象到具体的面向对象的设计思想。而像getTaskExecutor()这种获取一些对象通过一个protected的get方法来获取,使得程序的灵活性大大的提高了,充分的利用多态的特性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值