SpringBoot源码解析(一)

今天我们来看看SpringBoot是如何启动的:

首先进入run方法

一顿点之后,我们会来到一个最终的run方法

 

 

public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		FailureAnalyzers analyzers = null;
		configureHeadlessProperty();
//重点 获取启动的监听器
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {

			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
// 第二步:根据SpringApplicationRunListeners以及参数来准备环境
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
//打印你的banner
			Banner printedBanner = printBanner(environment);
//第三步创建容器
			context = createApplicationContext();
			analyzers = new FailureAnalyzers(context);
 // 第四步:Spring容器前置处理
			prepareContext(context, environment, listeners, applicationArguments,
					printedBanner);
//第五步:刷新容器
			refreshContext(context);
//第六步后置处理
			afterRefresh(context, applicationArguments);
//第七步发送结束执行
			listeners.finished(context, null);
//计时结束
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass)
						.logStarted(getApplicationLog(), stopWatch);
			}
			return context;
		}
		catch (Throwable ex) {
			handleRunFailure(context, listeners, analyzers, ex);
			throw new IllegalStateException(ex);
		}
	}

我们先看第一步,getRunListeners() 传入的参数是你的启动类

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

可以看到他创建了一个SpringApplicationRunListeners ,我们看一下getSrpingFactoriesInstances的方法

	private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
			Class<?>[] parameterTypes, Object... args) {
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
		// Use names and ensure unique to protect against duplicates
		Set<String> names = new LinkedHashSet<String>(
				SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
				classLoader, args, names);
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}

这段代码我们要关注的是loadFactoryNames方法。看看里面写了什么。

    public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
        String factoryClassName = factoryClass.getName();

        try {
            Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
            ArrayList result = new ArrayList();

            while(urls.hasMoreElements()) {
                URL url = (URL)urls.nextElement();
                Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
                String factoryClassNames = properties.getProperty(factoryClassName);
                result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
            }

            return result;
        } catch (IOException var8) {
            throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8);
        }
    }

可以看到里面加载了META-INFO下面的spring.factories的文件。并通过传进来的SpringApplicationRunListener类找到对应的value值

 也就是这个EventPublishingRunListener.

getSpringFactoriesInstances中反射获取实例时会触发EventPublishingRunListener的构造函数,我们来看看EventPublishingRunListener的构造函数:

public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {

	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();
/将上面设置到SpringApplication的十一个监听器全部添加到SimpleApplicationEventMulticaster这个广播器中
		for (ApplicationListener<?> listener : application.getListeners()) {
			this.initialMulticaster.addApplicationListener(listener);
		}
	}

我们看到EventPublishingRunListener里面有一个广播器,EventPublishingRunListener 的构造方法将SpringApplication的十一个监听器全部添加到SimpleApplicationEventMulticaster这个广播器中,我们来看看是如何添加到广播器:

    public void addApplicationListener(ApplicationListener<?> listener) {
        synchronized(this.retrievalMutex) {
            this.defaultRetriever.applicationListeners.add(listener);
            this.retrieverCache.clear();
        }
    }

上述方法定义在SimpleApplicationEventMulticaster父类AbstractApplicationEventMulticaster中。关键代码为this.defaultRetriever.applicationListeners.add(listener);,这是一个内部类,用来保存所有的监听器。也就是在这一步,将spring.factories中的监听器传递到SimpleApplicationEventMulticaster中。我们现在知道EventPublishingRunListener中有一个广播器SimpleApplicationEventMulticaster,SimpleApplicationEventMulticaster广播器中又存放所有的监听器。

我们先来看看SpringApplicationRunListener这个接口

public interface SpringApplicationRunListener {

    // 在run()方法开始执行时,该方法就立即被调用,可用于在初始化最早期时做一些工作
    void starting();
    // 当environment构建完成,ApplicationContext创建之前,该方法被调用
    void environmentPrepared(ConfigurableEnvironment environment);
    // 当ApplicationContext构建完成时,该方法被调用
    void contextPrepared(ConfigurableApplicationContext context);
    // 在ApplicationContext完成加载,但没有被刷新前,该方法被调用
    void contextLoaded(ConfigurableApplicationContext context);
    // 在ApplicationContext刷新并启动后,CommandLineRunners和ApplicationRunner未被调用前,该方法被调用
    void started(ConfigurableApplicationContext context);
    // 在run()方法执行完成前该方法被调用
    void running(ConfigurableApplicationContext context);
    // 当应用运行出错时该方法被调用
    void failed(ConfigurableApplicationContext context, Throwable exception);
}

我们看一下啊starting的源码

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

这里又调用了SimpleApplicationEventMulticaster 广播其的multicastEvent,看看这个方法里面写了什么

    public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
        ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
        Iterator var4 = this.getApplicationListeners(event, type).iterator();
//通过事件类型ApplicationStartingEvent获取对应的监听器
        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);
            }
        }

    }

这里会根据事件类型ApplicationStartingEvent获取对应的监听器,在容器启动之后执行响应的动作,有如下4种监听器:

LoggingApplicationListener

BackgroudPreinitializer

DelegatingApplicationListener

LiquibaseServiceLocatorApplicationListener

因为我们的事件类型为ApplicationEvent,所以会执行onApplicationStartedEvent((ApplicationStartedEvent) event);。springBoot会在运行过程中的不同阶段,发送各种事件,来执行对应监听器的对应方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值