springboot学习7

SpringApplication
1、SpringApplication基本使用:
1.1 SpringApplication运行

SpringApplication.run(DemoSpringBootApplication.class, args)

1.2、自定义SpringApplication
1)通过SpringApplicationAPI 方式

SpringApplication springApplication = new SpringApplication(DemoSpringBootApplication.class);
springApplication.setBannerMode(Banner.Mode.CONSOLE);
springApplication.setWebApplicationType(WebApplicationType.NONE);
springApplication.setAdditionalProfiles("prod");
springApplication.setHeadless(true);

2)通过SpringApplicationBuilderAPI 方式

new SpringApplicationBuilder(DemoSpringBootApplication.class)    
	.bannerMode(Banner.Mode.CONSOLE)   
 	.web(WebApplicationType.NONE)   
  	.profiles("prod") 
  	.headless(true)
  	.run(args);

2、SpringApplication准备阶段:

package org.springframework.boot;

public class SpringApplication {

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		// 配置源
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		// 推断应用类型
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		// 通过工厂方式,加载实例。在后面的运行阶段(run方法)来操作。
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
		// 通过工厂方式,加载实例。在后面的运行阶段(run方法)来操作。
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		// 推断当前主类,通过线程的栈来推断。
		this.mainApplicationClass = deduceMainApplicationClass();
	}
}

2.1 配置 Spring Boot Bean 源

Java 配置 Class 或 XML 上下文配置文件集合,用于 `Spring Boot BeanDefinitionLoader`读取,并且将配置源解析加载为Spring Bean 定义
package org.springframework.boot;

class BeanDefinitionLoader {
	//...省略
	// bean定义注册, 一个或多个
	BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
			Assert.notNull(registry, "Registry must not be null");
			Assert.notEmpty(sources, "Sources must not be empty");
			this.sources = sources;
			// java class或者bean或者 xml
			this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
			this.xmlReader = new XmlBeanDefinitionReader(registry);
			if (isGroovyPresent()) {
				this.groovyReader = new GroovyBeanDefinitionReader(registry);
			}
			this.scanner = new ClassPathBeanDefinitionScanner(registry);
			this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
	}
}

配置 Class

Java 配置 Class用于 Spring 注解驱动中 Java 配置类,大多数情况是 Spring 模式注解所标注的类,如`@Configuration`。
XML 上下文配置文件用于 Spring 传统配置驱动中的 XML 文件。

XML 上下文配置文件

package com.example.springbootlearn.demospringboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * {@link SpringApplication}
 *
 */
@SpringBootApplication
public class SpringApplicationBootstrap {

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

在SpringApplication的run方法中,要传入标了@SpringBootApplication的类。不一定是主类。比如下面这样也可以:

package com.example.springbootlearn.demospringboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * {@link SpringApplication}
 *
 */
public class SpringApplicationBootstrap {

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

    @SpringBootApplication
    public static class ApplicationConfiguration {

    }
}

也可以这样:

package com.example.springbootlearn.demospringboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.HashSet;
import java.util.Set;

/**
 * {@link SpringApplication}
 *
 */
public class SpringApplicationBootstrap {

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

        Set<String> sources = new HashSet<>();
        sources.add(ApplicationConfiguration.class.getName());
        SpringApplication springApplication = new SpringApplication();
        springApplication.setSources(sources);
        springApplication.run(args);
    }

    @SpringBootApplication
    public static class ApplicationConfiguration {

    }
}

setSources方法:

package org.springframework.boot;
public class SpringApplication {
	// ...省略
	
	/**
	 * Set additional sources that will be used to create an ApplicationContext. A source
	 * 可以是:
	 * can be: a class name, package name, or an XML resource location.
	 * <p>
	 * Sources set here will be used in addition to any primary sources set in the
	 * constructor.
	 * @param sources the application sources to set
	 * @see #SpringApplication(Class...)
	 * @see #getAllSources()
	 */
	public void setSources(Set<String> sources) {
		Assert.notNull(sources, "Sources must not be null");
		this.sources = new LinkedHashSet<>(sources);
	}
}

2.2 推断 Web 应用类型
根据当前应用 ClassPath 中是否存在相关实现类来推断 Web 应用的类型,包括:

Web Reactive:WebApplicationType.REACTIVE
Web Servlet:WebApplicationType.SERVLET
非 Web:WebApplicationType.NONE

推断方法:

package org.springframework.boot.test.context;

public class SpringBootTestContextBootstrapper extends DefaultTestContextBootstrapper {
	// ... 省略
	
	private WebApplicationType deduceWebApplicationType() {
			if (ClassUtils.isPresent(REACTIVE_WEB_ENVIRONMENT_CLASS, null) // REACTIVE_WEB_ENVIRONMENT_CLASS = "org.springframework." + "web.reactive.DispatcherHandler";
					&& !ClassUtils.isPresent(MVC_WEB_ENVIRONMENT_CLASS, null) // MVC_WEB_ENVIRONMENT_CLASS = "org.springframework." + "web.servlet.DispatcherServlet";
					&& !ClassUtils.isPresent(JERSEY_WEB_ENVIRONMENT_CLASS, null)) { // JERSEY_WEB_ENVIRONMENT_CLASS = "org.glassfish.jersey.server.ResourceConfig";
				return WebApplicationType.REACTIVE;
			}
			for (String className : WEB_ENVIRONMENT_CLASSES) {
				if (!ClassUtils.isPresent(className, null)) {
					return WebApplicationType.NONE;
				}
			}
			return WebApplicationType.SERVLET;
	}
}

2.3 推断引导类(Main Class):

package org.springframework.boot;

public class SpringApplication {

// ... 省略

private Class<?> deduceMainApplicationClass() {
		try {
			StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
			for (StackTraceElement stackTraceElement : stackTrace) {
				if ("main".equals(stackTraceElement.getMethodName())) {
					return Class.forName(stackTraceElement.getClassName());
				}
			}
		}
		catch (ClassNotFoundException ex) {
			// Swallow and continue
		}
		return null;
	}
}

2.4 加载应用上下文初始器ApplicationContextInitializer
通过Spring 工厂加载机制,实例化 ApplicationContextInitializer 实现类,并排序对象集合。

package org.springframework.boot;

public class SpringApplication {
	// ... 省略

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

上面代码中:SpringFactoriesLoader.loadFactoryNames方法,

  • 通过类: org.springframework.core.io.support.SpringFactoriesLoader实现。
  • 会去读取配置资源: META-INF/spring.factories
  • 排序: AnnotationAwareOrderComparator.sort(instances)

参考:
在org.springframework.boot.autoconfigure的spring.factories中,可以看到应用上下文初始配置。
在这里插入图片描述

自定义:
在resources目录下新建META-INF文件,在META-INF下新建spring.factories文件。

在这里插入图片描述
spring.factories

# 实际顺序与order有关,与这里配置顺序无关。
# Initializers
org.springframework.context.ApplicationContextInitializer=\
com.example.springbootlearn.context.AfterDemoApplicationContextInitializer,\
com.example.springbootlearn.context.DemoApplicationContextInitializer

新建content文件夹,新建DemoApplicationContextInitializer文件。

DemoApplicationContextInitializer

package com.example.springbootlearn.context;

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

/**
 *
 */
@Order(Ordered.HIGHEST_PRECEDENCE)
public class DemoApplicationContextInitializer<C extends ConfigurableApplicationContext>  implements ApplicationContextInitializer<C> {

    @Override
    public void initialize(C applicationContext) {
        System.out.println("ConfigurableApplicationContext.id =  :" + applicationContext.getId());
    }
}

新建AfterDemoApplicationContextInitializer文件:

package com.example.springbootlearn.context;

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.Ordered;

public class AfterDemoApplicationContextInitializer implements ApplicationContextInitializer, Ordered {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        System.out.println("after applicationContext.id = " + applicationContext.getId());
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}

SpringApplicationBootstrap

package com.example.springbootlearn.demospringboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.HashSet;
import java.util.Set;

/**
 * {@link SpringApplication}
 *
 */
public class SpringApplicationBootstrap {

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

        Set<String> sources = new HashSet<>();
        sources.add(ApplicationConfiguration.class.getName());
        SpringApplication springApplication = new SpringApplication();
        springApplication.setSources(sources);
        springApplication.setWebApplicationType(WebApplicationType.NONE);  // web和非web都会输出
        springApplication.run(args);
    }

    @SpringBootApplication
    public static class ApplicationConfiguration {

    }
}

运行结果:

// ... 省略
ConfigurableApplicationContext.id =  :org.springframework.context.annotation.AnnotationConfigApplicationContext@22702006
after applicationContext.id = application
// ... 省略

2.5 加载应用事件监听器( ApplicationListener)
通过Spring 工厂加载机制,实例化 ApplicationListener 实现类,并排序对象集合。
参考:
在这里插入图片描述

自定义:
创建listernr文件夹,在新建一个DemoApplicationListener类:

DemoApplicationListener

package com.example.springbootlearn.listener;

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

/**
 *  Demo {@link ApplicationListener} 监听 {@link ContextRefreshedEvent}
 *
 */
@Order(Ordered.HIGHEST_PRECEDENCE)
public class DemoApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        System.out.println("demo ... : " + event.getApplicationContext().getId()
                + ",timestamp : " + event.getTimestamp());
    }
}

创建AfterDemoApplicationListener

package com.example.springbootlearn.listener;

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.Ordered;


/**
 * After Demo {@link ApplicationListener} 监听 {@link ContextRefreshedEvent}
 */
public class AfterDemoApplicationListener implements ApplicationListener<ContextRefreshedEvent>, Ordered  {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // #监听事件要一样 进行order排序
        System.out.println("after demo ... : " + event.getApplicationContext().getId()
                + ",timestamp : " + event.getTimestamp());
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}

SpringApplicationBootstrap

package com.example.springbootlearn.demospringboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.HashSet;
import java.util.Set;

/**
 * {@link SpringApplication}
 *
 */
public class SpringApplicationBootstrap {

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

        Set<String> sources = new HashSet<>();
        sources.add(ApplicationConfiguration.class.getName());
        SpringApplication springApplication = new SpringApplication();
        springApplication.setSources(sources);
        springApplication.run(args);
    }

    @SpringBootApplication
    public static class ApplicationConfiguration {

    }
}

运行结果:

demo ... : application,timestamp : 1612591318234
after demo ... : application,timestamp : 1612591318234

3、SpringApplication 运行阶段
3.1 加载与运行SpringApplication 运行(run)监听器
main方法调用SpringApplication的run方法。
springApplication.run(args);

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

        Set<String> sources = new HashSet<>();
        sources.add(ApplicationConfiguration.class.getName());
        SpringApplication springApplication = new SpringApplication();
        springApplication.setSources(sources);
        springApplication.run(args);
    }

类:SpringApplication

package org.springframework.boot;

public class SpringApplication {
	//... 省略

	public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		//  加载监听器。通过Spring 工厂加载机制,读取 SpringApplicationRunListener 对象集合
		SpringApplicationRunListeners listeners = getRunListeners(args);
		// 运行监听器。
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			configureIgnoreBeanInfo(environment);
			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);
			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;
	}
}

SpringApplicationRunListener监听多个运行状态方法:

监听方法阶段说明Spring Boot Since版本
starting()Spring 应用刚启动1.0
environmentPrepared(ConfigurableEnvironment)ConfigurableEnvironment 准备妥当,允许将其调整1.0
contextPrepared(ConfigurableApplicationContext)ConfigurableApplicationContext 准备妥当,允许将其调整1.0
contextLoaded(ConfigurableApplicationContext)ConfigurableApplicationContext 已装载,但仍未启动1.0
started(ConfigurableApplicationContext)ConfigurableApplicationContext 已启动,此时 Spring Bean 已初始化完成2.0
running(ConfigurableApplicationContext)Spring 应用正在运行2.0
failed(ConfigurableApplicationContext,Throwable)Spring 应用运行失败2.0

3.2 监听 事件
springboot 通过 SpringApplicationRunListener 的实现类 EventPublishingRunListener
通过 Spring Framework 事件,API 来广播 Spring Boot 事件。
1)spring事件

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
// ... 省略

// 广播
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			Executor executor = getTaskExecutor();
			// 异步或同步
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				invokeListener(listener, event);
			}
		}
	}
}
Spring 应用事件
	普通应用事件: ApplicationEvent
	应用上下文事件: ApplicationContextEvent 
Spring 应用监听器
	接口编程模型: ApplicationListener
	注解编程模型: @EventListener 
Spring 应用事广播器
	接口: ApplicationEventMulticaster
	实现类: SimpleApplicationEventMulticaster

参考:
在spring-boot-2.1.0.RELEASE-sources.jar/META-INF/spring.factories文件中:
在这里插入图片描述
在这里插入图片描述
自定义一个:
在com.example.springbootlearn新建一个run包
新建一个DemoRunListener类:

package com.example.springbootlearn.run;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;

public class DemoRunListener implements SpringApplicationRunListener {

    public DemoRunListener(SpringApplication application, String[] args) {

    }

    @Override
    public void starting() {
        System.out.println("DemoRunListener:starting()......");
    }

    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {

    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {

    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {

    }

    @Override
    public void started(ConfigurableApplicationContext context) {

    }

    @Override
    public void running(ConfigurableApplicationContext context) {

    }

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {

    }
}

运行结果:
发现比banner打印还早。

DemoRunListener:starting()......
banner打印
// ... 省略

这是因为SpringApplicationrun方法:

package org.springframework.boot;
public class SpringApplication {
	// ... 省略
	public ConfigurableApplicationContext run(String... args) {
		 // ...省略
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try{
		// ...省略
			Banner printedBanner = printBanner(environment);
		}
		// ...省略
	}
}

EventPublishingRunListener 监听方法与 Spring Boot 事件对应关系

监听方法springboot 事件springboot since版本
starting()ApplicationStartingEvent1.5
environmentPrepared(ConfigurableEnvironment)ApplicationEnvironmentPreparedEvent1.0
contextPrepared(ConfigurableApplicationContext)
contextLoaded(ConfigurableApplicationContext)ApplicationPreparedEvent1.0
started(ConfigurableApplicationContext)ApplicationStartedEvent2.0
running(ConfigurableApplicationContext)ApplicationReadyEvent2.0
failed(ConfigurableApplicationContext,Throwable)ApplicationFailedEvent1.0

2) 监听springboot事件
spring-boot-2.1.0.RELEASE.jar/META-INF/spring.factoires中,
在这里插入图片描述
参考:org.springframework.boot.context.config.ConfigFileApplicationListener

自定义:
在com.example.springbootlearn.listener包下,新建一个BeforeConfigFileApplicationListener文件。
BeforeConfigFileApplicationListener

package com.example.springbootlearn.listener;

import org.springframework.boot.context.config.ConfigFileApplicationListener;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.SmartApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.env.Environment;

/**
 * before {@link ConfigFileApplicationListener} 实现
 */
public class BeforeConfigFileApplicationListener implements SmartApplicationListener, Ordered {
    // Order值越小,优先级越高。所以 这里 比 ConfigFileApplicationListener 优先级高
    @Override
    public int getOrder() {
        return ConfigFileApplicationListener.DEFAULT_ORDER - 1;
    }

    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(eventType)
                || ApplicationPreparedEvent.class.isAssignableFrom(eventType);
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ApplicationEnvironmentPreparedEvent) {
            ApplicationEnvironmentPreparedEvent preparedEvent = (ApplicationEnvironmentPreparedEvent)event;
            Environment environment = preparedEvent.getEnvironment();
            System.out.println("environment.getProperty(\"name\") :" + environment.getProperty("name"));
        }
        if (event instanceof ApplicationPreparedEvent) {

        }
    }
}

spring.factories

# Application Listeners
org.springframework.context.ApplicationListener=\
com.example.springbootlearn.listener.BeforeConfigFileApplicationListener

application.properties

name = learndemo

运行结果:

//... 省略
environment.getProperty("name") :null
// ... 省略

调整一下order值,将上面代码的order修改一下:

    @Override
    public int getOrder() {
        return ConfigFileApplicationListener.DEFAULT_ORDER + 1;
    }

运行输出:

// ...省略
environment.getProperty("name") :learndemo
// ...省略

3.3 创建 Spring 应用上下文

Web Reactive: AnnotationConfigReactiveWebServerApplicationContext // package org.springframework.boot.web.reactive.context;
Web Servlet: AnnotationConfigServletWebServerApplicationContext // package org.springframework.boot.web.servlet.context;
非 Web: AnnotationConfigApplicationContext  // package org.springframework.context.annotation;

参考:

package org.springframework.boot;

public class SpringApplication {
	public ConfigurableApplicationContext run(String... args) {
	// ...省略
	ConfigurableApplicationContext context = null;
	try {
		// ... 省略
		context = createApplicationContext();
		// ... 省略
	}
    // ... 省略
	}
}

createApplicationContext()

protected ConfigurableApplicationContext createApplicationContext() {
		Class<?> contextClass = this.applicationContextClass;
		if (contextClass == null) {
			try {
				switch (this.webApplicationType) {
				case SERVLET:
					contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
					break;
				case REACTIVE:
					contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
					break;
				default:
					contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
				}
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
						"Unable create a default ApplicationContext, "
								+ "please specify an ApplicationContextClass",
						ex);
			}
		}
		return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}

自定义:

package com.example.springbootlearn.demospringboot;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * Spring 应用上下文 引导类
 */
@SpringBootApplication
public class SpringApplicationContextBootstrap {

    public static void main(String[] args) {
		
		// web servlet或web Reactive 或非web
        ConfigurableApplicationContext context = new SpringApplicationBuilder(SpringApplicationContextBootstrap.class)
                // .web(WebApplicationType.NONE) // web servlet或web Reactive 或非web
                .run(args);

        System.out.println("ConfigurableApplicationContext 类型:" +
                context.getClass().getName());

        // 关闭上下文
        context.close();
    }
}

运行结果:

web = WebApplicationType.SERVLET

// ... 省略
ConfigurableApplicationContext 类型:org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
// ... 省略

web = WebApplicationType.NONE


// ... 省略
ConfigurableApplicationContext 类型:org.springframework.context.annotation.AnnotationConfigApplicationContext
// ... 省略

web =WebApplicationType.REACTIVE

// ... 省略
ConfigurableApplicationContext 类型:org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext
// ... 省略

3.4 创建 Environment
根据准备阶段的推断 Web 应用类型创建对应的 ConfigurableEnvironment 实例:

Web Reactive: StandardEnvironment
Web Servlet: StandardServletEnvironment 
非 Web: StandardEnvironment
package com.example.springbootlearn.demospringboot;

import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * Spring 应用上下文 引导类
 */
@SpringBootApplication
public class SpringApplicationContextBootstrap {

    public static void main(String[] args) {

        ConfigurableApplicationContext context = new SpringApplicationBuilder(SpringApplicationContextBootstrap.class)               
             // .web(WebApplicationType.NONE) // web servlet或web Reactive 或非web
                .run(args);

        System.out.println("ConfigurableApplicationContext 类型:" +
                context.getClass().getName());
		// Environment
        System.out.println("Environment 类型:" +
                context.getEnvironment().getClass().getName());

        // 关闭上下文
        context.close();
    }
}

运行结果:
.web(WebApplicationType.NONE)


ConfigurableApplicationContext 类型:org.springframework.context.annotation.AnnotationConfigApplicationContext
Environment 类型:org.springframework.core.env.StandardEnvironment

.web(WebApplicationType.REACTIVE)

ConfigurableApplicationContext 类型:org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext
Environment 类型:org.springframework.boot.web.reactive.context.StandardReactiveWebEnvironment

.web(WebApplicationType.SERVLET)

ConfigurableApplicationContext 类型:org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
Environment 类型:org.springframework.web.context.support.StandardServletEnvironment

SpringApplication上下文周期来逐一调用,把相应的资源准备好。

package org.springframework.boot;

public class SpringApplication {
	// ... 省略
	
	// SpringApplication上下文周期来逐一调用,把相应的资源准备好。
	public ConfigurableApplicationContext run(String... args) {
		// ... 省略
		ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
		// ... 省略
	}
	
	private ConfigurableEnvironment prepareEnvironment(
		// ... 省略
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		listeners.environmentPrepared(environment);	// 监听
		// ... 省略
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值