当前位置: 首页 > 最新文章 > 正文

Springboot流程(springboot详细讲解)

springboot启动过程中会用到事件发布机制。这里先事件发布说明一下。Spring中的事件发布机制。网上有一篇文章介绍得很详细,可以参考:https://www.cnblogs.com/takumicx/p/9972461.html但是在SpringBoot中用的是事件驱动机制,和Spring中的机制有一些区别。this.getSpringFactoriesInstances 这个方法不仅会

admin

springboot启动过程中会用到事件发布机制。这里先事件发布说明一下。Spring中的事件发布机制。网上有一篇文章介绍得很详细,可以参考:https://www.cnblogs.com/takumicx/p/9972461.html但是在SpringBoot中用的是事件驱动机制,和Spring中的机制有一些区别。this.getSpringFactoriesInstances 这个方法不仅会加载spring.factories中的类,还会进行实例化。而EventPublishingRunListener 只有一个构造器。> listener = var3.next(); / /添加事件发布器中 方法是在AbstractApplicationEventMulticaster中 会先排除代理类再进行添加 this.initialMulticaster.addApplicationListener; } }然后通过 SpringApplicationRunListeners的构造器,把这个EventPublishingRunListener 赋值给了全局变量 listeners。extends SpringApplicationRunListener> listeners, ApplicationStartup applicationStartup) { this.log = log; this.listeners = new ArrayList; this.applicationStartup = applicationStartup; } listeners.starting;发布事件根据事件找到匹配的监听器,执行。异步执行就丢到线程池中执行。同步的话就直接调用。

springboot启动过程中会用到事件发布机制。这里先事件发布说明一下。

Spring中的事件发布机制。网上有一篇文章介绍得很详细,可以参考:https://www.cnblogs.com/takumicx/p/9972461.html

但是在SpringBoot中用的是事件驱动机制,和Spring中的机制有一些区别。

一篇SpringBoot详细图解,坚持看完!带你真正搞懂启动流程分析

先来从图上整体看下springboot的启动流程。

一篇SpringBoot详细图解,坚持看完!带你真正搞懂启动流程分析

springboot的监听机制加载执行过程如下:

1:在SpringApplication.run方法中两步:

// 加载监听器SpringApplicationRunListeners listeners = this.getRunListeners(args);// 执行        listeners.starting(bootstrapContext, this.mainApplicationClass);
SpringApplicationRunListeners listeners = this.getRunListeners(args);
  private SpringApplicationRunListeners getRunListeners(String[] args) {        Class<?>[] types = new Class[]{SpringApplication.class, String[].class};        // 从spring.factories中加载key为 SpringApplicationRunListener.class对应的value值  并封装成返回的这个类实例  注意这个spring.factoies是在spring-boot.jar里面的        return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args), this.applicationStartup);    }
一篇SpringBoot详细图解,坚持看完!带你真正搞懂启动流程分析

加载的就一个 EventPublishingRunListener。

this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args)  这个方法不仅会加载spring.factories中的类,还会进行实例化。而EventPublishingRunListener 只有一个构造器。
public EventPublishingRunListener(SpringApplication application, String[] args) {        this.application = application;        this.args = args;       // 直接new了一个事件发布器        this.initialMulticaster = new SimpleApplicationEventMulticaster();        // 这里取的就是 上面spring.factories中加载出来的ApplicationListener 监听器        Iterator var3 = application.getListeners().iterator();        while(var3.hasNext()) {            ApplicationListener<?> listener = (ApplicationListener)var3.next();          / /添加事件发布器中  方法是在AbstractApplicationEventMulticaster中  会先排除代理类再进行添加            this.initialMulticaster.addApplicationListener(listener);        }    }
一篇SpringBoot详细图解,坚持看完!带你真正搞懂启动流程分析

然后通过 SpringApplicationRunListeners的构造器,把这个EventPublishingRunListener 赋值给了全局变量 listeners。

 SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners, ApplicationStartup applicationStartup) {        this.log = log;        this.listeners = new ArrayList(listeners);        this.applicationStartup = applicationStartup;    }

 listeners.starting(bootstrapContext, this.mainApplicationClass);发布事件
一篇SpringBoot详细图解,坚持看完!带你真正搞懂启动流程分析

根据事件找到匹配的监听器,执行。异步执行就丢到线程池中执行。同步的话就直接调用。

一篇SpringBoot详细图解,坚持看完!带你真正搞懂启动流程分析

一篇SpringBoot详细图解,坚持看完!带你真正搞懂启动流程分析



2:在SpringApplication.run方法中下一步:准备环境

ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);这里面又发布了一个环境准备的事件。
一篇SpringBoot详细图解,坚持看完!带你真正搞懂启动流程分析

一篇SpringBoot详细图解,坚持看完!带你真正搞懂启动流程分析

一篇SpringBoot详细图解,坚持看完!带你真正搞懂启动流程分析

这里发布了一个 ApplicationEnvironmentPreparedEvent 事件,这个事件对应的监听器 ConfigFileApplicationListener.

一篇SpringBoot详细图解,坚持看完!带你真正搞懂启动流程分析

List<EnvironmentPostProcessor> loadPostProcessors() {       // 加载一些环境处理的后置处理器        return SpringFactoriesLoader.loadFactories(EnvironmentPostProcessor.class, this.getClass().getClassLoader());    }
postProcessor.postProcessEnvironment(event.getEnvironment(), event.getSpringApplication()); 中最后会调用到加载配置文件的逻辑。

但是spring中的监听器监听不到springboot中的事件。

3:创建容器 context = this.createApplicationContext();

根据不同的类型,创建不同的容器

一篇SpringBoot详细图解,坚持看完!带你真正搞懂启动流程分析

4:准备上下文 this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);

 private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {        // 把environment设置到上下文里面        context.setEnvironment(environment);        this.postProcessApplicationContext(context);        // 调用初始化的方法        this.applyInitializers(context);       // 发布一个ApplicationContextInitializedEvent 事件         listeners.contextPrepared(context);        if (this.logStartupInfo) {            this.logStartupInfo(context.getParent() == null);            this.logStartupProfileInfo(context);        }        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();        beanFactory.registerSingleton("springApplicationArguments", applicationArguments);        if (printedBanner != null) {            beanFactory.registerSingleton("springBootBanner", printedBanner);        }        if (beanFactory instanceof DefaultListableBeanFactory) {            ((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);        }        if (this.lazyInitialization) {            context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());        }        Set<Object> sources = this.getAllSources();        Assert.notEmpty(sources, "Sources must not be empty");        this.load(context, sources.toArray(new Object[0]));        // 发布一个准备完成的事件, 在这一步  会把springboot 中的监听器都放入到spring容器context中        listeners.contextLoaded(context);    }
this.applyInitializers(context);
    protected void applyInitializers(ConfigurableApplicationContext context) {        // 这里获取调用的就是  SpringApplication构造函数执行时 加载的spring.factoies中 ApplicationContextInitializer        for (ApplicationContextInitializer initializer : getInitializers()) {            Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),                    ApplicationContextInitializer.class);            Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");            initializer.initialize(context);        }    }

注意一点,如果是我们自定义的监听器,如果是监听的这些启动过程中的事件,需要把监听器放到spring.factories中或者yml文件中才会生效,如果是@Component放到spring 容器中是不会生效的,因为到这里spring容器还没创建好。

这一步把springboot中的监听器都加入到spring容器中,在这一步之后,springboot中的监听器就能监听spring容器中的事件了。

但是spring中的监听器监听不到springboot中的事件。

public void contextLoaded(ConfigurableApplicationContext context) {        for (ApplicationListener<?> listener : this.application.getListeners()) {            if (listener instanceof ApplicationContextAware) {                ((ApplicationContextAware) listener).setApplicationContext(context);            }            context.addApplicationListener(listener);        }        this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));    }

5:刷新上下文 refreshContext(context);

6: afterRefresh(context, applicationArguments); 这是一个空方法,可以用于扩展,重写这个方法。

7: listeners.started(context); springboot启动后的事件,这个还没有对应的监听器,可以用于扩展,实现一个监听器监听这个事件做处理。

public void started(ConfigurableApplicationContext context) {        context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));        AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);    }

8: listeners.running(context); 也是可以扩展的

    public void running(ConfigurableApplicationContext context) {        context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));        AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);    }

通过上面的流程,可以知道,springboot中事件发布器就是 EventPublishingRunListener,它里面定义了一系列事件发布的方法。然后靠 spring中的SimpleApplicationEventMulticaster 发布事件。


ationContext context) {        for (ApplicationListener<?> listener : this.application.getListeners()) {            if (listener instanceof ApplicationContextAware) {                ((ApplicationContextAware) listener).setApplicationContext(context);            }            context.addApplicationListener(listener);        }        this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));    }

5:刷新上下文 refreshContext(context);

6: afterRefresh(context, applicationArguments); 这是一个空方法,可以用于扩展,重写这个方法。

7: listeners.started(context); springboot启动后的事件,这个还没有对应的监听器,可以用于扩展,实现一个监听器监听这个事件做处理。

public void started(ConfigurableApplicationContext context) {        context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));        AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);    }

8: listeners.running(context); 也是可以扩展的

    public void running(ConfigurableApplicationContext context) {        context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));        AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);    }

通过上面的流程,可以知道,springboot中事件发布器就是 EventPublishingRunListener,它里面定义了一系列事件发布的方法。然后靠 spring中的SimpleApplicationEventMulticaster 发布事件。


上一篇: 中国人 4 年没换手机了?网友:安卓太拉了... 下一篇:各国徽章 小方寸背后有大讲究
返回顶部