Spring源码2:发布启动事件ApplicationStartingEvent

上篇回顾

上一篇初始化SpringApplication实例, 我们实例化了一个SpringApplication实例,整个流程共计4步

  1. 调用WebApplicationType.deduceFromClasspath方法, 获取Web类型
  2. 通过getSpringFactoriesInstances()方法, 调用SpringFactoriesLoader.loadFactoryNames, 首先加载META-INF/spring.factories配置的类名到缓存中, 之后实例化了ApplicationContextInitializer的子类列表, 赋值给SpringApplication的initializers列表
  3. 通过getSpringFactoriesInstances()方法, 调用SpringFactoriesLoader.loadFactoryNames,从SpringFactoriesLoader的缓存中获取并实例化ApplicationListener子类列表, 赋值SpringApplication的listeners列表
  4. 通过抛出一个RuntimeException, 遍历其堆栈信息, 获取到类名中包含main方法的类, 实例化这个类, 赋值给SpringApplication的mainApplicationClass对象

目录

1. 发布启动事件ApplicationStartingEvent
    1.1 SpringApplicationRunListeners源码
    1.2 EventPublishingRunListener源码
    1.3 SimpleApplicationEventMulticaster源码
2. 启动事件的监听器
    2.1 LoggingApplicationListener
    2.2 BackgroundPreinitializer
    2.3 DelegatingApplicationListener
    2.4 LiquibaseServiceLocatorApplicationListener
3. 总结

1. 发布启动事件ApplicationStartingEvent

调用getRunListeners()方法, 实例化一个SpringApplicationRunListeners对象, SpringApplicationRunListeners的构造参数通过getSpringFactoriesInstances()方法获得,这个方法在之前分析过了, 获取的一个EventPublishingRunListener对象, 所以调用的是EventPublishingRunListener#starting()方法

public class SpringApplication {
    //run方法
    public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection exceptionReporters = new ArrayList<>();
        configureHeadlessProperty();
        
        //本文分析的重点,发布启动事件ApplicationStartingEvent
        //获取SpringApplicationRunListener的子类listener
        SpringApplicationRunListeners listeners = getRunListeners(args);
        //执行其starting()方法
        listeners.starting();
        ....
    }
    
    //获取SpringApplicationRunListener的子类listener
    private SpringApplicationRunListeners getRunListeners(String[] args) {
        Class[] types = new Class[] { SpringApplication.class, String[].class };
        
        //调用getSpringFactoriesInstances方法
        //获取SpringApplicationRunListener的子类
        //子类只有一个,EventPublishingRunListener
        //实例化了一个SpringApplicationRunListeners对象
        return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
                SpringApplicationRunListener.class, types, this, args));
    }
}
1.1 SpringApplicationRunListeners源码

SpringApplicationRunListeners是一个比较重要的类, 之后的代码会经常调用这个方法, 内部封装了一个SpringApplicationRunListener的list, 方便以后扩展, 目前只有一个EventPublishingRunListener实例, 所以spring的事件都是由EventPublishingRunListener发布的

//SpringApplicationRunListeners部分源码
class SpringApplicationRunListeners {

    private final Log log;

    //SpringApplicationRunListener的子类对象列表
    //listener列表扩展点
    private final List listeners;

    SpringApplicationRunListeners(Log log,
            Collection listeners) {
        this.log = log;
        this.listeners = new ArrayList<>(listeners);
    }

    //发布启动事件
    public void starting() {
        for (SpringApplicationRunListener listener : this.listeners) {
            //目前调用EventPublishingRunListener#starting方法
            listener.starting();
        }
    }
    
    //其他事件都是相同的代码
    //....
}
1.2 EventPublishingRunListener源码

EventPublishingRunListener是springboot的事件广播器, 内部封装了一个SimpleApplicationEventMulticaster对象, 用来发布springboot加载过程中的各个事件

  • 事件源SpringApplication对象
  • 事件SpringApplicationEvent对象
  • 事件发布器是EventPublishingRunListener, 正在的事件发布器是其内部SimpleApplicationEventMulticaster成员变量
  • 事件监听器SpringApplication维护的listeners, 调用AbstractApplicationEventMulticaster#getApplicationListeners(ApplicationEvent, ResolvableType)筛选出支持ApplicationEvent的listeners
//EventPublishingRunListener部分源码
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {

    //SpringApplication对象
    private final SpringApplication application;

    //命令函参数
    private final String[] args;

    //事件广播器
    private final SimpleApplicationEventMulticaster initialMulticaster;

    public EventPublishingRunListener(SpringApplication application, String[] args) {
        this.application = application;
        this.args = args;
        this.initialMulticaster = new SimpleApplicationEventMulticaster();
        // 通过application.getListeners(),获取到Listener列表
        // ConfigFileApplicationListener
        // AnsiOutputApplicationListener
        // LoggingApplicationListener
        // ClasspathLoggingApplicationListener
        // BackgroundPreinitializer
        // DelegatingApplicationListener
        // ParentContextCloserApplicationListener
        // ClearCachesApplicationListener
        // FileEncodingApplicationListener
        // LiquibaseServiceLocatorApplicationListener
        for (ApplicationListener listener : application.getListeners()) {
            //将listener添加到事件广播器initialMulticaster
            this.initialMulticaster.addApplicationListener(listener);
        }
    }
    @Override
    public void starting() {
        // 广播器广播ApplicationStartingEvent事件
        this.initialMulticaster.multicastEvent(
                new ApplicationStartingEvent(this.application, this.args));
    }
    
    //其他事件发布都是相同的代码
    //...
}

1.3 SimpleApplicationEventMulticaster源码

springboot默认事件广播器, 有三个重要方法, 用于发布spring启动过程中的各个事件

  • addApplicationListener() 添加监听器listener
  • multicastEvent() 广播spring事件
  • invokeListener() 实现每个listener的onApplicationEvent()方法
父类AbstractApplicationEventMulticaster

封装了四个重要方法:

  • addApplicationListener添加listener
  • addApplicationListenerBean添加注入的listener bean名称
  • removeApplicationListener删除listener
  • removeApplicationListenerBean删除注入的listener bean名称
  • getApplicationListeners()先从缓存retrieverCache获取listener,如果缓存不存在, 封装数据放入缓存中, 增删listener的时候, 缓存retrieverCache会被清空
//抽象事件广播器
public abstract class AbstractApplicationEventMulticaster
        implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
    
    //监听器遍历器
    //成员变量applicationListeners Set维护了application中包含的listeners,
    //成员变量applicationListenerBeans Set维护了注入的listener bean名称
    private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);

    //调用getApplicationListeners()方法之后
    //缓存spring事件以及对应的listener列表
    final Map retrieverCache = new ConcurrentHashMap<>(64);

    private Object retrievalMutex = this.defaultRetriever;

    @Override
    public void addApplicationListener(ApplicationListener listener) {
        synchronized (this.retrievalMutex) {
            //监听器已经被加载过,
            //先执行删除操作,防止重复执行
            Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
            if (singletonTarget instanceof ApplicationListener) {
                this.defaultRetriever.applicationListeners.remove(singletonTarget);
            }
            this.defaultRetriever.applicationListeners.add(listener);
            //清空缓存
            this.retrieverCache.clear();
        }
    }
    
    /**
     * 获取支持监听event的listener
     * 这里使用了单例模式
     */
    protected Collection> getApplicationListeners(
            ApplicationEvent event, ResolvableType eventType) {

        Object source = event.getSource();
        Class sourceType = (source != null ? source.getClass() : null);
        ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

        //尝试从ConcurrentHashMap缓存中取出listener列表
        ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
        if (retriever != null) {
            return retriever.getApplicationListeners();
        }

        if (this.beanClassLoader == null ||
                (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
                        (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
            //双重检查锁定
            //当多线程访问的时候,
            //之前retriever多个线程否返回null,
            //此时锁住this.retrievalMutex
            //防止多次实例化
            synchronized (this.retrievalMutex) {
                //再尝试从cache中获取
                retriever = this.retrieverCache.get(cacheKey);
                if (retriever != null) {
                    return retriever.getApplicationListeners();
                }
                //生成Key和Value放入缓存中
                retriever = new ListenerRetriever(true);
                Collection> listeners =
                        retrieveApplicationListeners(eventType, sourceType, retriever);
                this.retrieverCache.put(cacheKey, retriever);
                return listeners;
            }
        }
        else {
            //没有缓存ListenerRetriever,那么就不需要同步
            return retrieveApplicationListeners(eventType, sourceType, null);
        }
    }
    
    //retrieveApplicationListeners方法中
    //调用了supportsEvent方法
    //supportsEvent使用了适配器模式
    protected boolean supportsEvent(
            ApplicationListener listener, ResolvableType eventType, @Nullable Class sourceType) {
        GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
                (GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
        return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
    }
}
SimpleApplicationEventMulticaster

广播事件, 然后实现每个listener的onApplicationEvent()方法

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

    @Nullable
    private Executor taskExecutor;

    @Nullable
    private ErrorHandler errorHandler;

    /**
     * 构造函数
     * taskExecutor和errorHandler都是null
     */
    public SimpleApplicationEventMulticaster() {
    }
    
    /**
     * 广播事件
     * @param event 事件
     * @param eventType 事件类型
     */
    @Override
    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        //调用父类getApplicationListeners方法
        //遍历所有支持ApplicationStartingEvent事件的监听器
        //LoggingApplicationListener
        //BackgroundPreinitializer
        //DelegatingApplicationListener
        //LiquibaseServiceLocatorApplicationListener
        for (final ApplicationListener listener : getApplicationListeners(event, type)) {
            //此时的executor为null
            Executor executor = getTaskExecutor();
            if (executor != null) {
                executor.execute(() -> invokeListener(listener, event));
            }
            else {
                //调用listener
                invokeListener(listener, event);
            }
        }
    }
    
    /**
     * 具体调用监听器的方法
     * @param listener 监听器
     * @param event 事件
     */
    private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
        try {
            //调用listener的onApplicationEvent方法
            listener.onApplicationEvent(event);
        }
        catch (ClassCastException ex) {
            String msg = ex.getMessage();
            if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
                Log logger = LogFactory.getLog(getClass());
                if (logger.isDebugEnabled()) {
                    logger.debug("Non-matching event type for listener: " + listener, ex);
                }
            }
            else {
                throw ex;
            }
        }
    }
}

2. 启动事件的监听器

对Spring启动事件ApplicationStartingEvent感兴趣的Listener:

  • LoggingApplicationListener 日志监听器,配置日志
  • BackgroundPreinitializer 后台初始化器, 多线程加载耗时任务
  • DelegatingApplicationListener 代理监听器, 继续发布事件
  • LiquibaseServiceLocatorApplicationListener 将liquibas替换为可以和spring配合工作的版本
2.1 LoggingApplicationListener部分代码

获取当前应用使用的日志系统, 初始化loggingSystem, 调用loggingSystem的beforeInitialize方法, 开启日志的准备工作

public class LoggingApplicationListener implements GenericApplicationListener {
    //处理starting事件
    if (event instanceof ApplicationStartingEvent) {
            onApplicationStartingEvent((ApplicationStartingEvent) event);
        }
    }
    
    //日志系统准备工作
    private void onApplicationStartingEvent(ApplicationStartingEvent event) {
        //1.获取模块使用的日志系统
        this.loggingSystem = LoggingSystem
                .get(event.getSpringApplication().getClassLoader());
        //2.日志系统准备工作
        //调用的是LogbackLoggingSystem#beforeInitialize
        this.loggingSystem.beforeInitialize();
    }
}
LoggingSystem

spring支持logback, Log4j, JDK logging, 有两个重要方法

  • get() 获取应用使用的日志系统
  • beforeInitialize()获取

springboot默认使用logback, 也就是LogbackLoggingSystem

/**
 *日志系统的父类
 */
public abstract class LoggingSystem {

    public static final String SYSTEM_PROPERTY = LoggingSystem.class.getName();
    
    //Spring支持的几种日志系统
    private static final Map SYSTEMS;

    static {
        Map systems = new LinkedHashMap<>();
        //1.logback
        systems.put("ch.qos.logback.core.Appender",
                "org.springframework.boot.logging.logback.LogbackLoggingSystem");
        //2.Log4j
        systems.put("org.apache.logging.log4j.core.impl.Log4jContextFactory",
                "org.springframework.boot.logging.log4j2.Log4J2LoggingSystem");
        //3.JDK logging
        systems.put("java.util.logging.LogManager",
                "org.springframework.boot.logging.java.JavaLoggingSystem");
        SYSTEMS = Collections.unmodifiableMap(systems);
    }

    /**
     * 判断并返回模块使用的日志系统
     * 我们应用使用的是logback
     * @param classLoader 加载SpringApplication的classloader
     */
    public static LoggingSystem get(ClassLoader classLoader) {
        String loggingSystem = System.getProperty(SYSTEM_PROPERTY);
        if (StringUtils.hasLength(loggingSystem)) {
            if (NONE.equals(loggingSystem)) {
                return new NoOpLoggingSystem();
            }
            return get(classLoader, loggingSystem);
        }
        //使用加载SpringApplication的classloader去加载支持的日志
        //如果能加载一个或者多个,返回第一个
        //否则就抛出异常
        return SYSTEMS.entrySet().stream()
                .filter((entry) -> ClassUtils.isPresent(entry.getKey(), classLoader))
                .map((entry) -> get(classLoader, entry.getValue())).findFirst()
                .orElseThrow(() -> new IllegalStateException(
                        "No suitable logging system located"));
    }
}

/**
 * logback日志系统
 * 继承了Sfl4j日志系统
 */
public class LogbackLoggingSystem extends Slf4JLoggingSystem {
    @Override
    public void beforeInitialize() {
        //获取LoggerContext
        LoggerContext loggerContext = getLoggerContext();
        //如果logger已经被初始化,name直接返回
        if (isAlreadyInitialized(loggerContext)) {
            return;
        }
        //调用父类的beforeInitialize方法
        //默认使用debug模式
        super.beforeInitialize();
        loggerContext.getTurboFilterList().add(FILTER);
    }
}

2.2 BackgroundPreinitializer

Spring会在项目启动的时候,默认开启线程加载一些耗时的任务,这样可以加快启动速度

@Order(LoggingApplicationListener.DEFAULT_ORDER + 1)
public class BackgroundPreinitializer
        implements ApplicationListener {
        
    //系统属性用来配置是够需要忽略预加载
    public static final String IGNORE_BACKGROUNDPREINITIALIZER_PROPERTY_NAME = "spring.backgroundpreinitializer.ignore";
    
    //预加载是否执行,启动原子布尔类型,默认为false
    private static final AtomicBoolean preinitializationStarted = new AtomicBoolean(
            false);

    //同步工具
    private static final CountDownLatch preinitializationComplete = new CountDownLatch(1);
}
2.3 DelegatingApplicationListener

扩展点, 可以继续广播事件, 查找属性context.listener.classes对应的listener名称列表, 实例化代理监听器, 继续广播事件, 当前应用中没有做任何操作

public class DelegatingApplicationListener
        implements ApplicationListener, Ordered {
        
    private static final String PROPERTY_NAME = "context.listener.classes";
            
    //默认为null
    private SimpleApplicationEventMulticaster multicaster;

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ApplicationEnvironmentPreparedEvent) {
            //监听到EnvironmentPreparedEvent事件
            List> delegates = getListeners(
                    ((ApplicationEnvironmentPreparedEvent) event).getEnvironment());
            if (delegates.isEmpty()) {
                return;
            }
            this.multicaster = new SimpleApplicationEventMulticaster();
            for (ApplicationListener listener : delegates) {
                this.multicaster.addApplicationListener(listener);
            }
        }
        if (this.multicaster != null) {
            //再次发送事件
            this.multicaster.multicastEvent(event);
        }
    }
    
    //生成并返回Listener
    private List> getListeners(
            ConfigurableEnvironment environment) {
        if (environment == null) {
            return Collections.emptyList();
        }
        //获取属性名称对应的事件监听器名称
        String classNames = environment.getProperty(PROPERTY_NAME);
        List> listeners = new ArrayList<>();
        if (StringUtils.hasLength(classNames)) {
            for (String className : StringUtils.commaDelimitedListToSet(classNames)) {
                try {
                    //反射生成对象
                    //放入监听器列表中
                    Class clazz = ClassUtils.forName(className,
                            ClassUtils.getDefaultClassLoader());
                    Assert.isAssignable(ApplicationListener.class, clazz, "class ["
                            + className + "] must implement ApplicationListener");
                    listeners.add((ApplicationListener) BeanUtils
                            .instantiateClass(clazz));
                }
                catch (Exception ex) {
                    throw new ApplicationContextException(
                            "Failed to load context listener class [" + className + "]",
                            ex);
                }
            }
        }
        AnnotationAwareOrderComparator.sort(listeners);
        return listeners;
    }
}
2.4 LiquibaseServiceLocatorApplicationListener
public class LiquibaseServiceLocatorApplicationListener
        implements ApplicationListener {
    if (ClassUtils.isPresent("liquibase.servicelocator.CustomResolverServiceLocator",
            event.getSpringApplication().getClassLoader())) {
        //将liquibas替换为 可以和spring配合工作的版本
        new LiquibasePresent().replaceServiceLocator();
    }
}

3. 总结

  1. 首先调用getRunListeners()方法, 获得一个SpringApplicationRunListeners对象,
    • SpringApplicationRunListeners的成员变量listeners是通过getSpringFactoriesInstances()方法获取的SpringApplicationRunListener子类列表
    • 当前只能获取EventPublishingRunListener,
  2. 调用SpringApplicationRunListeners对象的starting()方法, 发布SpringApplication启动事件
    • 内部EventPublishingRunListener#starting()方法
    • 最终调用SimpleApplicationEventMulticaster#multicastEvent()方法
    • 发布了ApplicationStartingEvent事件, 最后执行每个监听器的onApplicationEvent方法
  3. 对ApplicationStartingEvent事件感兴趣的监听器
    • LoggingApplicationListener 日志监听器,配置日志
    • BackgroundPreinitializer 后台初始化器, 多线程加载耗时任务
    • DelegatingApplicationListener 代理监听器, 继续发布事件
    • LiquibaseServiceLocatorApplicationListener 将liquibas替换为可以和spring配合工作的版本

下一篇

我们将会在下一篇封装命令行参数DefaultApplicationArguments, 继续研究springboot的启动流程

你可能感兴趣的:(Spring源码2:发布启动事件ApplicationStartingEvent)