【JAVA使用笔记】——SpringBoot启动方式及远程调用(一)

下一篇:https://blog.csdn.net/NEU_LightBulb/article/details/102892314

一、RUN

1.Spring Boot 启动

        SpringBoot项目入口在@SpringBootApplication注解的类的main方法中。在main方法中有两种启动Spring项目方式,一种是简而明了的:

SpringApplication.run(YourApplication.class, args);

        和可以自定Banner、Web属性、记录器等配置项的:

new SpringApplicationBuilder(YourApplication.class)
                .web(... ...) //配置Web类型
                //... ... many many config
                .run(args);

        不管是哪一种,最后都会调用类SpringApplication中的run方法,方法内容及逻辑如下:

// 创建 StopWatch 对象,用于统计 run 方法启动时长。
StopWatch stopWatch = new StopWatch();

// 启动统计。
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();

// 配置 headless 属性。
configureHeadlessProperty();

// 获得 SpringApplicationRunListener 数组
SpringApplicationRunListeners listeners = getRunListeners(args);

// 启动监听,遍历 SpringApplicationRunListener 数组每个元素,并执行。
listeners.starting();

try {
	//创建 ApplicationArguments 对象
	ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
		
    // 加载属性配置,包括所有的配置属性application.properties 等
	ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
	configureIgnoreBeanInfo(environment);

	// 打印 Banner
	Banner printedBanner = printBanner(environment);
			
    // 创建容器
	context = createApplicationContext();

	// 异常报告器
	exceptionReporters = getSpringFactoriesInstances(
					SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);

	// 准备容器,组件对象之间进行关联
	prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			
    // 初始化容器
	refreshContext(context);
			
    // 初始化操作之后执行,默认实现为空。
	afterRefresh(context, applicationArguments);
			
    // 停止时长统计
	stopWatch.stop();

	// 打印启动日志
	if (this.logStartupInfo) {
		new StartupInfoLogger(this.mainApplicationClass)
						.logStarted(getApplicationLog(), stopWatch);
	}
			
    // 通知监听器:容器启动完成。
	listeners.started(context);

	// 调用 ApplicationRunner 和 CommandLineRunner 的运行方法。
	callRunners(context, applicationArguments);
}
catch (Throwable ex) {
	// 异常处理
	handleRunFailure(context, ex, exceptionReporters, listeners);
	throw new IllegalStateException(ex);
}

try {
	// 通知监听器:容器正在运行。
	listeners.running(context);
}
catch (Throwable ex) {
	// 异常处理
	handleRunFailure(context, ex, exceptionReporters, null);
	throw new IllegalStateException(ex);
}
return context;

        这里我们按顺序关注几个方法,第一个createApplicationContext,在这个方法中会根据你的Web类型设置返回对应的Context类型。可以在 SpringApplicationBuilder中用.web()设置,也可以在配置文件中加入spring.main.web-application-type。不同类型对应结果如下:

        SERVLET:org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext

        应用程序应作为基于servlet的Web应用程序运行,并应启动嵌入式servlet Web服务器。

        REACTIVE:org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext

        应用程序应作为响应式Web应用程序运行,并应启动嵌入式响应式Web服务器。

        default/NONE:org.springframework.context.annotation.AnnotationConfigApplicationContext

        应用程序不应作为Web应用程序运行,也不应启动嵌入式Web服务器。

        第二个是prepareContext,这个方法首先将Environment添加到Context,然后向Context中的beanFactory注入一个"internalConfigurationBeanNameGenerator"(内部可配置的bean名称生成器),同时注入ResourceLoader和ClassLoader。

        第三个是refreshContext,这个方法比较重要,按照他的逻辑顺序详细说一下。

this.prepareRefresh();

        这个方法会清除classpath下的一些bean缓存,设置context的启动和关闭状态,初始化包括Servlet的一些init参数。

ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);

        这个两步是获取最新的beanFactory,添加bean的类加载器和bean表达式解析器,注册相关的可解析依赖,添加一些BeanPostProcessor以及注册一些单例bean。

this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);

        这两步是获取应用定义的bean的名称的集合,将这些bean的名称放到beanFactory中的变量beanDefinitionNames中,向beanFactory的manualSingletonNames变量,添加一些不在Spring的容器内(不受Spring控制的)bean。

this.onRefresh();

        重点来了,刚刚提到有根据设置我们的Context会有不同的类型。不同的区别之一就是,每一个类型有自己独特的主题Theme和onRefresh方法。以SERVLET为例,这种Context继承ServletWebServerApplicationContext,使用其onRefresh方法。该方法首先执行GenericWebApplicationContext类中的onRefresh(都叫一个名别乱),获取并装配主题Theme。之后再执行自己类中的createWebServer方法,这个方法先getWebServerFactory再获取WebServer(当前Springboot使用的Web容器)。附一张图吧:

        注意,依赖中的spring-boot-starter-web已经默认集成了spring-boot-starter-tomcat作为Web容器,所以这里Tomcat Web Server被装配进来了。

2.CommandLineRunner和ApplicationRunner

        SpringBoot中提供了两个接口可以在Spring Boot启动的过程中进行一些额外的操作,比如读取配置文件、数据库操作等自定义的内容。而这些功能的实现也非常简单,直接实现这两个接口并实现其run方法,然后将该类实例化,并通过@Component将其注册为Spring的一个bean即可。同时也可以通过@Order或实现Ordered接口来对其指定执行顺序。

        这个实现的run方法会在上面给出的SpringApplication中的run方法的try的最后的callRunners方法中执行。

下一篇:https://blog.csdn.net/NEU_LightBulb/article/details/102892314

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值