spring boot 2 Source Series (two) - Listener ApplicationListener

It is strongly recommended to read this article before, look at the  spring boot 2 Source Series (a) - system initialization is ApplicationContextInitializer . Source listener with an initialization source code there are many similarities, such as: load, initialize the listener, the listener delegate, the listener sort.

Use spring boot listener

spring boot listener a variety of configurations.

The first: use spring.factories Configuration

1, the new Alistener achieve ApplicationListener Interface

// 监听ApplicationStartedEvent事件
@Order(1)
public class Alistener implements ApplicationListener<ApplicationStartedEvent> {
    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        System.out.println("####Alistener监听到ApplicationStartedEvent");
    }
}

2, add the spring.factories

org.springframework.context.ApplicationListener=com.example.springbootdemo.listener.Alistener

The second: hard-coded

1, the new Blistener achieve ApplicationListener Interface

// 监听ApplicationStartedEvent事件
@Order(2)
public class Blistener implements ApplicationListener<ApplicationStartedEvent> {
    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        System.out.println("####Blistener监听到ApplicationStartedEvent");
    }
}

2, modifying the boot class, by adding the code Blistener

@SpringBootApplication
public class SpringBootDemoApplication {
    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(SpringBootDemoApplication.class);
        // 添加监听器
        springApplication.addListeners(new Blistener());
        springApplication.run(args);
    }
}

Third: context.listener.classes arranged in application.properties

1, the new Clistener achieve ApplicationListener Interface

// 监听ApplicationStartedEvent事件
@Order(3)
public class Clistener implements ApplicationListener<ApplicationStartedEvent> {
    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        System.out.println("####Clistener监听到ApplicationStartedEvent");
    }
}

2, disposed in the application.properties

context.listener.classes=com.example.springbootdemo.listener.Clistener

Fourth: to achieve GenericApplicationListener Interface

1, the new Dlistener achieve GenericApplicationListener Interface

/**
 * GenericApplicationListener是标准ApplicationListener接口的扩展变体,
 * 公开了其他元数据,例如受支持的事件和源类型。
 * 从Spring Framework 4.2开始,此接口取代了基于类的SmartApplicationListener,并全面处理了通用事件类型。
 */
@Order(4)
public class Dlistener implements GenericApplicationListener {

    // 此监听器支持的事件类型
    @Override
    public boolean supportsEventType(ResolvableType eventType) {
        // 监听ApplicationStartingEvent、ApplicationStartedEvent事件
        return eventType.isAssignableFrom(ApplicationStartingEvent.class)
                || eventType.isAssignableFrom(ApplicationStartedEvent.class);
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("####Dlistener监听到"+event.getClass().getSimpleName());
    }

}

2, add the configuration (note: no spaces and achieve, \ between before and after class) in spring.factories in.

org.springframework.context.ApplicationListener=com.example.springbootdemo.listener.Alistener,\
com.example.springbootdemo.listener.Dlistener

Start the project, the console print

#### Dlistener listening to ApplicationStartingEvent
#### Clistener listening to ApplicationStartedEvent
#### aListener listening to ApplicationStartedEvent
#### BLISTENER listening to ApplicationStartedEvent
#### Dlistener listening to ApplicationStartedEvent

Source explanation - initialization phase

spring boot listener initialization phase system initialization is very similar, you are creating SpringApplication instances when the property is set to this.listeners in spring.factories configuration of listeners.

The main source is as follows:

// 源码位置 org.springframework.boot.SpringApplication#SpringApplication(org.springframework.core.io.ResourceLoader, java.lang.Class<?>...)
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
	// 将spring.factories配置的监听器赋值给this.listeners
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
}

Source explanation - the operational phase

1, enter SpringApplication # run (java.lang.String ...) source code, run the inquiry process listener

// list only the main code
org.springframework.boot.SpringApplication # RUN (java.lang.String ...)
    // break point here. Get SpringApplicationRunListeners
    SpringApplicationRunListeners in the Listeners = getRunListeners (args);
    // start the Spring the Application start-up phase
    listeners.starting ();
    // start the Spring the Application stage of completion. Here to make a break through the stage of completion of the startup code analysis listener spring boot source
    listeners.started (context);
    // run the Application phase of the Spring
    listeners.running (context);

// SpringApplicationRunListeners讲解
class SpringApplicationRunListeners {

    /**
     * SpringApplicationRunListeners 是对 SpringApplicationRunListener 的封装。
     * 包含多个SpringApplicationRunListener,以便能批量执行SpringApplicationRunListener的同名方法。
     * 利用List<SpringApplicationRunListener> listeners 可以方便我们拓展,自定义运行监听器。
     */
    private final List<SpringApplicationRunListener> listeners;

    // 省略部分代码

    /**
     * 循环listeners并调用SpringApplicationRunListener的started同名方法。
     * this.listeners默认只包含一个SpringApplicationRunListener实现类EventPublishingRunListener
     */
    void started(ConfigurableApplicationContext context) {
        for (SpringApplicationRunListener listener : this.listeners) {
            listener.started(context);
        }
    }

    void environmentPrepared(ConfigurableEnvironment environment) {
        for (SpringApplicationRunListener listener : this.listeners) {
            listener.environmentPrepared(environment);
        }
    }

    // 省略部分代码

}

SpringApplicationRunListener interface is shown below:

/**
 * SpringApplicationRunListener是SpringApplication运行阶段的侦听器。
 */
public interface SpringApplicationRunListener {

	/**
	 * 在首次启动run方法时立即调用。 可用于非常早的初始化。
	 */
	default void starting() {
	}

	/**
	 * 在环境准备好、ApplicationContext创建之前调用。
	 */
	default void environmentPrepared(ConfigurableEnvironment environment) {
	}

	/**
	 * ApplicationContext已创建并准备好,但是在加载源之前。
	 */
	default void contextPrepared(ConfigurableApplicationContext context) {
	}

	/**
	 * 应用程序上下文已加载,但尚未刷新。
	 */
	default void contextLoaded(ConfigurableApplicationContext context) {
	}

	/**
	 * 上下文已刷新,应用程序已启动,CommandLineRunners和ApplicationRunner尚未被调用。
	 */
	default void started(ConfigurableApplicationContext context) {
	}

	/**
	 * 在run方法完成之前,当刷新应用程序上下文并且已调用所有CommandLineRunners和ApplicationRunners
	 */
	default void running(ConfigurableApplicationContext context) {
	}

	/**
	 * 运行应用程序时发生故障时调用
	 */
	default void failed(ConfigurableApplicationContext context, Throwable exception) {
	}

}

2, enters listeners.started (); source code

2.1 SpringApplicationRunListeners # started into the first method

// 源码位置 org.springframework.boot.SpringApplicationRunListeners#started
void started(ConfigurableApplicationContext context) {
    for (SpringApplicationRunListener listener : this.listeners) {
        // 调用SpringApplicationRunListener实现类的同名方法
        listener.started(context);
    }
}

2.2 listener.started(context); 分析

listener是EventPublishingRunListener。

/**
 * EventPublishingRunListener是SpringApplicationRunListener接口的默认实现,用于发布事件。
 * 仅展示部分代码
 */
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {

    // 默认事件广播器,用于广播事件
    private final SimpleApplicationEventMulticaster initialMulticaster;

    @Override
    public int getOrder() {
        return 0;
    }

    // 省略部分代码

    // 使用SimpleApplicationEventMulticaster#multicastEvent()广播ApplicationStartedEvent事件
    @Override
    public void started(ConfigurableApplicationContext context) {
        context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
    }
    
    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {
        this.initialMulticaster
                .multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
    }

}

3、context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));   源码

// 源码位置 org.springframework.context.support.AbstractApplicationContext.publishEvent(java.lang.Object, org.springframework.core.ResolvableType)
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
    /**
     * 主要代码:
     * getApplicationEventMulticaster()返回的依旧是SimpleApplicationEventMulticaster实例
     * multicastEvent(applicationEvent, eventType);广播事件
     */
    getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}

4, the role of SimpleApplicationEventMulticaster # multicastEvent () is a broadcast event.

// 源码位置 org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType)
// 将的应用程序事件广播给对此事件感兴趣的侦听器
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    // 重点代码1:根据event创建ResolvableType
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    Executor executor = getTaskExecutor();
    /**
     * 重点代码2:getApplicationListeners(event, type)
     * 返回监听了当前event事件的监听器,不监听当前事件的监听器被排除,不会返回
     * event:要广播的事件
     * eventType:事件类型
     */
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        // 若设置了线程池,使用线程调用监听器
        if (executor != null) {
            executor.execute(() -> invokeListener(listener, event));
        }
        else {
            // 重点代码3:没设置线程池,使用当前线程调用监听器。默认没设置线程池
            invokeListener(listener, event);
        }
    }
}

4.1 ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));   通过event创建ResolvableType。

4.2 getApplicationListeners (event, type) Returns the current listener event monitor events, does not listen to the current event listener is excluded, it will not return. This is a key way.

Enter getApplicationListeners (event, type) in debug, you will enter into AbstractApplicationEventMulticaster # supportsEvent () in

// 源码位置 org.springframework.context.event.AbstractApplicationEventMulticaster#supportsEvent(org.springframework.context.ApplicationListener<?>, org.springframework.core.ResolvableType, java.lang.Class<?>)
protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
    // 如果监听器是GenericApplicationListener的实现类则返回监听器本身,否则创建GenericApplicationListenerAdapter
    GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
            (GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
    /**
     * 通过supportsEventType和supportsSourceType判断监听器是否监听了当前事件
     * supportsSourceType默认返回true
     */
    return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}

Create our own Dlistener achieve GenericApplicationListener interface, and rewrite the supportsEventType () method, listening ApplicationStartingEvent, ApplicationStartedEvent event.

Alistener, Blistener did not realize GenericApplicationListener. And system initialization is the same, Clistener called by DelegatingApplicationListener, DelegatingApplicationListener did not realize GenericApplicationListener. Thus created GenericApplicationListenerAdapter instance, then execute (smartListener.supportsEventType (eventType) && smartListener.supportsSourceType (sourceType)); Analyzing

4.2.1 new GenericApplicationListenerAdapter (listener)); Source Analysis

// 源码位置 org.springframework.context.event.GenericApplicationListenerAdapter#GenericApplicationListenerAdapter
public GenericApplicationListenerAdapter(ApplicationListener<?> delegate) {
    // 将监听器赋值给delegate属性
    this.delegate = (ApplicationListener<ApplicationEvent>) delegate;
    /**
     * 获取监听器监听的事件类型。
     * 例如:this.delegate = Alistener
     *      this.declaredEventType就等于ApplicationStartedEvent
     */
    this.declaredEventType = resolveDeclaredEventType(this.delegate);
}

4.2.2 GenericApplicationListenerAdapter # supportsEventType () source code analysis

    // 源码位置 org.springframework.context.event.GenericApplicationListenerAdapter.supportsEventType(org.springframework.core.ResolvableType)
    @Override
    @SuppressWarnings("unchecked")
    public boolean supportsEventType(ResolvableType eventType) {
        if (this.delegate instanceof SmartApplicationListener) {
            Class<? extends ApplicationEvent> eventClass = (Class<? extends ApplicationEvent>) eventType.resolve();
            return (eventClass != null && ((SmartApplicationListener) this.delegate).supportsEventType(eventClass));
        }
        else {
            /**
             * 主要代码是 this.declaredEventType.isAssignableFrom(eventType))
             * 当监听器是Alistener、Blistener时:
             *    this.declaredEventType是ApplicationStartedEvent,eventType也是ApplicationStartedEvent,返回true
             * 当监听器是DelegatingApplicationListener时:
             *    this.declaredEventType是ApplicationEvent,eventType是ApplicationStartedEvent,
             *    ApplicationEvent是ApplicationStartedEvent的父类,this.declaredEventType.isAssignableFrom(eventType)也返回true
             */
            return (this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType));
        }
    }

In this project getApplicationListeners (event, type) returns the listener will contain Alistener, Blistener, Dlistener, DelegatingApplicationListener. DelegatingApplicationListener calls Clistener.

4.3 monitor the event event listener by getApplicationListeners (event, type) returns, the next step is to call the listener onApplicationEvent (event) method.

 invokeListener(listener, event); 源码

// 源码位置 org.springframework.context.event.SimpleApplicationEventMulticaster#invokeListener
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
    // 主要代码,调用监听器
    doInvokeListener(listener, event);
}

4.3.1 doInvokeListener(listener, event); 源码

// 源码位置 org.springframework.context.event.SimpleApplicationEventMulticaster#doInvokeListener
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
    // 主要代码,执行监听器的onApplicationEvent(E event);方法
    listener.onApplicationEvent(event);
}

 

 

Published 51 original articles · won praise 14 · views 40000 +

Guess you like

Origin blog.csdn.net/u010606397/article/details/105325189