理解Spring Application

我们在创建一个Spring boot应用的时候,通常都是使用SpringApplication或者SpringApplicationBuilder API,通过执行run方法进行启动Spring Boot应用;我们可以将整体的生命周期总结为以下几个阶段:

SpringApplication的初始化阶段

SpringApplication的运行阶段

SpringApplication的结束阶段

Spring Boot应用的退出

大致结构如下:

以上几个阶段又有细化的步骤,我们一起来分析下源代码进行查看:

1 初始化阶段

1.1 SpringApplication构造阶段

我们启动项目一般都是通过SpringApplicationBuilder进行初始化SpringApplication或者使用SpringApplication调用静态方法进行初始化启动项目,代码如下所示:

public class SpringBootApplicationBootstrap {

    public static void main(String[] args) {
        new SpringApplicationBuilder(MultipleSpringBootEventListener.class)
                .web(WebApplicationType.NONE)
                .run(args);
    }
}
public class SpringBootApplicationBootstrap {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootApplicationBootstrap.class, args);
     }

}

两种方式最终都是在SpringApplication的构造方法中进行初始化操作,源码如下:

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.sources = new LinkedHashSet();
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.addConversionService = true;
        this.headless = true;
        this.registerShutdownHook = true;
        this.additionalProfiles = new HashSet();
        this.isCustomEnvironment = false;
        this.lazyInitialization = false;
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }

我们所关心的就是最后四行代码了;

 梳理整体的流程为:

1.1.1 判断应用类型

this.webApplicationType = WebApplicationType.deduceFromClasspath();

这个方法就是判断当前运行的应用是REACTIVE类型的还是SERVLET类型,或者是非Web应用;

1.1.2 加载ApplicationContextInitializer应用上下文初始化器

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
        ClassLoader classLoader = this.getClassLoader();
        Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }

通过跟踪源码,我们可以看到获取ApplicationContextInitializer实现类的方式,是使用的Spring的SPI机制,从spring.factories文件中获取配置的实现类名称列表,再通过调用SpringBoot新增的一个方法BeanUtils.instantiateClass(constructor, args)去创建实例,再进行排序操作(每一个实现类都实现了Ordered接口),最后将这些实现类实例保存在SpringApplication的initializers属性中;

ApplicationContextInitializer的作用,如下是官网的解释:

@FunctionalInterface
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext>

Callback interface for initializing a Spring ConfigurableApplicationContext prior to being refreshed.

Typically used within web applications that require some programmatic initialization of the application context. For example, registering property sources or activating profiles against the context's environment. See ContextLoader and FrameworkServlet support for declaring a "contextInitializerClasses" context-param and init-param, respectively.

我在网上查找到一个比较全面的解释,请参考:

ApplicationContextInitializer的实现与使用

1.1.3 加载ApplicationListener应用事件监听器

执行的流程和加载ApplicationContextInitializer方式流程一致;

1.1.4 获取主类(应用引导类)

将获取到的主类信息保存到mainApplicationClass属性中;

1.2 SpringApplication配置阶段

这个阶段介于1.1SpringApplication与2 SpringApplication运行阶段之间,其实就是在我们运行run方法之前,通过SpringApplication提供的公共方法,修改相关的配置信息,来达到我们期望的运行效果,例如:

public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplicationBuilder(MultipleSpringBootEventListener.class)
                .web(WebApplicationType.NONE)
                .bannerMode(Banner.Mode.OFF)
                .application();
        springApplication.getInitializers();
        springApplication.addListeners(new MultipleSpringBootEventListener());
        springApplication.setSources(new HashSet<>());
        springApplication.run(args);
    }

可以获取应用上下文初始化器,也可以添加自定义的应用上下文初始化器,添加事件监听器,添加配置源等信息;

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值