springboot starter 原理解析及实践

4、在refreshContext方法中会进行整个容器刷新过程,会调用中spring中的refresh方法,refresh中有13个非常关键的方法,来完成整个spring应用程序的启动,在自动装配过程中,会调用invokeBeanFactoryPostProcessor方法,在此方法中主要是对ConfigurationClassPostProcessor类的处理,这次是BFPP的子类也是BDRPP的子类,在调用的时候会先调用BDRPP中的tProcessBeanDefinitionRegistry方法,然后调用tProcessBeanFactory方法,在执行tProcessBeanDefinitionRegistry的时候回解析处理各种注解,包含@PropertySource,@ComponentScan,@ComponentScans,@Bean,@Import等注解,最主要的是@Import注解的解析。

starter是springBoot的一个重要部分。通过starter,我们能够快速的引入一个功能,而无需额外的配置。同时starter一般还会给我提供预留的自定配置选项,我们只需要在application.properties中设置相关参数,就可以实现配置的个性化。

spring boot文档_springboot文档pdfspring boot文档_springboot文档pdf


spring boot文档_springboot文档pdf


微服务是一种架构思想,springcloud是一套利于实现微服务架构的技术。相互之间没有必然的联系。

那么这些方便的作是怎么实现的呢?通过了解其原理,我们也可以做一个自己的starter,来让别人快速使用我们的功能。

按个人理解,我认为springBoot Starter就是一个 智能化的配置类 @Configuration 。

接下来介绍内容包括:

1、【创建module】,首先我们自定义一个starter的module,根据你的starter实现复杂度,引入相关spring组件。最基本的,我们只需引入 spring-boot-autoconfigure 模块。

2、【业务bean实现】实现我们的业务bean,案例中我们实现最简单的sayHello服务,输入msg,返回“hello,{msg}”。

4、配置 spring.factories ,通过该配置,才能让springboot来自动加载我们的Configuration类。具体原理我们稍后深入了解。

具体的,是在模块的 resources/META-INF 目录下,新建 spring.factories 文件。内容如下:

我们把上述模块单独执行以下install或者deploy,一个starter就做好了。

其他项目使用我们的starter就非常简单了:(1)引入starter依赖;(2)注入需要的serv。

done!

回头再看上边的开发流程,有两个地方需要我们了解一下:

(1)如何让starter被自动识别加载:spring.factories里的EnableAutoConfiguration原理。

(2)如何实现自动加载的智能化、可配置化:@Configuration配置类里注解。

这里我们只简单的说一下大致的原理和流程,执行细节大家可以按照文章给出的思路自己去研读。

在SpringBoot的启动类,我们都会加上 @SpringBootApplication 注解。这个注解默认会引入 @EnableAutoConfiguration 注解。然后 @EnableAutoConfiguration 会 @Import(AutoConfigurationImportSelector.class) 。

AutoConfigurationImportSelector.class 的selectImports方法最终会通过 SpringFactoriesLoader.loadFactoryNames ,加载 META-INF/spring.factories 里的 EnableAutoConfiguration 配置值,也就是我们上文中设置的资源文件。

实际使用中,我们并不总是希望使用默认配置。比如有时候我想自己配置相关功能,有时候我想更改一下默认的服务参数。这些常见的场景Starter都想到了,并提供了如下的解决方案:

springboot starter提供了一系列的 @Conditional 注解,代表什么时候启用对应的配置,具体的可以去查看一下springboot的文档。

比如我们案例中的 「@ConditionalOnClass(DemoHelloServ.class)」,代表如果存在DemoHelloServ类时,配置类才会生效;又比如「@ConditionalOnMissingBean(DemoHelloServ.class)」,代表着如果项目中没有DemoHelloServ类型的bean,那么该配置类会自动创建出starter默认的DemoHelloServ类型bean。

这个注解主要是为了解决如下场景:我想要使用starter的默认配置类,但是又想对配置中的某些参数进行自定义配置。 @ConfigurationProperties 类就是做这个工作的。例如上述例子中,我想对默认的defaultMsg做些个性化的设置。就可以按如下方式来实现:

starter新增ConfigurationProperties类bean

启用property

在实际项目中自定义默认msg

Spring Boot怎么处理上传文件时出现的MultipartException

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

1、文件上传大小可在js框架里就做验证了。JS上传框架uploadify.js

相信使用过Spring的众多开发者都知道Spring提供了非常好用的 JaMailSender 接口实现邮件发送。在Spring Boot的Starter模块中也为此提供了自动化配置。下面通过实例看看如何在Spring Boot中使用 JaMailSender 发送邮件。

2、既然使用了springboot,那你的文件上传的处理应该在Controller里处理。

3、如果你需要的仅仅是错误信息跳转到错误页面而不是打印堆栈信息,只需要实现一个@RequestMapping(value = "/error")的Controller实现。

聊聊Spring Boot面试相关问题

Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手。

Spring Boot 主要有如下优点:

启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:

@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。

@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能:

@SpringBootApplication(exclude= { DataSourceAutoConfiguration.class })。

@ComponentScan:Spring组件扫描。

Spring JaConfig 是 Spring 社区的产品,它提供了配置 Spring IoC 容器的纯Ja 方法。因此它有助于避免使用 XML 配置。使用 JaConfig 的优点在于:

(1) 面向对象的配置。由于配置被定义为 JaConfig 中的类,因此用户可以

充分利用 Ja 中的面向对象的功能。一个配置类可以继承另一个,重写它的

@Bean 方法等。

(2) 减少或消除 XML 配置。基于依赖注入原则的外化配置的好处已被证明。

但是,许多开发人员不希望在 XML 和 Ja 之间来回切换。JaConfig 为开发人员提供了一种纯粹 Ja 方法来配置与 XML 配置概念相似的 Spring 容器。从

技术角度来讲,只是使用 JaConfig 配置类来配置容器是可行的,但实际上很多人认为将JaConfig 与 XML 混合匹配是理想的。(3)类型安全和重构友好。JaConfig 提供了一种类型安全的方法来配置

Spring容器。由于 Ja 5.0 对泛型的支持,现在可以按类型而不是按名称检索 bean,不需要任何强制转换或基于字符串的查找。

BFPP:BeanFactoryPostProcessor

BPP:BeanPostProcessor

BDRPP:BeanDefinitionRegistryPostProcessor

表达的总体思路是:总-分-总

1、springboot自动装配是什么,解决了什么问题

2、自动装配实现的原理:

1、当启动springboot应用程序的时候, 会先创建SpringApplication的对象,在对象的构造方法中会进行某些参数的初始化工作,最主要的是判断当前应用程序的类型以及初始化器和,在这个过程中会加载整个应用程序中的spring.factories文件,将文件的内容放到缓存对象中,方便后续获取。

2、SpringApplication对象创建完成之后,开始执行run方法,来完成整个启动,启动过程中最主要的有两个方法,个叫做prepareContext,第二个叫做refreshContext,在这两个关键步骤中完整了自动装配的核心功能,前面的处理逻辑包含了上下文对象的创建,banner的打印,异常报告期的准备等各个准备工作,方便后续来进行调用。

3、在prepareContext方法中主要完成的是对上下文对象的初始化作,包括了属性值的设置,比如环境对象,在整个过程中有一个非常重要的方法,叫做load,load主要完成一件事,将当前启动类做为一个beanDefinition注册到registry中,方便后续在进行BeanFactoryPostProcessor调用执行的时候,找到对应的主类,来完成@SpringBootApplicaiton,@EnableAutoConfiguration等注解的解析工作

5、在解析@Import注解的时候,会有一个getImports的方法,从主类开始递归解析注解,把所有包含@Import的注解都解析到,然后在processImport方法中对Import的类进行分类,此处主要识别的时候AutoConfigurationImportSelect归属于ImportSelect的子类,在后续过程中会调用deferredImportSelectorHandler中的process方法,来完整EnableAutoConfiguration的加载。

6、上面是我对springboot自动装配的简单理解,面试官您看一下,我回答有没有问题,帮我指点一下!

在 Spring Boot 里面,可以使用以下几种方式来加载配置。

1) properties文件;

2) YAML文件;

3) 系统环境变量;

等等……

YAML 是一种人类可读的数据序列化语言。它通常用于配置文件。与属性文件相比,如果我们想要在配置文件中添加复杂的属性,YAML 文件就更加结构化,而且更少混淆。可以看出 YAML 具有分层配置数据。

YAML 现在可以算是非常流行的一种配置文件格式了,无论是前端还是后端,都可以见到 YAML 配置。那么 YAML 配置和传统的 properties 配置相比到底有哪些优势呢?

相比 properties 配置文件,YAML 还有一个缺点,就是不支持 @PropertySource 注解导入自定义的 YAML 配置。

Spring Boot 使用 Ja 配置而非 XML 配置,但是 Spring Boot 中也可以使用 XML 配置,通过 @ImportResource 注解可以引入一个 XML 配置。 spring boot 核心配置文件是什么?

bootstrap.properties 和 application.properties 有何区别 ?

单纯做 Spring Boot 开发,可能不太容易遇到 bootstrap.properties 配置文

件,但是在结合 Spring Cloud 时,这个配置就会经常遇到了,特别是在需要加载一些远程配置文件的时侯。

spring boot 核心的两个配置文件:

bootstrap (. yml 或者 . properties):boostrap 由父 ApplicationContext 加载的,比 applicaton 优先加载,配置在应用程序上下文的阶段生效。一般来说我们在 Spring Cloud Config 或者 Nacos 中会用到它。且 boostrap 里面的属性不

能被覆盖;

application (. yml 或者 . properties): 由ApplicatonContext 加载,用于 spring boot 项目的自动化配置。

Spring Profiles 允许用户根据配置文件(dev,test,prod 等)来注册 bean。因此,当应用程序在开发中运行时,只有某些 bean 可以加载,而在

PRODUCTION中,某些其他 bean 可以加载。设我们的要求是 Swagger 文档仅适用于 QA 环境,并且禁用所有其他文档。这可以使用配置文件来完成。Spring Boot 使得使用配置文件非常简单。

为了在自定义端口上运行 Spring Boot 应用程序,您可以在

application.properties 中指定端口。server.port = 8090

为了实现 Spring Boot 的安全性,我们使用 spring-boot-starter-security 依赖项,并且必须添加安全配置。它只需要很少的代码。配置类将必须扩展

WebSession + Redis 来实现 session 共享。将所有微服务的 session 统一保存在 Redis 上,当各个微服务对 session 有相关的读写作时,都去作 Redis 上的 session 。这样就实现了 session 共享,Spring Session 基于 Spring 中的过滤器实现,使得 session 的同步作对开发人员而言是透明的,非常简便。SecurityConfigurerAdapter 并覆盖其方法。

跨域可以在前端通过 JSONP 来解决,但是 JSONP 只可以发送 GET 请求,无法发送其他类型的请求,在 RESTful 风格的应用中,就显得非常鸡肋,因此我们在后端通过 (CORS,Cross-origin resource sharing) 来解决跨域问题。这种解决方案并非 Spring Boot 特有的,在传统的 SSM 框架中,就可以通过 CORS 来解决跨域问题,只不过之前我们是在 XML 文件中配置 CORS ,现在可以通过实现WebMvcConfigurer接口然后重写addCorsMappings方法解决跨域问题。

项目中前后端分离部署,所以需要解决跨域的问题。

我们使用cookie存放用户登录的信息,在spring进行权限控制,当权限不符合时,直接返回给用户固定的json结果。

当用户登录以后,正常使用;当用户退出登录状态时或者token过期时,由于和跨域的顺序有问题,出现了跨域的现象。

CSRF 代表跨站请求伪造。这是一种攻击,迫使 终用户在当前通过身份验证的 Web 应用程序上执行不需要的作。CSRF 攻击专门针对状态改变请求,而不是数据窃取,因为攻击者无法查看对伪造请求的响应。

如何在 Spring Boot 中禁用 Actuator 端点安全性?

默认情况下,所有敏感的 HTTP 端点都是安全的,只有具有 ACTUATOR 角色

的用户才能访问它们。安全性是使用标准的 HttpServletRequest.isUserInRole 方法实施的。 我们可以使用来禁用安全性。只有在执行机构端点在防火墙后访问时,才建议禁用安全性。

Spring Boot 提供监视器端点以各个微服务的度量。这些端点对于获取有关应用程序的信息(如它们是否已启动)以及它们的组件(如数据库等)是否正常运行很有帮助。但是,使用监视器的一个主要缺点或困难是,我们必须单独打开应用程序的知识点以了解其状态或 健康 状况。想象一下涉及 50 个应用程序的微服务,将不得不击中所有 50 个应用程序的执行终端。为了帮助我们处理这种情况,我们将使用位于的开源项目。 它建立在 Spring Boot Actuator 之上,它提供了一个 Web UI,使我们能够可视化多个应用程序的度量。

WebSocket 是一种计算机通信协议,通过单个 TCP 连接提供全双工通信信道。

1、 WebSocket 是双向的 -使用 WebSocket 客户端或可以发起消息发送。

2、 WebSocket 是全双工的 -客户端和通信是相互的。

3、 单个 TCP 连接 -初始连接使用 HTTP,然后将此连接升级到基于套接字的连接。然后这个单一连接用于所有未来的通信

4、 Light -与 相比,WebSocket 消息数据交换要轻得多。

什么是 Spring Data ?

Spring Data 是 Spring 的一个子项目。用于简化数据库访问,支持NoSQL 和 关系数据存储。其主要目标是使数据库的访问变得方便快捷。Spring Data 具有如下特点:

SpringData 项目支持 NoSQL 存储:

SpringData 项目所支持的关系数据存储技术:

Spring Boot Batch 提供可重用的函数,这些函数在处理大量记录时非常重要,包括日志/跟踪,事务管理,作业处理统计信息,作业重新启动,跳过和资源管理。它还提供了更先进的技术服务和功能,通过优化和分区技术,可以实现极高批量和高性能批处理作业。简单以及复杂的大批量批处理作业可以高度可扩展的方式利用框架处理重要大量的信息。

FreeMarker 是一个基于 Ja 的模板引擎, 初专注于使用 MVC 软件架构进行页生成。使用 Freemarker 的主要优点是表示层和业务层的完全分离。程序员可以处理应用程序代码,而设计人员可以处理 html 页面设计。 后使用 freemarker 可以将这些结合起来,给出 终的输出页面。

对于集成 Spring Boot 和 ActiveMQ,我们使用依赖关系。 它只需要很少的配置,并且不需要样板代码。

Swagger 广泛用于可视化 API,使用 Swagger UI 为前端开发人员提供在线沙箱。Swagger 是用于生成 RESTful Web 服务的可视化表示的工具,规范和完整框架实现。它使文档能够以与相同的速度更新。当通过 Swagger 正确定义时,消费者可以使用 少量的实现逻辑来理解远程服务并与其进行交互。因此,Swagger消除了调用服务时的猜测。

前后端分离,如何维护接口文档 ?

前后端分离开发日益流行,大部分情况下,我们都是通过 Spring Boot 做前后端分离开发,前后端分离一定会有接口文档,不然会前后端会深深陷入到扯皮中。一个比较笨的方法就是使用 word 或者 md 来维护接口文档,但是效率太低,接口一变,所有人手上的文档都得变。在 Spring Boot 中,这个问题常见

的解决方案是 Swagger ,使用 Swagger 我们可以快速生成一个接口文档网

站,接口一旦发生变化,文档就会自动更新,所有开发工程师访问这一个在线网站就可以获取到 新的接口文档,非常方便。

这可以使用 DEV 工具来实现。通过这种依赖关系,您可以节省任何更改,嵌入式tomcat 将重新启动。Spring Boot 有一个开发工具(DevTools)模块,它有助于提高开发人员的生产力。Ja 开发人员面临的一个主要挑战是将文件更改自动部署到并自动重启。开发人员可以重新加载 Spring Boot 上的更改,而无需重新启动。这将消除每次手动部署更改的需要。

Spring Boot 在发布它的个版本时没有这个功能。这是开发人员 需要的功能。DevTools 模块完全满足开发人员的需求。该模块将在生产环境中被禁用。

使用了下面的一些依赖项

spring-boot-starter-activemq

spring-boot-starter-security

这有助于增加更少的依赖关系,并减少版本的冲突。

Spring Boot 中的 starter 到底是什么 ?

首先,这个 Starter 并非什么新的技术点,基本上还是基于 Spring 已有功能来实现的。首先它提供了一个自动化配置类,一般命名为 XXXAutoConfiguration

,在这个配置类中通过条件注解来决定一个配置是否生效(条件注解就是

Spring 中原本就有的),然后它还会提供一系列的默认配置,也允许开发者根据实际情况自定义相关配置,然后通过类型安全的属性注入将这些配置属性注入进来,新注入的属性会代替掉默认属性。正因为如此,很多第三方框架,我们只需要引入依赖就可以直接使用了。当然,开发者也可以自定义 Starter spring-boot-starter-parent 有什么用 ?

我们都知道,新创建一个 Spring Boot 项目,默认都是有 parent 的,这个

parent 就是 spring-boot-starter-parent ,spring-boot-starter-parent 主要有如下作用:

Spring Boot 打成的 Spring boot actuator 是 spring 启动框架中的重要功能之一。Spring boot 监视器可帮助您访问生产环境中正在运行的应用程序的当前状态。有几个指标必须在生产环境中进行检查和。即使一些外部应用程序可能正在使用这些服务来向相关人员触发警报消息。监视器模块公开了一组可直接作为 HTTP URL 访问 的REST 端点来检查状态。jar 和普通的 jar 有什么区别 ?

Spring Boot 项目 终打包成的 jar 是可执行 jar ,这种 jar 可以直接通过 ja jar xxx.jar 命令来运行,这种 jar 不可以作为普通的 jar 被其他项目依赖,即使依赖了也无法使用其中的类。

Spring Boot 的 jar 无法被其他项目依赖,主要还是他和普通 jar 的结构不同。普通的 jar 包,解压后直接就是包名,包里就是我们的代码,而 Spring Boot

打包成的可执行 jar 解压后,在 BOOT-INFclasses 目录下才是我们的代码,因此无法被直接引用。如果非要引用,可以在 pom.xml 文件中增加配置,将 Spring Boot 项目打包成两个 jar ,一个可执行,一个可引用。

2) 用 Men/ Gradle 插件运行

3)直接执行 main 方法运行

1) 继承spring-boot-starter-parent项目

2) 导入spring-boot-dependencies项目依赖

Spring 提供了一种使用 ControllerA 处理异常的非常有用的方法。 我们通过实现一个 ControlerA 类,来处理类抛出的所有异常。

使用 Spring Boot 实现分页非常简单。使用 Spring Data-JPA 可以实现将可分页的传递给存储库方法。

微服务中如何实现 session 共享 ?

在微服务中,一个完整的项目被拆分成多个不相同的的服务,各个服务部署在不同的上,各自的 session 被从物理空间上隔离开了,但是经

常,我们需要在不同微服务之间共享 session ,常见的方案就是 Spring

定时任务也是一个常见的需求,Spring Boot 中对于定时任务的支持主要还是来自 Spring 框架。

在 Spring Boot 中使用定时任务主要有两种不同的方式,一个就是使用 Spring 中的 @Scheduled 注解,另一个则是使用第三方框架 Quartz。

使用 Spring 中的 @Scheduled 的方式主要通过 @Scheduled 注解来实现。

使用 Quartz ,则按照 Quartz 的方式,定义 Job 和 Trigger 即可。

SpringBoot配置Email发送功能

如果你需要session,针对动态容错和部署,你可以看看spring-session

在Spring Boot的工程中的 pom.xml 中引入 spring-boot-starter-mail 依赖:

如其他自动化配置模块一样,在完成了依赖引入之后,只需要在 application.properties 中配置相应的属性内容。

通过单元测试来实现一封简单邮件的发送:

到这里,一个简单的邮件发送就完成了,运行一下该单元测试,看看效果如何?

由于Spring Boot的starter模块提供了自动化配置,所以在引入了 spring-boot-starter-mail 依赖之后,会根据配置文件中的内容去创建 JaMailSender 实例,因此我们可以直接在需要使用的地方直接 @Autowired 来引入邮件发送对象。

对于qq邮箱这样写过后会报错:

1、异常信息:

这种错误一般是因为jre的lib下C:Program FilesJajdk1.8.0_51jrelibsecurity,替换2个jar包,参考文档

2、异常信息

发送方必须要开启tp,获取到的授权码,界面如下:

3、异常信息:

换成公司企业邮箱报错,通过将properties文件的内容修改就可以了,这里的用户密码就是自己的邮箱密码(这点不同于qq邮箱)

1. 发送HTML格式的邮件

注意: 这里创建的是 MimeMessageHelper ,且在调用 setText 时需要在第二个参数传入 tr3、然后就是Configuration类的创建,这个类是starter自动初始化的核心类,负责把业务相关的bean智能的加载进来。ue ,这样才会使用HTML格式发送邮件

通过velocity模板发送邮件:

在resources下建一个templates包 该包下建立一个文件template.vm,内容以html格式随便写

你好, ${username}, 这是一封模板邮件!

测试结果:

[Spring boot源码解析] 2 启动流程分析

在了解 Spring Boot 的启动流程的时候,我们先看一下一个Spring Boot 应用是如何启动的,如下是一个简单的 SpringBoot 程序,非常的简洁,他是如何做到的呢,我们接下来就将一步步分解。

我们 SpringApplication.run() 方法,其实最终它主要的逻辑是新建一个 SpringApplication ,然后调用他的 run 方法,如下:

我们先来看一下创建 SpringApplication 的方法:

在将Main class 设置 primarySources 后,调用了 WebApplicationType.deduceFromClasspath() 方法,该方法是为了检查当前的应用类型,并设置给 webApplicationType 。 我们进入 deduceFromClasspath 方法 :

这里主要是通过类加载器判断是否存在 REACTIVE 相关的类信息,如有就代表是一个 REACTIVE 的应用,如不是就检查是否存在 Servelt 和 ConfigurableWebApplicationContext ,如都没有,就代表应用为非 WEB 类应用,返回 NONE ,默认返回 SERVLET 类型,我们这期以我们目前最常使用的 SERVLET 类型进行讲解,所以我们在应用中引入了 spring-boot-starter-web 作为依赖:

他会包含 Spring-mvc 的依赖,所以就包含了内嵌 tomcat 中的 Servlet 和 Spring-web 中的 ConfigurableWebApplicationContext ,因此返回了 SERVLET 类型。

回到刚才创建 SpringApplication 的构建方法中,我们设置完成应用类型后,就寻找所有的 Initializer 实现类,并设置到 SpringApplication 的 Initializers 中,这里先说一下 getSpringFactoriesInstances 方法,我们知道在我们使用 SpringBoot 程序中,会经常在 META-INF/spring.factories 目录下看到一些 EnableAutoConfiguration ,来出发 config 类注入到容器中,我们知道一般一个 config 类要想被 SpringBoot 扫描到需要使用 @CompnentScan 来扫描具体的路径,对于 jar 包来说这无疑是非常不方便的,所以 SpringBoot 提供了另外一种方式来实现,就是使用 spring.factories ,比如下面这个,我们从 Springboot-test 中找到的例子,这里先定义了一个ExampleAutoConfiguration,并加上了 Configuration 注解:

然后在 spring.factories 中定义如下:

那这种方式是怎么实现的你,这就要回到我们刚才的方法 getSpringFactoriesInstances :

首先是会先检查缓存,如缓存中存在就直接返回,如没有就调用 classLoader#getResources 方法,传入 META-INF/spring.factories ,即获取所有 jar 包下的对应文件,并封装成 UrlResource ,然后使用 PropertiesLoaderUtils 将这些信息读取成一个对一对的 properties,我们观察一下 spring.factories 都是按 properties 格式排版的,如有多个就用逗号隔开,所以这里还需要将逗号的多个类分隔开来,并加到 result 中,由于 result 是一个 LinkedMultiValueMap 类型,支持多个值插入,放回缓存中。最终完成加载 META-INF/spring.factories 中的配置,如下:

我们可以看一下我们找到的 initializer 有多少个:

在获取到所有的 Initializer 后接下来是调用 createSpringFactoriesInstances 方法进行初始化。

这里的 names 就是我们上面通过类加载器加载到的类名,到这里会先通过反射生成 class 对象,然后判断该类是否继承与 ApplicationContextInitializer ,通过发射的方式获取这个类的构造方法,并调用该构造方法,传入已经定义好的构造参数,对于 ApplicationContextInitializer 是无参的构造方法,然后初始化实例并返回,回到原来的方法,这里会先对所有的 ApplicationContextInitializer 进行排序,调用 AnnotationAwareOrderComparator#sort(instances) 方法,这里就是根据 @Order 中的顺序进行排序。

接下来是设置 ApplicationListener ,我们跟进去就会发现这里和上面获取 ApplicationContextInitializer 的方法如出一辙,最终会加载到如图的 15 个 listener (这里除了 EnableEncryptablePropertiesBeanFactoryPostProcessor 外,其他都是 SpringBoot 内部的 Listener):

在完成 SpringApplication 对象的初始化后,我们进入了他的 run 方法,这个方法几乎涵盖了 SpringBoot 生命周期的所有内容,主要分为九个步骤,每一个步骤这里都使用注解进行标识:

主要步骤如下:

第二步:根据 SpringApplicationRunListeners以及参数来准备环境。

第三步2.在pom.xml文件中,project下面增加package标签:创建 Spring 容器。

第五步:刷新 Spring 容器。

第六步: Spring 容器的后置处理器。

第七步:通知所有 listener 结束启动。

第八步:调用所有 runner 的 run 方法。

第九步:通知所有 listener running 。

我们接下来一一讲解这些内容。

我们首先看一下步,获取 SpringApplicationRunListener :

这里和上面获取 initializer 和 listener 的方式基本一致,都是通过 getSpringFactoriesInstances , 最终只找到一个类就是: org.springframework.boot.context.nt.EventPublishingRunListener ,然后调用其构造方法并传入产生 args , 和 SpringApplication 本身:

我们可以看出,是放到了 applicationListenters 这个容器中。他是 defaultRetrir 的成员属性, defaultRetrir 则是 AbstractApplicationEventMulticaster 的私有类,我们简单看一下这个类:

我们只需要看一下这里的 getApplicationListeners 方法,它主要是到 beanFactory 中检查是否存在多的 ApplicationListener 和旧的 applicationListeners 组合并返回,接着执行 listener 的 start 方法,也是调用了 AbstractApplicationEventMulticaster 的 multicastEvent 查找支持对应的 ApplicationEvent 类型的通知的 ApplicationListener 的 onApplicationEvent 方法 ,这里除了会:

筛选的方法如下,都是调用了对应类型的 supportsEventType 方法 :

如图,我们可以看到对 org.springframework.boot.context.nt.ApplicationStartingEvent 感兴趣的有5个 Liste步:获取 SpringApplicationRunListener, 然后调用他的 staring 方法启动。ner

环境准备的具体方法如下:

首先是调用 getOrCreateEnvironment 方法来创建 environment ,我们跟进去可以发现这里是根据我们上面设置的环境的类型来进行选择的,当前环境会创建 StandardServletEnvironment

我们先来看一下 StandardServletEnvironment 的类继承关系图,我们可以看出他是继承了 AbstractEnvironment :

我们看一下 StandardEnvironment#customizePropertySources 方法,与上面的三个 properties 创建不同,这两个是会进行赋值的,包括系统环境变量放入 Environment 中,jvm 先关参数放到 Properties 中:

这里会添加 Environment 和 Properties 这两个 properties,最终拿到的 properties 数量如下 4个:

我们先看一下 configurePropertySources 方法,这里主要分两部分,首先是查询当前是否存在 defaultProperties ,如不为空就会添加到 environment 的 propertySources 中,接着是处理命令行参数,将命令行参数作为一个 ComitePropertySource 或则 SimpleCommandLinePropertySource 添加到 environment 的 propertySources 里面,

接着调用 ConfigurationPropertySources#attach 方法,他会先去 environment 中查找 configurationProperties , 如寻找到了,先检查 configurationProperties 和当前 environment 是否匹配,如不相等,就先去除,添加 configurationProperties 并将其 sources 属性设置进去。

回到我们的 prepareEnvironment 逻辑,下一步是通知观察者,发送 ApplicationEnvironmentPreparedEvent ,调用的是 SpringApplicationRunListeners#environmentPrepared 方法,最终回到了 SimpleApplicationEventMulticaster#multicastEvent 方法,我们通过 debug 找到对这个时间感兴趣的 Listener 如下:

其主要逻辑如下:

这个方法加载了 PropertySourceLoader , 这里主要是两种,一个是用于 Properties 的,一个是用于 YAML 的如下:

其中 apply 方法主要是加载 defaultProperties ,如已经存在,就进行替换,而替换的目标 PropertySource 就是 load 这里的一个 consumer 函数加载出来的,这里列一下主要做的事情:

1、加载系统中设置的所有的 Profile 。

2、遍历所有的 Profile ,如是默认的 Profile , 就将这个 Profile 加到 environment 中。

3、调用load 方法,加载配置,我们深入看一下这个方法:

他会先调用 getSearchLocations 方法,加载所有的需要加载的路径,最终有如下路径:

其核心方法是遍历所有的 propertySourceLoader ,也就是上面加载到两种 propertySourceLoader ,最红 loadForFileExtension 方法,加载配置文件,这里就不展开分析了,说一下主要的作用,因为每个 propertySourceLoader 都有自己可以加载的扩展名,默认扩展名有如下四个 properties, xml, yml, yaml,所以最终拿到文件名字,然后通过 - 拼接所有的真实的名字,然后加上路径一起加载。

接下来,我们分析 BackgroundPreinitializer ,这个方法在接收 ApplicationPrepareEnvironment 的时候真正调用了这份方法:

1、 ConversionServInitializer 主要负责将包括 日期,货等一些默认的转换器注册到 formatterRegistry 中。

2、 ValidationInitializer 创建 validation 的匹配器。

4、 JacksonInitializer 主要用于生成 xml 转换器的。

接着回到我们将的主体方法, prepareEnvironment 在调用完成 listeners.environmentPrepared(environment) 方法后,调用 bindToSpringApplication(environment) 方法,将 environment 绑定到 SpirngApplication 中。

接着将 enviroment 转化为 StandardEnvironment 对象。

将 configurationProperties 加入到 enviroment 中, configurationProperties 其实是将 environment 中其他的 PropertySource 重新包装了一遍,并放到 environment 中,这里主要的作用是方便 PropertySourcesPropertyResolver 进行解析。

它主要是检查是否存在 spring.bean.ignore 配置,这个配置的主要作用是设置 jaBean 的内省模式,所谓内省就是应用程序在 Runtime 的时候能检查对象类型的能力,通常也可以称作运行时类型检查,区别于反射主要用于修改类属性,内省主要用户获取类属性。那么我们什么时候会使用到内省呢,ja主要是通过内省工具 Introspector 来完成内省的工作,内省的结果通过一个 Bean 对象返回,主要包括类的一些相关信息,而在 Spring中,主要是 BeanUtils#copyProperties 会使用到,Spring 对内省机制还进行了改进,有三种内省模式,如下图中红色框框的内容,默认情况下是使用 USE_ALL_BEANINFO。如设置为true,就是改成第三中 IGNORE_ALL_BEANINFO

首先是检查 Application的类型,然后获取对应的 ApplicationContext 类,我们这里是获取到了 org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext 接着调用 BeanUtils.instantiateClass(contextClass); 方法进行对象的初始化。

最终其实是调用了 AnnotationConfigServletWebApplicationContext 的默认构造方法。我们看一下这个方法做了什么事情。这里只是简单的设置了一个 reader 和一个 scanner,作用于 bean 的扫描工作。

我们再来看一下这个类的继承关系

这里获取 ExceptionReporter 的方式主要还是和之前 Listener 的方式一致,通过 getSpringFactoriesInstances 来获取所有的 SpringBootExceptionReporter 。

其主要方法执行如下:

启动spring boot报错,怎么解决

今天准备把我之前搭建的,基于springboot的框架的基础功能包抽离出来,在增加spring yml自定义设置后,在业务项目启动时会报出以下异常。

2017-02-23 18:55:09.869 WARN main org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext[refresh:550] - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Tomcat.class]: Bean instantiation via factory mod failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.tomcat.jdbc.pool.DataSource]: Factory mod 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath. If you he database settings to be loaded from a particular profile you may need to active it (the profiles "dev,redis,config,mongodb,activemq,socketio" are currently active).

2017-02-23 18:55:14.322 INFO main com.corundumstudio.socketio.SocketIO[stop:198] - SocketIO server stopped

2017-02-23 18:55:14.349 INFO main org.springframework.boot.autoconfigure.logging.AutoConfiSpringCloud微服务组件介绍gurationReportLoggingInitializer[logAutoConfigurationReport:101] -

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.

2017-02-23 18:55:14.355 ERROR main org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter[report:42] -

A下面我们以QQ邮箱为例,在 application.properties 中加入如下配置(注意替换自己的用户名和密码):PPLICATION FAILED TO START

Description:

Cannot determine embedded database driver class for database type NONE

Action:

If you want an embedded database please put a supported one on the classpath. If you he database settings to be loaded from a particular profile you may need to active it (the profiles "dev,redis,config,mongodb,activemq,socketio" are currently active).12345678011121314151617181234567801112131415161718

在多方查证后,需要在启动类的@EnableAutoConfiguration或@SpringBootApplication中添加exclude

= {DataSourceAutoConfiguration.class},排除此类的autoconfig。启动以后就可以正常运行。

SpringBoot整合ORM开发框架MyBatis和JPA

1、在使用Spring整合ORM组件的过程中,为了达到简化的目的,往往会进行大量的配置。利用SpringBoot可以进一步实现配置的简化。SpringBoot整合MyBatis开发框架,MyBatis是一款常用并且配置极为简单的ORM开发框架。其与Spring结合后,可以利用Spring的特征实现DAO接口的自动配置。在SpringBoot中,又对MyBatis框架的整合进行了进一步简化。

修改pom.xml配置文件,在项目中引入mybatis-spring-boot- starter依赖支持库,切记也需要数据库链接池的支持的哦。

数据表结构,如下所示:

注意:如果数据表字段两个英文单词之间是下划线连接的,但是你的实体类是驼峰命名法,此时就需要进行配置,数据库字段是你下划线分隔,但是bean中的字段是驼峰命名的,如user_name和userName,导致无法匹配。如果是通过xml文件来配置的话,只需要开启驼峰命名转换,setting name="mapUnderscoreToCamelCase" value="true"/>,在/src/main/resources/mybatis/mybatis.cfg.xml里面配置即可。

创建一个po实体类,方便数据传输,如下所示:

如果在appl他会调用子类的 customizePropertySources 方法实现,首先是 StandardServletEnvironment 的实现如下,他会添加 servletConfigInitParams , servletContextInitParams , jndiProperties 三种 properties,当前调试环境没有配置 jndi properties,所以这里不会添加。接着调用父类的 customizePropertySources 方法,即调用到了 StandardEnvironment 。ication.properties中开启转换的话,使用mybatis.configuration.map-underscore-to-camel-case=true配置即可。

或者搞个配置类,如果数据库表字段Column无法自动映射到相对应的实体类属性上,我们可以在config包下新建一个自动配置类MybatisConfig,开始驼峰命名规则。

MyBatis配置文件开启驼峰命名映射

修改application.yml配置文件,追加MyBatis配置,如下所示:

搞几个Dao层、Serv层、Controller层的接口或者类,如下所示:

注意:如果不想每次都在mapper接口上添加@Mapper注解,可以在主启动类上通过添加@MapperScan注解来批量扫描指定包下的所有mapper接口。

Serv层的接口和实现类代码,如下所示:

项目启动类,如下所示:

通过Postman测试一下,自己写的接口,看看好使不,如下所示:

项目结构,如下所示:

2、JPA是推出的Ja持久层作标准(现主要使用Hibernate实现),使用SpringData技术和JpaReitory接口技术,也可以达到简化数据层的目的。要在SpringBoot中使用SpringDataJPA,需要spring-boot-starter-data-jpa依赖库的支持。

修改pom.xml配置文件,引入相关依赖包,如下所示:

创建UserInfo实体类,如下所示:

创建UserDao,然后继承J控制层的代码,如下所示:paReitory ,此时就可以使用写好的方法了,不用自己再额外写接口和实现,如下所示:

然后定义Serv接口和Serv接口实现,如下所示:

然后搞一个Controller,作为接口访问的入口,如下所示:

修改程序启动主类,追加Reitory扫描配置。如果使用JpaReitory实现了DAO接口的自动实现。需要注意的是,如果想启用Reitory配置,则需要在程序启动主类时使用@EnableJpaReitories注解配置扫描包,而后才可以正常使用。

修改application.properties,使用Druid作为数据源连接池,如下所示:

使用tman进行接口调用,如下所示:

最主要的是给自己增加知识的储备,有备无患。给大家分享Spring系列的学习笔记和面试题,包含spring面试题、spring cloud面试题、spring boot面试题、spring教程笔记、spring boot教程笔记、阿里巴巴开发手册(63页PDF总结)、2022年Ja面试手册。一共整理了1184页PDF文档。私信博主(666)领取,祝大家更上一层楼!!!

springboot整合富文本编辑器一直不能上传

数据访问层提供与数据存储层的交互,可以使用DAO设计模式或者对象-关系映射解决方案(如Hibernate、OJB或iBATIS)实现。

题主是否想询问“springboot整合富文本编辑器一直不能上传怎么办”?

1、首先确保使用正确版本的富文本编辑器,并根据文档完成整合。

2、其次对于前端部分,确保上传功能已启用,并且配置了正确的上传URL。通常在富文本编辑器的配置项中设置。

3、然后在SpringBoot后端程序中,设置一个用于处理上传请求的Controller,并提供对应的URL。

2、SpringCloud是基于SpringBoot基础之上开发的微服务框架,SpringCloud是一套目前非常完整的微服务解决方案框架,其内容包含服务治理、注册中心、配置管理、断路器、智能路由、微、控制总线、全局锁、分布式会话等。4、若要实现上传功能,可以考虑保存到本地、外部存储(如OSS)等方式。上传时,注意验证格式、大小等限制。

求一套spring boot视频教程

第四步:Spring 容器的前置处理。

我们先来看一下传入参数,这里需要注意的是 args,这个是初始化对应 type 的时候传入的构造参数,我们先看一下 SpringFactoriesLoader#loadFactoryNames 方法:地址:

springboot的目前还没看到有人做视频讲解。

其实学习这种新框架的话,建议先看网上的入门文档,然后参考文档(英文的),自己多写几个例子跑跑看。

就是看源码。

这个学习就是比较透彻、