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

目录

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<SpringBootExceptionReporter> 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<SpringApplicationRunListener> listeners;

    SpringApplicationRunListeners(Log log,
            Collection<? extends SpringApplicationRunListener> 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<ListenerCacheKey, ListenerRetriever> 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<ApplicationListener<?>> 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<ApplicationListener<?>> 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<String, String> SYSTEMS;

    static {
        Map<String, String> 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<SpringApplicationEvent> {
        
    //系统属性用来配置是够需要忽略预加载
    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<ApplicationEvent>, 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<ApplicationListener<ApplicationEvent>> delegates = getListeners(
                    ((ApplicationEnvironmentPreparedEvent) event).getEnvironment());
            if (delegates.isEmpty()) {
                return;
            }
            this.multicaster = new SimpleApplicationEventMulticaster();
            for (ApplicationListener<ApplicationEvent> listener : delegates) {
                this.multicaster.addApplicationListener(listener);
            }
        }
        if (this.multicaster != null) {
            //再次发送事件
            this.multicaster.multicastEvent(event);
        }
    }
    
    //生成并返回Listener
    private List<ApplicationListener<ApplicationEvent>> getListeners(
            ConfigurableEnvironment environment) {
        if (environment == null) {
            return Collections.emptyList();
        }
        //获取属性名称对应的事件监听器名称
        String classNames = environment.getProperty(PROPERTY_NAME);
        List<ApplicationListener<ApplicationEvent>> 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<ApplicationEvent>) 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<ApplicationStartingEvent> {
    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配合工作的版本
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值