SpringApplication run方法解析:SpringApplicationRunListeners(二)

前言

在spring boot 源码解析2-SpringApplication初始化 中我们分析了SpringApplication的初始化.接下来我们继续分析SpringApplication的run⽅法。


解析

1. SpringApplication#run⽅法的代码如下:

public ConfigurableApplicationContext run(String... args) {
        //计时工具
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        FailureAnalyzers analyzers = null;
        this.configureHeadlessProperty();
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting();

        try {
            // 创建⼀个DefaultApplicationArguments对象,它持有着args参数,就是main函数传进来的参数
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            Banner printedBanner = this.printBanner(environment);
            // 创建SpringBoot上下⽂
            context = this.createApplicationContext();
            new FailureAnalyzers(context);
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            listeners.finished(context, (Throwable)null);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);
            throw new IllegalStateException(var9);
        }
    }

该⽅法做了13件事:
1. 初始化StopWatch,调⽤其start⽅法开始计时.
2. 调⽤configureHeadlessProperty设置系统属性java.awt.headless,这⾥设置为true,表示运⾏在服务器端,在没有显示器和⿏标键盘的模式下⼯作,模拟输⼊输出设备功能
3. 调⽤SpringApplicationRunListeners#starting
4. 创建⼀个DefaultApplicationArguments对象,它持有着args参数,就是main函数传进来的参数.调⽤prepareEnvironment⽅法.
5. 打印banner
6. 创建SpringBoot上下⽂
7. 初始化FailureAnalyzers
8. 调⽤prepareContext
9. 调⽤AbstractApplicationContext#refresh⽅法,并注册钩⼦
10. 在容器完成刷新后,依次调⽤注册的Runners
11. 调⽤SpringApplicationRunListeners#finished
12. 停⽌计时
13. 初始化过程中出现异常时调⽤handleRunFailure进⾏处理,然后抛出IllegalStateException异常。
 

2. run⽅法中第1步.代码如下:

StopWatch stopWatch = new StopWatch();
stopWatch.start();

在StopWatch初始化时,设置id为"".代码如下:

public StopWatch() {
    this("");
}
public StopWatch(String id) {
    this.id = id;
}

 start⽅法代码如下:

public void start() throws IllegalStateException {
        this.start("");
    }

 public void start(String taskName) throws IllegalStateException {
        if (this.running) {
            throw new IllegalStateException("Can't start StopWatch: it's already running");
        } else {
            this.running = true;
            this.currentTaskName = taskName;
            this.startTimeMillis = System.currentTimeMillis();
        }
 }

在start⽅法中,⾸先判断当前状态是否为running.如果是的话,抛出异常.如果不是的话,将running设置为true.currentTaskName设置为"",startTimeMillis为当前时间。

在run⽅法中的第12步中,调⽤了StopWatch#stop⽅法.停⽌计时.代码如下:

public void stop() throws IllegalStateException {
        if (!this.running) {
            throw new IllegalStateException("Can't stop StopWatch: it's not running");
        } else {
            long lastTime = System.currentTimeMillis() - this.startTimeMillis;
            this.totalTimeMillis += lastTime;
            this.lastTaskInfo = new StopWatch.TaskInfo(this.currentTaskName, lastTime);
            if (this.keepTaskList) {
                this.taskList.add(this.lastTaskInfo);
            }

            ++this.taskCount;
            this.running = false;
            this.currentTaskName = null;
        }
    }

3. run⽅法第2步--> 调⽤configureHeadlessProperty⽅法.设置系统属性java.awt.headless,这⾥设置为true,表示运⾏在服务器端,在没有显示器和⿏标键盘的模式下⼯作,模拟输⼊输出设备功能.该⽅法如下:

private void configureHeadlessProperty() {
        System.setProperty("java.awt.headless", System.getProperty("java.awt.headless", Boolean.toString(this.headless)));
    }

4. run⽅法第3步,代码如下:

SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();

    getRunListeners⽅法如下:

private SpringApplicationRunListeners getRunListeners(String[] args) {
        Class<?>[] types = new Class[]{SpringApplication.class, String[].class};
        return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
    }

    还是同样的味道.通过调⽤getSpringFactoriesInstances加载SpringApplicationRunListener.然后初始化SpringApplicationRunListeners。
 对应当前场景来说,org.springframework.boot.SpringApplicationRunListener只有⼀个(配置在META-INF/spring.factories中).如下:

org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

在初始化EventPublishingRunListener时,会将SpringApplication中的Listeners添加到EventPublishingRunListener中的initialMulticaster.代码如下:

public EventPublishingRunListener(SpringApplication application, String[] args) {
    this.application = application;
    this.args = args;
    this.initialMulticaster = new SimpleApplicationEventMulticaster();
    for (ApplicationListener<?> listener : application.getListeners()) {
        this.initialMulticaster.addApplicationListener(listener);
    }
}

也就是在META-INF/spring.factories中配置的org.springframework.context.ApplicationListener.关于这点,我们在上节课中讲过了。

那么在什么时候调用 EventPublishingRunListener(SpringApplication application, String[] args),这个构造方法呢?

在调用createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names)方法中调用:

T instance = BeanUtils.instantiateClass(constructor, args);

 

在进入Listeners之前先介绍下对应的类和作用:

ApplicationListener:事件监听者,观察者;
ApplicationEvent:Spring 事件,记录事件源、时间和数据;
ApplicationEventPublisher:发布事件;

参考文章:原理洞察|Spring 事件通知机制解析

 

然后调⽤SpringApplicationRunListeners#starting⽅法.代码如下:

public void starting() {
        Iterator var1 = this.listeners.iterator();

        while(var1.hasNext()) {
            SpringApplicationRunListener listener = (SpringApplicationRunListener)var1.next();
            listener.starting();
        }

    }

由于只有⼀个,因此会调⽤EventPublishingRunListener的starting⽅法.代码如下:

public void starting() {
    this.initialMulticaster
    .multicastEvent(new ApplicationStartedEvent(this.application, this.args));
}

接着调⽤SimpleApplicationEventMulticaster#multicastEvent.代码如下:

public void multicastEvent(ApplicationEvent event) {
        this.multicastEvent(event, this.resolveDefaultEventType(event));
    }

resolveDefaultEventType⽅法如下:

private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
        return ResolvableType.forInstance(event);
    }

 调⽤:

public static ResolvableType forInstance(Object instance) {
        Assert.notNull(instance, "Instance must not be null");
        if (instance instanceof ResolvableTypeProvider) {
            ResolvableType type = ((ResolvableTypeProvider)instance).getResolvableType();
            if (type != null) {
                return type;
            }
        }

        return forClass(instance.getClass());
    }

由于当前传⼊的ApplicationStartedEvent不是ResolvableTypeProvider的实例,因此最终会调⽤ResolvableType#forClass.代码如下:

public static ResolvableType forClass(Class<?> clazz) {
        return new ResolvableType(clazz);
    }

 直接初始化了ResolvableType.其构造器如下:

 private ResolvableType(Class<?> clazz) {
        this.resolved = clazz != null ? clazz : Object.class;
        this.type = this.resolved;
        this.typeProvider = null;
        this.variableResolver = null;
        this.componentType = null;
        this.hash = null;
    }

 实现回到SimpleApplicationEventMulticaster#multicastEvent中,此时会调用:

ublic void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
        ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
        Iterator var4 = this.getApplicationListeners(event, type).iterator();

        while(var4.hasNext()) {
            final ApplicationListener<?> listener = (ApplicationListener)var4.next();
            Executor executor = this.getTaskExecutor();
            if (executor != null) {
                executor.execute(new Runnable() {
                    public void run() {
                        SimpleApplicationEventMulticaster.this.invokeListener(listener, event);
                    }
                });
            } else {
                this.invokeListener(listener, event);
            }
        }

    }

 该⽅法调⽤getApplicationListeners获得ApplicationListener.然后调⽤SimpleApplicationEventMulticaster#invokeListener⽅法。

getApplicationListeners代码如下:
 

protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {
        Object source = event.getSource();
        Class<?> sourceType = source != null ? source.getClass() : null;
        AbstractApplicationEventMulticaster.ListenerCacheKey cacheKey = new AbstractApplicationEventMulticaster.ListenerCacheKey(eventType, sourceType);
        AbstractApplicationEventMulticaster.ListenerRetriever retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey);
        if (retriever != null) {
            return retriever.getApplicationListeners();
        } else if (this.beanClassLoader == null || ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader))) {
            synchronized(this.retrievalMutex) {
                retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey);
                if (retriever != null) {
                    return retriever.getApplicationListeners();
                } else {
                    retriever = new AbstractApplicationEventMulticaster.ListenerRetriever(true);
                    Collection<ApplicationListener<?>> listeners = this.retrieveApplicationListeners(eventType, sourceType, retriever);
                    this.retrieverCache.put(cacheKey, retriever);
                    return listeners;
                }
            }
        } else {
            return this.retrieveApplicationListeners(eventType, sourceType, (AbstractApplicationEventMulticaster.ListenerRetriever)null);
        }
    }

 该⽅法⾸先构建ListenerCacheKey,然后查询缓存中是否有的话,直接返回.否则调⽤retrieveApplicationListeners⽅法.如果
this.beanClassLoader == null || (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType,
this.beanClassLoader))) 为真的话,则调⽤retrieveApplicationListeners⽅法时会进⾏加锁.并将⽅法的返回值加⼊缓存.⼀般都会放⼊缓存的。

retrieveApplicationListeners⽅法,代码如下:
 

private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, Class<?> sourceType, AbstractApplicationEventMulticaster.ListenerRetriever retriever) {
        LinkedList<ApplicationListener<?>> allListeners = new LinkedList();
        LinkedHashSet listeners;
        LinkedHashSet listenerBeans;
        synchronized(this.retrievalMutex) {
            listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
            listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans);
        }

        Iterator var7 = listeners.iterator();

        while(var7.hasNext()) {
            ApplicationListener<?> listener = (ApplicationListener)var7.next();
            if (this.supportsEvent(listener, eventType, sourceType)) {
                if (retriever != null) {
                    retriever.applicationListeners.add(listener);
                }

                allListeners.add(listener);
            }
        }

        if (!listenerBeans.isEmpty()) {
            BeanFactory beanFactory = this.getBeanFactory();
            Iterator var15 = listenerBeans.iterator();

            while(var15.hasNext()) {
                String listenerBeanName = (String)var15.next();

                try {
                    Class<?> listenerType = beanFactory.getType(listenerBeanName);
                    if (listenerType == null || this.supportsEvent(listenerType, eventType)) {
                        ApplicationListener<?> listener = (ApplicationListener)beanFactory.getBean(listenerBeanName, ApplicationListener.class);
                        if (!allListeners.contains(listener) && this.supportsEvent(listener, eventType, sourceType)) {
                            if (retriever != null) {
                                retriever.applicationListenerBeans.add(listenerBeanName);
                            }

                            allListeners.add(listener);
                        }
                    }
                } catch (NoSuchBeanDefinitionException var13) {
                }
            }
        }

        AnnotationAwareOrderComparator.sort(allListeners);
        return allListeners;
    }

处理逻辑如下:
1. 初始化allListeners, listeners,listenerBeans,对于当前场景来说. listeners 中的元素如下:

org.springframework.boot.context.config.ConfigFileApplicationListener,
org.springframework.boot.context.config.AnsiOutputApplicationListener,
org.springframework.boot.logging.LoggingApplicationListener,
org.springframework.boot.logging.ClasspathLoggingApplicationListener,
org.springframework.boot.autoconfigure.BackgroundPreinitializer,
org.springframework.boot.context.config.DelegatingApplicationListener,
org.springframework.boot.builder.ParentContextCloserApplicationListener,
org.springframework.boot.ClearCachesApplicationListener,
org.springframework.boot.context.FileEncodingApplicationListener,
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener

listenerBeans中的元素为空.
2. 遍历listeners, listenerBeans 如果监听器是否⽀持指定的事件则加⼊到allListeners.
3. 排序

疑问: listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
标红处变量是什么时候设置进去的?

对于当前场景ApplicationStartedEvent⽀持的listeners如下:

疑问: listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
标红处变量是什么时候设置进去的?

 SimpleApplicationEventMulticaster#invokeListener⽅法如下:

protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
        ErrorHandler errorHandler = this.getErrorHandler();
        if (errorHandler != null) {
            try {
                this.doInvokeListener(listener, event);
            } catch (Throwable var5) {
                errorHandler.handleError(var5);
            }
        } else {
            this.doInvokeListener(listener, event);
        }

    }

 该⽅法主要调⽤doInvokeListener,当ErrorHandler不为null时,当调⽤doInvokeListener出现异常时,会交由ErrorHandler进⾏处理.对于当前, ErrorHandler为null。

那么ErrorHandler什么时候进⾏设置呢?
未完待续。。。

doInvokeListener代码如下:
 

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
        try {
            listener.onApplicationEvent(event);
        } catch (ClassCastException var6) {
            String msg = var6.getMessage();
            if (msg != null && !msg.startsWith(event.getClass().getName())) {
                throw var6;
            }

            Log logger = LogFactory.getLog(this.getClass());
            if (logger.isDebugEnabled()) {
                logger.debug("Non-matching event type for listener: " + listener, var6);
            }
        }

    }

 对于LoggingApplicationListener,会调⽤LoggingApplicationListener#onApplicationEvent⽅法.代码如下:

public void onApplicationEvent(ApplicationEvent event) {
		if (event instanceof ApplicationStartingEvent) {
			onApplicationStartingEvent((ApplicationStartingEvent) event);
		}
		else if (event instanceof ApplicationEnvironmentPreparedEvent) {
			onApplicationEnvironmentPreparedEvent(
					(ApplicationEnvironmentPreparedEvent) event);
		}
		else if (event instanceof ApplicationPreparedEvent) {
			onApplicationPreparedEvent((ApplicationPreparedEvent) event);
		}
		else if (event instanceof ContextClosedEvent && ((ContextClosedEvent) event)
				.getApplicationContext().getParent() == null) {
			onContextClosedEvent();
		}
		else if (event instanceof ApplicationFailedEvent) {
			onApplicationFailedEvent();
		}
	}

 接下来,LoggingApplicationListener#onApplicationStartingEvent⽅法.代码如下:

private void onApplicationStartingEvent(ApplicationStartingEvent event) {
		this.loggingSystem = LoggingSystem
				.get(event.getSpringApplication().getClassLoader());
		this.loggingSystem.beforeInitialize();
	}

 对于当前场景来说,loggingSystem为LogbackLoggingSystem.
对于BackgroundPreinitializer,DelegatingApplicationListener来说,没有做任何事。

对于LiquibaseServiceLocatorApplicationListener,代码如下:

public void onApplicationEvent(ApplicationStartingEvent event) {
		if (ClassUtils.isPresent("liquibase.servicelocator.ServiceLocator", null)) {
			new LiquibasePresent().replaceServiceLocator();
		}
	}

 对于场景来说,在项⽬的类路径下,不存在liquibase.servicelocator.ServiceLocator.
本⽂就到这⾥.剩下的后续分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值