java回调spring接口_Spring Boot启动过程及回调接口汇总

启动顺序

Spring boot的启动代码一般是这样的:

1

2

3

4

5

6@SpringBootApplication

public class SampleApplication {

public static void main(String[] args)throws Exception {

SpringApplication.run(SampleApplication.class, args);

}

}

初始化SpringApplication

1、SpringApplication#run(Object source, String... args)#L1174

2、SpringApplication#L1186 -> SpringApplication(sources)#L236

3、SpringApplication#initialize(Object[] sources)#L256 javadoc

4、SpringApplication#L257 添加source(复数),SpringApplication使用source来构建Bean。一般来说在run的时候都会把@SpringBootApplication标记的类(本例中是SampleApplication)放到sources参数里,然后由这个类出发找到Bean的定义。

7、SpringApplication#L1186 -> SpringApplication#run(args)#L297,进入运行阶段

推送ApplicationStartedEvent

SpringApplication#run(args)#L297

准备Environment

SpringApplication#run(args)#L297->#L308->prepareEnvironment(...)#L331准备ConfigurableEnvironment。

创建及准备ApplicationContext

SpringApplication#run(args)#L297

5、SpringApplication#L348->postProcessApplicationContext(context)#L605,给ApplicationContext设置了一些其他东西

8、SpringApplication#L366->load#L687,负责将source(复数)里所定义的Bean加载到ApplicationContext里,在本例中就是SampleApplication,这些source是在初始化SpringApplication阶段获得的。

要注意的是在这个阶段,ApplicationContext里只有SampleApplication,SampleApplication是Bean的加载工作的起点。

刷新ApplicationContext

SpringApplication#run(args)#L297 ->#L315->SpringApplication#refreshContext(context)#L370 ->#L371->SpringApplication#refresh(context)#L759 ->#L761->AbstractApplicationContext#refreshAbstractApplicationContext#L507

1、AbstractApplicationContext#L510->AbstractApplicationContext#prepareRefresh()#L575,做了一些初始化工作,比如设置了当前Context的状态,初始化propertySource(其实啥都没干),检查required的property是否都已在Environment中(其实并没有required的property可供检查)等。

4、给beanFactory设置了ClassLoader

5、给beanFactory设置了SpEL解析器

11、把getEnvironment()作为Bean添加到beanFactory中,Bean Name: environment

12、把getEnvironment().getSystemProperties()作为Bean添加到beanFactory中,Bean Name: systemProperties

13、把getEnvironment().getSystemEnvironment()作为Bean添加到beanFactory中,Bean Name: systemEnvironment

14、AbstractApplicationContext#L520->postProcessBeanFactory(beanFactory),后置处理BeanFactory,实际啥都没做

25、AbstractApplicationContext#L541->finishBeanFactoryInitialization#L828。注意#L861,在这一步的时候才会实例化所有non-lazy-init bean,这里说的实例化不只是new而已,注入、BeanPostProcessor都会执行。

调用 ApplicationRunner 和 CommandLineRunner

SpringApplication#run(args)#L297 ->afterRefresh(context, applicationArguments)#L316 ->callRunners(context, args)#L771 ->#L774 先后调用了当前ApplicationContext中的ApplicationRunner和CommandLineRunner。关于它们的相关文档可以看这里。

需要注意的是,此时的ApplicationContext已经刷新完毕了,该有的Bean都已经有了。

推送ApplicationReadyEvent or ApplicationFailedEvent

SpringApplication#run(args)#L297->listeners.finished(context, null)#L317 间接地调用了EventPublishingRunListener#getFinishedEventEventPublishingRunListener#L96,发送了ApplicationReadyEvent或ApplicationFailedEvent回调接口

ApplicationContextInitializer

加载方式:读取classpath*:META-INF/spring.factories中key等于org.springframework.context.ApplicationContextInitializer的property列出的类

已知清单1:spring-boot-1.4.1.RELEASE.jar!/META-INF/spring.factories

2、ContextIdApplicationContextInitializer(优先级:Ordered.LOWEST_PRECEDENCE – 10)

已知清单2:spring-boot-autoconfigure-1.4.1.RELEASE.jar!/META-INF/spring.factories

ApplicationListener

加载方式:读取classpath*:META-INF/spring.factories中key等于org.springframework.context.ApplicationListener的property列出的类

已知清单1:spring-boot-1.4.1.RELEASE.jar!/META-INF/spring.factories中定义的

1、ClearCachesApplicationListener(优先级:无=Ordered.LOWEST_PRECEDENCE)

2、ParentContextCloserApplicationListener(优先级:Ordered.LOWEST_PRECEDENCE – 10)

3、FileEncodingApplicationListener(优先级:Ordered.LOWEST_PRECEDENCE)

4、AnsiOutputApplicationListener(优先级:ConfigFileApplicationListener.DEFAULT_ORDER + 1)

5、ConfigFileApplicationListener(优先级:Ordered.HIGHEST_PRECEDENCE + 10)

8、ClasspathLoggingApplicationListener(优先级:LoggingApplicationListener的优先级 + 1)

9、LoggingApplicationListener(优先级:Ordered.HIGHEST_PRECEDENCE + 20)

已知清单2:spring-boot-autoconfigure-1.4.1.RELEASE.jar!/META-INF/spring.factories中定义的

SpringApplicationRunListener

加载方式:读取classpath*:META-INF/spring.factories中key等于org.springframework.boot.SpringApplicationRunListener的property列出的类

已知清单:spring-boot-1.4.1.RELEASE.jar!/META-INF/spring.factories定义的

1、org.springframework.boot.context.event.EventPublishingRunListener(优先级:0)

EnvironmentPostProcessor

加载方式:读取classpath*:META-INF/spring.factories中key等于org.springframework.boot.env.EnvironmentPostProcessor的property列出的类

已知清单:spring-boot-1.4.1.RELEASE.jar!/META-INF/spring.factories定义的

1、CloudFoundryVcapEnvironmentPostProcessor(优先级:ConfigFileApplicationListener.DEFAULT_ORDER – 1)

BeanPostProcessor

用来对Bean实例进行修改的勾子,根据Javadoc ApplicationContext会自动侦测到BeanPostProcessor Bean,然后将它们应用到后续创建的所有Bean上。

BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor

*Aware

*Aware是一类可以用来获得Spring对象的interface,这些interface都继承了Aware,已知的有:

@Configuration 和 Auto-configuration

这两者的相同之处有:

都可以使用@Condition*来根据情况选择是否加载

而不同之处有:

1、加载方式不同:普通@Configuration则是通过扫描package path加载的

Auto-configuration的是通过读取classpath*:META-INF/spring.factories中key等于org.springframework.boot.autoconfigure.EnableAutoConfiguration的property列出的@Configuration加载的

2、加载顺序不同:普通@Configuration的加载在Auto-configuration之前,但是有例外情况,看下面。

3、内部加载顺序可控上的不同:

1、Auto-configuration如果出现在最初的扫描路径里(@ComponentScan),就会被提前加载到,然后被当作普通的@Configuration处理,这样@AutoConfigureBefore和@AutoConfigureAfter就没用了。参看例子代码里的InsideAutoConfiguration和InsideAutoConfiguration2。

2、Auto-configuration如果提供BeanPostProcessor,那么它会被提前加载。参见例子代码里的BeanPostProcessorAutoConfiguration。

4、Auto-configuration如果使用了ImportSelector,那么ImportSelector会被提前加载。参见例子代码里的UselessDeferredImportSelectorAutoConfiguration。

AnnotatedBeanDefinitionReader

ConfigurationClassPostProcessor

需要注意一个烟雾弹:看#L296->ConfigurationClassUtils#L209。而order的值则是在ConfigurationClassUtils#L122从注解中提取的。 这段代码似乎告诉我们它会对@Configuration进行排序,然后按次序加载。 实际上不是的,@Configuration是一个递归加载的过程。在本例中,是先从SampleApplication开始加载的,而事实上在这个时候,也就只有SampleApplication它自己可以提供排序。 而之后则直接使用了ConfigurationClassParser,它里面并没有排序的逻辑。

关于排序的方式简单来说是这样的:@Configuration的排序根据且只根据@Order排序,如果没有@Order则优先级最低。

ConfigurationClassParser

下面讲以下加载的顺序:

1、以SampleApplication为起点开始扫描

4、如果使用的是ImportSelector,则递归导入

顺带一提,如果Auto-configuration里再使用DeferredImportSelector,那么效果和使用ImportSelector效果是一样的,不会再被延后处理。参见例子代码里的UselessDeferredImportSelectorAutoConfiguration。

EnableAutoConfigurationImportSelector

1、先根据类名排序

内置类说明

LoggingApplicationListener

LoggingApplicationListener用来配置日志系统的,比如logback、log4j。Spring boot对于日志有详细解释,如果你想自定义日志配置,那么也请参考本文中对于LoggingApplicationListener的被调用时机的说明以获得更深入的了解。

StandardEnvironment

ConfigFileApplicationListener

ApplicationContextAwareProcessor

AnnotationConfigApplicationContext

根据javadoc,这个类用来将@Configuration和@Component作为输入来注册BeanDefinition。

特别需要注意的是,在javadoc中讲到其支持@Bean的覆盖:In case of multiple @Configuration classes, @Bean methods defined in later classes will override those defined in earlier classes. This can be leveraged to deliberately override certain bean definitions via an extra @Configuration class.

AnnotatedBeanDefinitionReader

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/340134.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python面向对象编程138讲_Python面向对象编程简单讲解

学习目标:1-面向对象编程2-类和对象3-对象的属性和方法4-类的特性Python面向对象编程一种编程程序的设计思想,把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。把计算机程序视为一组对象的集合,而每个对象都可以接…

jboss 程序位置_介绍JBoss BPM Suite安装程序

jboss 程序位置本周,我们想向您介绍JBoss BRMS和JBoss BPM Suite产品随附的一个鲜为人知的安装程序组件。 请注意,当前所有的演示项目都要求您下载JBoss BPM Suite可部署的eap zip产品文件和JBoss EAP 6.1.1 zip产品文件。 展望未来,我们将迁…

java换成中文_如果我们的编程替换成中文会变成怎样?

首先大概的看一下中文编码:你以为会写中文就会编程吗?这就像你以为会写汉字就会写出好文章一样。编程是和机器沟通,因此要用机器的语言而不是人类的语言。最早的程序就是0和1的数字,不是中文也不是英文。以前的程序员,…

高等数学公式大全_高中物理知识思维导图大全,赶紧收藏!

物理作为理综的重中之重,物理的学习一直是广大考生的难点。如何快捷高效的掌握物理知识点是高考复习的重点之一,根据高中物理三年知识点用思维导图的方式,来助大家掌握物理知识点。运动的描述 重力 基本相互作用 相互作用 牛顿运动定律 力的合…

HTTP方法:幂等性和安全性

幂等性和安全性是HTTP方法的属性。 HTTP RFC定义了这些属性,并告诉我们哪些HTTP方法是安全且幂等的。 服务器应用程序应确保正确执行安全和幂等的语义,如客户端期望的那样。 安全的HTTP方法 如果HTTP方法不更改服务器状态,则认为它们是安全的…

java a[i].setx(-1);_java – setX和setY在尝试定位图像时不起作用

我在使用setX上的setX和setY为我的JavaFX程序中定位图像时遇到问题.我不确定是什么问题?感谢任何给予的帮助!这是我的代码:Image rocket2 new Image("img/Rocket.png");ImageView iv1 new ImageView(rocket2);iv1.setX(60);iv1.s…

go环境搭建_学习的golang第一步,搭建我们运行的环境,go! go! go

这是Golang教程系列中的第一个教程。本教程介绍了Go,并讨论了选择Go优于其他编程语言的优势。我们还将学习如何在Mac OS,Windows和Linux中安装Go。介绍Go也称为Golang是由Google开发的一种开源,编译和静态类型的编程语言。创造Go的关键人物是…

如何在Java中将数组转换为列表

你好朋友, 在本教程中,我们将学习将数组转换为List的各种方法。 package com.blogspot.javasolutionsguide;import com.google.common.collect.Lists; import org.apache.commons.collections4.CollectionUtils;import java.util.ArrayList; import ja…

html5网页制作代码_HTML5的网页设计教程

关注小编,教你如何制作网页HTML5是超文本标记语言(HyperText Markup Language)的第五代版本,它是书写网页代码的一种规范、一种标准。它通过标记符号来标记要显示的网页中的各个部分。浏览器根据这个标准显示其中的内容(如:文字如何处理&…

java命令框编译代码的方式_在命令行模式下如何编译运行Java代码

由于已经习惯了在Windows环境中进行开发,最近在尝试将开发环境转移到Linux上面。遇到一篇值得参考的外文,特翻译记录一下。【只翻译了部分】一直被集成开发环境和自动构建工具“溺爱”着,我最近意识到我居然一点儿都不会在命令行模式下去运行…

hibernate jpa_JPA /Hibernate刷新策略初学者指南

hibernate jpa介绍 在我以前的文章中,我介绍了实体状态转换 对象关系映射范例。 当刷新当前持久性上下文时,所有管理实体状态转换都将转换为关联的数据库语句。 Hibernate的刷新行为并不总是像人们想象的那样明显。 后写 Hibernate尝试将持久性上下文刷…

aop+注解 实现对实体类的字段校验_SpringBoot实现通用的接口参数校验

来自:掘金,作者:cipher链接:https://juejin.im/post/5af3c25b5188253064651c76原文链接:http://www.ciphermagic.cn/spring-boot-aop-param-check.html本文介绍基于Spring Boot和JDK8编写一个AOP,结合自定义…

java基础分享_一、java基础教程

1、java是一门比较纯粹的面向对象编程语言,所以java的所有代码都必须写在类的内部。1.1 java的可执行文件后缀名是".java",例如HelloWorld.java,并且每个可执行文件内部,必须有且仅有一个public公共类/公共接口/公共抽象…

Spring Boot自定义横幅生成

每当我们启动Spring Boot应用程序时,都会显示如下所示的文本消息。 这称为横幅。 现在,如果我们可以创建一个特定于我们的Spring Boot应用程序的自定义横幅并使用它代替默认的Spring Boot横幅,那将不是一件很棒的事。 有很多方法可以生成和使…

java简单递归算法_java递归算法的简单示例

java递归算法的简单示例今天参加笔试,要求用递归实现1357……没写出来,蛋疼。。。。下面复习一下,自己尝试着写还是没有写出来。。。。。没有写出来的关键是自己不知道该如何实现求和、实现出口递归实现的关键是:1.出口的设计2.递…

java等待_Java学习:等待唤醒机制

等待唤醒机制线程的状态NEW 至今尚未启动的线程处于这种状态RUNNABLE 正在Java虚拟机中执行的线程处于这种状态BLOCKED 受阻塞并等待某个监视器锁的线程处于这种状态WAITING 无限期的等待另一个线程来执行某一待定操作的线程处于这种状态TIMED_WAITNG 等待另一个线程来执行取…

游戏ai 行为树_游戏AI –行为树简介

游戏ai 行为树游戏AI是一个非常广泛的主题,尽管有很多资料,但我找不到能以较慢且更易理解的速度缓慢介绍这些概念的东西。 本文将尝试解释如何基于行为树的概念来设计一个非常简单但可扩展的AI系统。 什么是AI? 人工智能是参与游戏的实体表现…

java适配器模式应用_java笔记--适配器模式的运用

适配器模式的运用主要应用:可以在符合OCP原则(开笔原则)的基础上,为类增加新的功能。在现有功能上添加新的功能时无须修改原有功能代码。主要角色:目标角色:就是期待得到的接口,如给汽车添加GPS的接口;源角色&#xff…

java构造器_Java构造器就是这么简单!

前言理解构造器之前,首先我们需要了解Java中为什么要引入构造器,以及构造器的作用。在很久之前,程序员们编写C程序总会忘记初始化变量(这真的是一件琐碎但必须的事),C引入了 构造器(constructor) 的概念&am…

JavaFX技巧32:需要图标吗? 使用Ikonli!

动机 自2013年以来,我一直在编写JavaFX应用程序和库的代码,它们的共同点是,我需要找到可以用于它们的良好图标/图形。 作为前Swing开发人员,我首先使用图像文件,GIF或PNG。 通常,我会从IconExperience&…