-
创建独立的
Spring
应用。 -
直接嵌入了
Tomcat
、Jetty
或Undertow
(不需要部署WAR
文件)。 -
提供了固定的配置来简化配置。
-
尽可能地自动配置
Spring
和第三方库。 -
提供可用于生产的特性,如度量、运行状况检查和外部化配置。
-
完全不需要生成代码,也不需要
XML
配置。
SpringBoot
这些特点中最重要的两条就是约定优于配置和自动装配。
SpringBoot
的约定由于配置主要体现在以下方面:
-
maven
项目的配置文件存放在resources
资源目录下。 -
maven
项目默认编译后的文件放于target
目录。 -
maven
项目默认打包成jar
格式。 -
配置文件默认为
application.yml
或者application.yaml
或者application.properties
。 -
默认通过配置文件
spring.profiles.active
来激活配置。
自动装配则是 SpringBoot
的核心,自动装配是如何实现的呢?为什么我们只要引入一个 starter
组件依赖就能实现自动装配呢,接下来就让我们一起来探讨下 SpringBoot
的自动装配机制。
相比较于传统的 Spring
应用,搭建一个 SpringBoot
应用,我们只需要引入一个注解 @SpringBootApplication
,就可以成功运行。
我们就从 SpringBoot
的这个注解开始入手,看看这个注解到底替我们做了什么。
前面四个不用说,是定义一个注解所必须的,关键就在于后面三个注解:@SpringBootConfiguration
,@EnableAutoConfiguration
,@ComponentScan
。也就是说我们如果不用 @SpringBootApplication
这个复合注解,而是直接使用最下面这三个注解,也能启动一个 SpringBoot
应用。
@SpringBootConfiguration 注解
这个注解我们点进去就可以发现,它实际上就是一个 @Configuration
注解,这个注解大家应该很熟悉了,加上这个注解就是为了让当前类作为一个配置类交由 Spring
的 IOC
容器进行管理,因为前面我们说了,SpringBoot
本质上还是 Spring
,所以原属于 Spring
的注解 @Configuration
在 SpringBoot
中也可以直接应用。
@ComponentScan 注解
这个注解也很熟悉,用于定义 Spring
的扫描路径,等价于在 xml
文件中配置 <context:component-scan>
,假如不配置扫描路径,那么 Spring
就会默认扫描当前类所在的包及其子包中的所有标注了 @Component
,@Service
,@Controller
等注解的类。
@EnableAutoConfiguration
这个注解才是实现自动装配的关键,点进去之后发现,它是一个由 @AutoConfigurationPackage
和 @Import
注解组成的复合注解。
@EnableXXX
注解也并不是 SpringBoot
中的新注解,这种注解在 Spring 3.1
版本就开始出现了,比如开启定时任务的注解 @EnableScheduling
等。
@Import 注解
这个注解比较关键,我们通过一个例子来说明一下。
定义一个普通类 TestImport
,不加任何注解,我们知道这个时候这个类并不会被 Spring
扫描到,也就是无法直接注入这个类:
public class TestImport {
}
现实开发中,假如就有这种情况,定义好了一个类,即使加上了注解,也不能保证这个类一定被 Spring
扫描到,这个时候该怎么做呢?
这时候我们可以再定义一个类 MyConfiguration
,保证这个类可以被 Spring
扫描到,然后通过加上 @Import
注解来导入 TestImport
类,这时候就可以直接注入 TestImport
了:
@Configuration
@Import(TestImport.class)
public class MyConfiguration {
}
所以这里的 @Import
注解其实就是为了去导入一个类 AutoConfigurationImportSelector
,接下来我们需要分析一下这个类。
AutoConfigurationImportSelector 类
进入这个类之后,有一个方法,这个方法很好理解,首先就是看一下 AnnotationMetadata
(注解的元信息),有没有数据,没有就说明没导入直接返回一个空数组,否则就调用 getAutoConfigurationEntry
方法:
进入 getAutoConfigurationEntry
方法:
这个方法里面就是通过调用 getCandidateConfigurations
来获取候选的 Bean
,并将其存为一个集合,最后经过去重,校验等一系列操作之后,被封装成 AutoConfigurationEntry
对象返回。
继续进入 getCandidateConfigurations
方法,这时候就几乎看到曙光了:
这里面再继续点击去就没必要了,看错误提示大概就知道了,loadFactoryNames
方法会去 META-INF/spring.factories
文件中根据 EnableAutoConfiguration
的全限定类名获取到我们需要导入的类,而 EnableAutoConfiguration
类的全限定类名为 org.springframework.boot.autoconfigure.EnableAutoConfiguration
,那么就让我们打开这个文件看一下:
可以看到,这个文件中配置了大量的需要自动装配的类,当我们启动 SpringBoot
项目的时候,SpringBoot
会扫描所有 jar
包下面的 META-INF/spring.factories
文件,并根据 key
值进行读取,最后在经过去重等一些列操作得到了需要自动装配的类。
需要注意的是:上图中的 spring.factories
文件是在 spring-boot-autoconfigure
包下面,这个包记录了官方提供的 stater
中几乎所有需要的自动装配类,所以并不是每一个官方的 starter
下都会有 spring.factories
文件。
谈谈 SPI 机制
通过 SpringFactoriesLoader
来读取配置文件 spring.factories
中的配置文件的这种方式是一种 SPI
的思想。那么什么是 SPI
呢?
SPI,Service Provider Interface。即:接口服务的提供者。就是说我们应该面向接口(抽象)编程,而不是面向具体的实现来编程,这样一旦我们需要切换到当前接口的其他实现就无需修改代码。
在 Java
中,数据库驱动就使用到了 SPI
技术,每次我们只需要引入数据库驱动就能被加载的原因就是因为使用了 SPI
技术。
打开 DriverManager
类,其初始化驱动的代码如下:
进入 ServiceLoader
方法,发现其内部定义了一个变量:
private static final String PREFIX = “META-INF/services/”;
这个变量在下面加载驱动的时候有用到,下图中的 service
即 java.sql.Driver
:
所以就是说,在数据库驱动的 jar
包下面的 META-INF/services/
下有一个文件 java.sql.Driver
,里面记录了当前需要加载的驱动,我们打开这个文件可以看到里面记录的就是驱动的全限定类名:
@AutoConfigurationPackage 注解
从这个注解继续点进去之后可以发现,它最终还是一个 @Import
注解:
这个时候它导入了一个 AutoConfigurationPackages
的内部类 Registrar
, 而这个类其实作用就是读取到我们在最外层的 @SpringBootApplication
注解中配置的扫描路径(没有配置则默认当前包下),然后把扫描路径下面的类都加到数组中返回。
===========================================================================
了解完自动装配的原理,接下来就可以动手写一个自己的 starter
组件了。
SpringBoot
官方的建议是,如果是我们开发者自己开发的 starter
组件(即属于第三方组件),那么命名规范是{name}-spring-boot-starter
,而如果是 SpringBoot
官方自己开发的组件,则命名为 spring-boot-starter
-{name}`。
当然,这只是一个建议,如果非不按这个规则也没什么问题,但是为了更好的识别区分,还是建议按照这个规则来命名。
写一个非常简单的组件,这个组件只做一件事,那就是实现 fastjson
序列化。
-
新建一个
SpringBoot
应用lonelyWolf-spring-boot-starter
。 -
修改
pom
文件,并新增fastjson
依赖(省略了部分属性)。
org.springframework.boot
spring-boot-starter-parent
2.4.0
com.lonely.wolf.note
lonelyWolf-spring-boot-starter
1.0.0-SNAPSHOT
org.springframework.boot
spring-boot-starter
com.alibaba
fastjson
1.2.72
- 新建一个序列化类
JsonSerial
类来实现fastjson
序列化。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
总结
三个工作日收到了offer,头条面试体验还是很棒的,这次的头条面试好像每面技术都问了我算法,然后就是中间件、MySQL、Redis、Kafka、网络等等。
- 第一个是算法
关于算法,我觉得最好的是刷题,作死的刷的,多做多练习,加上自己的理解,还是比较容易拿下的。
而且,我貌似是将《算法刷题LeetCode中文版》、《算法的乐趣》大概都过了一遍,尤其是这本
《算法刷题LeetCode中文版》总共有15个章节:编程技巧、线性表、字符串、栈和队列、树、排序、查找、暴力枚举法、广度优先搜索、深度优先搜索、分治法、贪心法、动态规划、图、细节实现题
《算法的乐趣》共有23个章节:
- 第二个是Redis、MySQL、kafka(给大家看下我都有哪些复习笔记)
基本上都是面试真题解析、笔记和学习大纲图,感觉复习也就需要这些吧(个人意见)
- 第三个是网络(给大家看一本我之前得到的《JAVA核心知识整理》包括30个章节分类,这本283页的JAVA核心知识整理还是很不错的,一次性总结了30个分享的大知识点)
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
20733)]
- 第二个是Redis、MySQL、kafka(给大家看下我都有哪些复习笔记)
基本上都是面试真题解析、笔记和学习大纲图,感觉复习也就需要这些吧(个人意见)
[外链图片转存中…(img-SZridVFx-1713322720733)]
- 第三个是网络(给大家看一本我之前得到的《JAVA核心知识整理》包括30个章节分类,这本283页的JAVA核心知识整理还是很不错的,一次性总结了30个分享的大知识点)
[外链图片转存中…(img-k0Xgg2mN-1713322720734)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!