- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
Spring 应用的启动类.
创建 ApplicationContext 实例 。
ApplicationContext 就是我们所说的容器实例.
注册 CommandLinePropertySource 。
CommandLinePropertySource 的作用是将命令行参数输出为 Spring 属性.
刷新 ApplicationContext 。
这一步骤包括诸多操作,并且会加载所有的单例 bean.
触发 CommandLineRunner bean 。
CommandLineRunner 是一个接口,它只有一个 run() 方法.
凡是实现了此接口的类,如果被加载进容器,就会执行其 run() 方法.
容器中可以包含多个实现 CommandLineRunner 的 bean,执行顺序可以遵从 Ordered 接口或者 @Order 注解设置.
SpringApplication 有诸多 bean 加载源:
AnnotatedBeanDefinitionReader 。
顾名思义,注解 bean 定义读取.
XmlBeanDefinitionReader 。
xml 配置资源读取.
ClassPathBeanDefinitionScanner 。
classpath 路径扫描.
GroovyBeanDefinitionReader 。
... ... 。
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();
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
参数可以为 null,为 null 时,使用默认:
(this.resourceLoader != null) ? this.resourceLoader: new DefaultResourceLoader(null);
主要的 bean 定义来源.
web 应用类型判断:
NONE:应用不会以 web 应用运行,且不会启动内嵌 web 服务器.
SERVLET:基于 servlet web 应用,运行于内嵌 web 服务器.
REACTIVE:响应式 web 应用,运行于内嵌 web 服务器.
BootstrapRegistryInitializer:回调接口,用于 BootstrapRegistry 初始化.
BootstrapRegistry:对象注册器,作用期间为从应用启动,Environment 处理直到 ApplicationContext 完备.
ApplicationContextInitializer 列表设置.
ApplicationContextInitializer:回调接口,用于 Spring ConfigurableApplicationContext 初始化.
通常用于 web 应用 ApplicationContext 自定义初始化。如注册 property source、激活 profile 等.
ApplicationListener 列表设置.
ApplicationListener:应用事件监听接口,基于标准的 EventListener 接口,观察者模式实现.
main class 。
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
创建,刷新 ApplicationContext 并运行 Spring 应用.
使用 System.nanoTime(),计算耗时间隔更精确。不可用于获取具体时刻.
DefaultBootstrapContext = createBootstrapContext(),
BootstrapContext:启动上下文,生命周期同 BootstrapRegistry.
DefaultBootstrapContext 继承了 BootstrapContext、BootstrapRegistry.
用于 BootstrapRegistry 初始化.
可配置的 ApplicationContext.
SpringApplicationRunListeners = getRunListeners().
Spring 应用运行期间事件监听.
listeners.starting():starting step.
ApplicationArguments:提供 SpringApplication 启动参数访问.
ConfigurableEnvironment = prepareEnvironment() 。
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
listeners.environmentPrepared(bootstrapContext, environment);
DefaultPropertiesPropertySource.moveToEnd(environment);
Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
"Environment prefix cannot be set via properties.");
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());
environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
configureEnvironment() 模板方法,代理执行 configurePropertySources() 及 configureProfiles() 方法.
configurePropertySources():PropertySource 配置,用于添加、移除或者调序 PropertySource 资源。CommandLinePropertySource 在这一步处理.
configureProfiles():应用 profile 设置.
ConfigurationPropertySources.attach(environment) 。
ConfigurationPropertySources:提供对 ConfigurationPropertySource 的访问.
attach(environment):就是将这个功能提供给 environment.
listeners.environmentPrepared(bootstrapContext, environment) 。
environment-prepared step.
DefaultPropertiesPropertySource.moveToEnd(environment) 。
DefaultPropertiesPropertySource:是一个 MapPropertySource,包含 SpringApplication 可以使用的一些默认属性。为了使用方便,默认会置于尾序.
bindToSpringApplication(environment) 。
将 environment 绑定到 SpringApplication.
Binder:用于对象绑定的容器.
printBanner().
createApplicationContext().
内部通过 ApplicationContextFactory 创建.
ApplicationContextFactory:策略接口,默认实现为 DefaultApplicationContextFactory.
为容器设置 ApplicationStartup,用于记录启动过程性能指标.
prepareContext() 。
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
postProcessApplicationContext(context);
applyInitializers(context);
listeners.contextPrepared(context);
bootstrapContext.close(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
设置环境 。
postProcessApplicationContext() 前置处理 。
beanNameGenerator 设置,用于 bean 名称生成.
resourceLoader 设置,用于资源加载.
addConversionService:ConversionService 类型转换 Service.
applyInitializers() 。
ApplicationContextInitializer 应用 。
contextPrepared 事件 。
【spring.boot.application.context-prepared】step 。
BootstrapContext 关闭 。
注册 springApplicationArguments bean 。
注册 springBootBanner bean 。
AbstractAutowireCapableBeanFactory 。
设置是否允许 bean 之间的循环依赖,并自动处理,默认为 true.
设置是否允许 bean 定义覆盖,默认为 true.
lazyInitialization 懒加载 。
设置 LazyInitializationBeanFactoryPostProcessor post-processor.
PropertySource 重排序 。
设置 PropertySourceOrderingBeanFactoryPostProcessor post-processor.
getAllSources() bean 定义源加载 。
load() bean 定义加载,BeanDefinitionLoader 。
用于从底层资源加载 bean 定义信息,包括 xml、JavaConfig.
是基于 AnnotatedBeanDefinitionReader、XmlBeanDefinitionReader、ClassPathBeanDefinitionScanner 的门面模式.
beanNameGenerator、resourceLoader、environment 设置.
资源加载:
private void load(Object source) {
Assert.notNull(source, "Source must not be null");
if (source instanceof Class<?>) {
load((Class<?>) source);
return;
}
if (source instanceof Resource) {
load((Resource) source);
return;
}
if (source instanceof Package) {
load((Package) source);
return;
}
if (source instanceof CharSequence) {
load((CharSequence) source);
return;
}
throw new IllegalArgumentException("Invalid source type " + source.getClass());
}
contextLoaded() contextLoaded 事件 。
【spring.boot.application.context-loaded】step.
refreshContext() 。
注册 shutdownHook.
Runtime.getRuntime().addShutdownHook(new Thread(this, "SpringApplicationShutdownHook"));
刷新操作:加载或刷新 。
AbstractApplicationContext::refresh()
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
contextRefresh.end();
}
}
}
作为启动方法,如果失败,则必须销毁所有已创建的单例bean.
StartupStep【spring.context.refresh】 。
准备刷新 prepareRefresh() 。
设置启动日期.
设置 active 标志.
initPropertySources():子类实现 PropertySource 初始化.
validateRequiredProperties():校验 ConfigurablePropertyResolver#setRequiredProperties 设置的必需属性.
obtainFreshBeanFactory():通过子类获取最新的内部 bean factory。如果存在旧的则先销毁,然后再创建新的返回.
prepareBeanFactory() 准备 bean factory 。
setBeanClassLoader():默认为线程上下文类加载器,用于 bean 定义加载.
setBeanExpressionResolver() spel 表达式解析设置:StandardBeanExpressionResolver.
addPropertyEditorRegistrar():ResourceEditorRegistrar 用于 bean 创建过程.
添加 ApplicationContextAwareProcessor post-processor.
注册依赖:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext.
添加 ApplicationListenerDetector post-processor:用于检测发现实现了 ApplicationListener 的 bean.
LoadTimeWeaver 处理.
environment、systemProperties、systemEnvironment、applicationStartup 注册.
postProcessBeanFactory():用于子类实现,修改内部 bean factory.
这一时期,所有的 bean 定义都已被加载,但还未实例化.
StartupStep【spring.context.beans.post-process】 。
invokeBeanFactoryPostProcessors() 触发所有已注册的 BeanFactoryPostProcessor 。
registerBeanPostProcessors() 注册 bean post-processor 。
StartupStep【spring.context.beans.post-process】 结束 。
initMessageSource() MessageSource 初始化 。
容器内 bean 名称:messageSource.
存在则检查并设置 ParentMessageSource.
不存在则创建默认 DelegatingMessageSource,设置 ParentMessageSource 并注册.
initApplicationEventMulticaster() 事件分发初始化 。
容器 bean:applicationEventMulticaster。ApplicationEventMulticaster 接口,用于管理 ApplicationListener,并执行事件分发.
不存在则创建并注册 SimpleApplicationEventMulticaster 对象.
onRefresh() 。
用于子类初始化一些特有的 bean.
模板方法,用于重写实现刷新逻辑.
registerListeners() 监听器注册 。
将实现了 ApplicationListener 接口的 bean 注册到容器.
finishBeanFactoryInitialization() 实例化所有余下的单例 bean.
conversionService.
注册内嵌值(${...})解析器.
初始化 LoadTimeWeaverAware.
停用类型匹配 ClassLoader.
freezeConfiguration() 冻结所有的 bean 定义。所有注册的 bean 定义都不允许再有变更.
preInstantiateSingletons() 实例化所有余下的单例 bean.
ApplicationContext 刷新完毕后调用.
记录应用启动信息.
listeners.started() 。
包括 ApplicationRunner 和 CommandLineRunner.
listeners.ready() 。
最后此篇关于从SpringApplication认识Spring应用启动过程的文章就讲到这里了,如果你想了解更多关于从SpringApplication认识Spring应用启动过程的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
SpringApplication类提供了一种从main()方法启动Spring应用的便捷方式。在很多情况下, 你只需委托给 SpringApplication.run这个静态方法 : @S
我有以下类(class): package org.edgexfoundry.pkg; import org.springframework.boot.SpringApplication; impor
我正在开发 Spring Boot、MySQL、JavaFX、客户端服务器应用程序 - 没有网络 - 并且产生了令人惊讶的效果,尽管我没有更改 UI 中的任何实体,但我收到了一个 ObjectOpti
我使用 Maven 添加 spring-boot Artifact 作为依赖项。 SpringApplication class not found in spring-boot-starter-ac
我使用 Spring Starter 项目模板在 Eclipse 中创建了一个项目。 它自动创建了一个 Application 类文件,并且该路径与 POM.xml 文件中的路径匹配,所以一切正常。这
我们有一个 SpringApplication 可以在默认的 ApplicationContext 中正常运行,但是我们有一个场景,我们需要刷新上下文,而默认上下文不允许我们执行此操作。我已经将我们的
我可能遗漏了一些明显的东西,但我正在尝试弄清楚如何在运行应用程序时以编程方式设置/覆盖 Spring Boot SpringApplication 的属性。 默认情况下,我知道我可以将命令行参数传递给
在 SpringApplication.run 之后,Logback 不打印但 System.out.println 打印。我正在尝试打印出在上下文中加载的 bean。当然,我可以使用 System.
嘿,我是 spring 的新手,我正在尝试在我的 Applications.java 中运行多个运行方法。 import org.springframework.boot.autoconfigure.
我使用 STS 构建了一个 SpringBoot 2.1.5.RELEASE 应用程序。从 STS 运行良好。依赖项下载到我的 .m2 中。到目前为止一切看起来都很好。 此应用程序打包为 jar。我使
我试图在启动 SpringApplication 时获取我编写的所有 bean。 获取所有 列出的 bean 就完成了。这段代码做到了。 String[] beanNames = appContext
上下文:我有一个项目,其中包含一些实用程序来执行数据修复等操作。每个实用程序都是一个 Java 应用程序,即具有 main() 方法的类。我想将它们定义为 Spring Boot 应用程序,以便我可以
我想将Hibernate5插件设置为我的grails应用程序,我使用grails 3.1.1。我已经检查了这个问题,然后我遵循了它:How to configure Grails 3.1.1 to u
我有一个 spring boot 项目,在此之前我总是将它打包成一个 jar 文件并像这样运行它: java -jar myjar.jar 而现在我想把它转换成war包部署到tomcat中。我关注了这
我正在寻找答案,但没有找到。我以“hello world”风格编写了一个简单的应用程序,但无法运行它。我是 Spring Boot 的新手,我不知道出了什么问题。感谢您的帮助。 控制台: .
我是 Spring 的新人。我收到这个错误。这是我的日志: :: Spring Boot :: (v2.1.2.RELEASE) 2019-01-31 15:55:08.747
我正在尝试创建一个 spring mvc 应用程序。这是我的 pom.xml 4.0.0 com.acme test springmvc jar 1
我正在尝试创建一个 spring mvc 应用程序。这是我的 pom.xml 4.0.0 com.acme test springmvc jar 1
我已经很多年没有使用 Java 了,但现在我想使用 Java/Groovy 进行 Web 开发。 Spring Boot 似乎是目前最推荐用作框架的选项,因此我尝试按照pluralsight.com
这是我的 pom.xml 文件: 4.0.0 SpringBootGame SpringBootGame 1.0-SNAPSHOT
我是一名优秀的程序员,十分优秀!