Spring
一、Spring Bean 的生命周期
- Bean 容器找到配置文件中 Spring Bean 的定义。
- Bean 容器利用 Java Reflection API 创建一个 Bean 的实例。
- 如果涉及到一些属性值,利用 set()方法设置一些属性值。
- 如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName()方法,传入 Bean 的名字。
- 如果 Bean 实现了 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader 对象的实例。
- 如果 Bean 实现了 BeanFactoryAware 接口,调用 setBeanClassFacotory()方法,传入 ClassLoader 对象的实例。
- 与上面的类似,如果实现了其他*Aware 接口,就调用相应的方法。
- 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行 postProcessBeforeInitialization()方法。
- 如果 Bean 实现了 InitializingBean 接口,执行 afeterPropertiesSet()方法。
- 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
- 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcess 对象,执行 postProcessAfterInitialization()方法。
- 当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy()方法。
- 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。
总结以上步骤,核心主干主要就是五部分构成:
- 构造 Bean 对象
- 设置 Bean 属性
- 初始化回调
- Bean 调用
- 销毁 Bean
二、IOC 概念解析
IOC(Inversion Of Controll,控制反转)是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由给 Spring 框架来管理。Spring IOC 负责创建对象,管理对象。通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期。IOC 容器实际上就是一个 Map(key, value),Map 中存放的是各种对象。
将对象之间的相互依赖关系交给 IOC 容器来管理,并由 IOC 容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。IOC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。
三、IOC 中 Bean 的注入方式
- 构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。
- Setter 方法注入:Setter 方法注入是容器通过调用无参构造器或无参 static 工厂方法实例化 bean 之后,调用该 bean 的 Setter 方法,即实现了基于 Setter 的依赖注入。
- 基于注解的注入:最好的解决方案是用构造器参数实现强制依赖,Setter 方法实现可选依赖。
四、重要的 Spring 注解
@Component
- 用于服务类。@Service
、@Repository
、@Controller
@Autowired
- 用于在 spring bean 中自动装配依赖项。通过类型来实现自动注入 bean。和@Qualifier
注解配合使用可以实现根据 name 注入 bean。@Qualifier
- 和@Autowired
一块使用,在同一类型的 bean 有多个的情况下可以实现根据 name 注入的需求。@Scope
- 用于配置 spring bean 的范围。@Configuration
,@ComponentScan
和@Bean
- 用于基于 java 的配置。@Aspect
,@Before
,@After
,@Around
,@Pointcut
- 用于切面编程(AOP)
五、AOP 详解
AOP 是什么?
AOP:全称 Aspect Oriented Programming,即:面向切面编程。
AOP(Aspect-Oriented Programming,面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可扩展性和可维护性。
Spring AOP 是基于动态代理的,如果要代理的对象实现了某个接口,那么 Spring AOP 就会使用 JDK 动态代理去创建代理对象;而对于没有实现接口的对象,就无法使用 JDK 动态代理,转而使用 CGlib 动态代理生成一个被代理对象的子类来作为代理。当然也可以使用 AspectJ,Spring AOP 中已经集成了 AspectJ, AspectJ 应该算得上是 Java 生态系统中最完整的 AOP 框架了。使用 AOP 之后我们可以把一些通用功能抽象出来,在需要用到的地方直接使用即可,这样可以大大简化代码量。我们需要增加新功能也方便,提高了系统的扩展性。日志功能、事务管理和权限管理等场景都用到了 AOP。
AOP 的基本概念
- **切面(Aspect):**官方的抽象定义为“一个关注点的模块化,这个关注点可能会横切多个对象”。
- **连接点(Joinpoint):**程序执行过程中的某一行为。
- 通知(Advice):“切面”对于某个“连接点”所产生的动作。
- **切入点(Pointcut):**匹配连接点的断言,在 AOP 中通知和一个切入点表达式关联。
- **目标对象(Target Object):**被一个或者多个切面所通知的对象。
- **AOP 代理(AOP Proxy):**在 Spring AOP 中有两种代理方式,JDK 动态代理和 CGLIB 代理。
AOP 的代理方式(AOP 的实现原理)
AOP 思想的实现一般都是基于代理模式,在 Java 中一般采用 JDK 动态代理模式,但是我们都知道,JDK 动态代理模式只能代理接口而不能代理类。因此,Spring AOP 会按照下面两种情况进行切换,因为 Spring AOP 同时支持 CGLIB、ASPECTJ、JDK 动态代理。
如果目标对象的实现类实现了接口,Spring AOP 将会采用 JDK 动态代理来生成 AOP 代理类;
如果目标对象的实现类没有实现接口,Spring AOP 将会采用 CGLIB 来生成 AOP 代理类。不过这个选择过程对开发者完全透明、开发者也无需关心。
AOP 主要应用场景
- 事务管理
- 日志
- 性能监视
- 安全检查
- 缓存
六、Spring Bean 的作用域
Spring 框架支持以下五种 bean 的作用域:
singleton
:唯一 bean 实例,Spring 中的 bean 默认都是单例的。prototype
:每次请求都会创建一个新的 bean 实例。request
:每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。session
:每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。global-session
:全局 session 作用域,仅仅在基于 Portlet 的 Web 应用中才有意义,Spring5 中已经没有了 Portlet。
七、Spring 框架中的单例 bean 线程安全问题
大部分时候我们并没有在系统中使用多线程,所以很少有人会关注这个问题。单例 bean 存在线程问题,主要是因为当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。
有两种常见的解决方案:
- 在 bean 对象中尽量避免定义可变的成员变量(不太现实)。
- 在类中定义一个 ThreadLocal 成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。
八、Spring 事务管理方式
- 编程式事务:在代码中硬编码。
- 声明式事务:在配置文件中配置声明式事务又分为:
- 基于 XML 的声明式事务
- 基于注解的声明式事务
九、Spring 事务传播行为
事务传播行为是为了解决业务层方法之间互相调用的事务问题。当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。在 TransactionDefinition 定义中包括了如下几个表示传播行为的常量:
支持当前事务的情况:
TransactionDefinition.PROPAGATION_REQUIRED
:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务;TransactionDefinition.PROPAGATION_SUPPORTS
:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行;TransactionDefinition.PROPAGATION_MANDATORY
:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
不支持当前事务的情况:
TransactionDefinition.PROPAGATION_REQUIRES_NEW
:创建一个新的事务,如果当前存在事务,则把当前事务挂起;TransactionDefinition.PROPAGATION_NOT_SUPPORTED
:以非事务方式运行,如果当前存在事务,则把当前事务挂起。TransactionDefinition.PROPAGATION_NEVER
:以非事务方式运行,如果当前存在事务,则抛出异常。
其他情况:
TransactionDefinition.PROPAGATION_NESTED
:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 TransactionDefinition.PROPAGATION_REQUIRED
。
十、Spring 中的事务实现原理
- Spring 事务底层是基于数据库事务和 AOP 机制的
- 首先对于使用了
@Transactional
注解的 Bean,Spring 会创建一个代理对象作为 Bean - 当调用代理对象的方法时,会先判断该方法上是否加了
@Transactional
注解 - 如果加了,那么则利用事务管理器创建一个数据库连接
- 并且修改数据库连接的
autocommit
属性为false
,禁止此连接的自动提交,这是实现 Spring 事务非常重要的一步 - 然后执行当前方法,方法中会执行 sql
- 执行完当前方法后,如果没有出现异常就直接提交事务
- 如果出现了异常,并且这个异常是需要回滚的就会回滚事务,否则仍然提交事务
- Spring 事务的隔离级别对应的就是数据库的隔离级别
- Spring 事务的传播机制是 Spring 事务自己实现的,也是 Spring 事务中最复杂的
- Spring 事务的传播机制是基于数据库连接来做的,一个数据库连接一个事务,如果传播机制配置为需要新开一个事务,那么实际上就是先建立一个数据库连接,在此新数据库连接上执行 sql
十一、Spring 中的设计模式
- 工厂模式:Spring 借助 BeanFactory 和 ApplicationContext 运用工厂模式来创建 bean 对象。
- 单例模式:Spring 中的 bean 默认采用单例模式。
- 代理模式:Spring 的 AOP 功能运用了 JDK 的动态代理和 CGLIB 字节码生成技术来实现。
- 模板方法:用于解决代码重复问题,像以 Template 结尾的对数据库操作的类,如 RestTemplate、jdbcTemplate、JpaTemplate 等都运用了此模式。
- 观察者模式:Spring 事件驱动模型是其经典应用,定义了对象间一对多的依赖关系,当对象状态改变时,依赖对象会被通知并自动更新,如 Spring 中的 ApplicationListener。
- 包装器设计模式:在项目连接多个数据库且不同客户按需访问不同数据库的场景中,此模式可实现动态切换数据源。
- 适配器模式:Spring AOP 的增强或通知(Advice)以及 Spring MVC 中的 Controller 适配都用到了适配器模式。
十二、Spring 解决循环依赖的方法
整个 IOC 容器解决循环依赖,用到的几个重要成员:
singletonObjects
:一级缓存,存放完全初始化好的 Bean 的集合,从这个集合中取出来的 Bean 可以立马返回earlySingletonObjects
:二级缓存,存放创建好但没有初始化属性的 Bean 的集合,它用来解决循环依赖singletonFactories
:三级缓存,存放单实例 Bean 工厂的集合singletonsCurrentlyInCreation
:存放正在被创建的 Bean 的集合
IOC 容器解决循环依赖的思路:
- 初始化 Bean 之前,将这个 BeanName 放入三级缓存
- 创建 Bean 将准备创建的 Bean 放入
singletonsCurrentlyInCreation
(正在创建的 Bean) createNewInstance
(创建新实例) 方法执行完后执行addSingletonFactory
,将这个实例化但没有属性赋值的 Bean 放入二级缓存,并从三级缓存中移除- 属性赋值&自动注入时,引发关联创建
- 关联创建时,检查“正在被创建的 Bean”中是否有即将注入的 Bean。如果有,检查二级缓存中是否有当前创建好但没有赋值初始化的 Bean。如果没有,检查三级缓存中是否有正在创建中的 Bean。至此一般会有,将这个 Bean 放入二级缓存,并从三级缓存中移除
- 之后 Bean 被成功注入,最后执行
addSingleton
,将这个完全创建好的 Bean 放入一级缓存,从二级缓存和三级缓存移除,并记录已经创建了的单实例 Bean。
SpringMVC
一、SpringMVC 执行流程(工作原理)
MVC 是 Model
(模型)— View
(视图)— Controller
(控制器)的简称,它是一种架构模式,分离了表现与交互,被分为三个核心部件:模型(Model
)、视图(View
)、控制器(Controller
)。
- 用户发送出请求到前端控制器
DispatcherServlet
。(关键第一步,所有请求的入口) DispatcherServlet
收到请求调用HandlerMapping
(处理器映射器)。HandlerMapping
找到具体的处理器(可查找 xml 配置或注解配置),生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet
。DispatcherServlet
调用HandlerAdapter
(处理器适配器)。HandlerAdapter
经过适配调用具体的处理器(Handler
/Controller
)。Controller
执行完成返回ModelAndView
对象。HandlerAdapter
将Controller
执行结果ModelAndView
返回给DispatcherServlet
。DispatcherServlet
将ModelAndView
传给ViewReslover
(视图解析器)。ViewReslover
解析后返回具体View
(视图)。DispatcherServlet
根据View
进行渲染视图(即将模型数据填充至视图中)。DispatcherServlet
响应用户。(最后一步,响应请求)
二、SpringMVC 的常用组件有哪些?
- 前端控制器 DispatcherServlet
作用:Spring MVC 的入口函数。接收请求,响应结果,相当于转发器,中央处理器。有了DispatcherServlet
减少了其它组件之间的耦合度。用户请求到达前端控制器,它就相当于 MVC 模式中的C
(Controller),DispatcherServlet
是整个流程控制的中心,由它调用其它组件处理用户的请求,DispatcherServlet
的存在降低了组件之间的耦合性。 - 处理器映射器 HandlerMapping
作用:根据请求的url
查找Handler
。HandlerMapping
负责根据用户请求找到Handler
即处理器(Controller
),SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。 - 处理器适配器 HandlerAdapter
作用:按照特定规则(HandlerAdapter
要求的规则)去执行Handler
。通过HandlerAdapter
对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。 - 处理器 Handler
注意:编写Handler
时按照HandlerAdapter
的要求去做,这样适配器才可以去正确执行Handler
。Handler
是继DispatcherServlet
前端控制器的后端控制器,在DispatcherServlet
的控制下Handler
对具体的用户请求进行处理。由于Handler
涉及到具体的用户业务请求,所以一般情况需要工程师根据业务需求开发Handler
。 - 视图解析器 View resolver
作用:进行视图解析,根据逻辑视图名解析成真正的视图(View
)。View Resolver
负责将处理结果生成View
视图,View Resolver
首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View
视图对象,最后对View
进行渲染将处理结果通过页面展示给用户。SpringMVC 框架提供了很多的View
视图类型,包括:jstlView
、freemarkerView
、pdfView
等。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由工程师根据业务需求开发具体的页面。 - 视图 View
View
是一个接口,实现类支持不同的View
类型(jsp
、freemarker
…)。
处理器Handler
(也就是我们平常说的Controller
控制器)以及视图层View
都是需要我们自己手动开发的。其他的一些组件比如:前端控制器DispatcherServlet
、处理器映射器HandlerMapping
、处理器适配器HandlerAdapter
等等都是框架提供给我们的,不需要自己手动开发。
三、SpringMVC 的常用注解有哪些?
@RequestMapping
:用于映射请求路径,可以定义在类上和方法上。用于类上,则表示类中的所有的方法都是以该地址作为父路径。@RequestBody
:注解实现接收 http 请求的 json 数据,将 json 转换为 java 对象。@RequestParam
:指定请求参数的名称。@PathViriable
:从请求路径下中获取请求参数(/user/{id}),传递给方法的形式参数。@ResponseBody
:注解实现将 controller 方法返回对象转化为 json 对象响应给客户端。@RequestHeader
:获取指定的请求头数据。
四、SpringMVC 如何处理统一异常?
方式一: 创建一个自定义异常处理器(实现 HandlerExceptionResolver 接口),并实现里面的异常处理方法,然后将这个类交给 Spring 容器管理。
方式二: 在类上加注解(@ControllerAdvice
)表明这是一个全局异常处理类,在方法上加注解(@ExceptionHandler
),在ExceptionHandler
中有一个 value 属性,可以指定可以处理的异常类型。
Mybatis
一、Mybatis #{}和${}的区别
#{}
是预编译处理,${}
是字符串替换。- Mybatis 在处理
#{}
时,会将 sql 中的#{}
替换为?号,调用PreparedStatement
的set
方法来赋值; - Mybatis 在处理
${}
时,就是把${}
替换成变量的值。 - 使用
#{}
可以有效的防止 SQL 注入,提高系统安全性。
二、当实体类中的属性名和表中的字段名不一样,怎么办
第 1 种:通过在查询的 SQL 语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。
第 2 种:通过<resultMap>
来映射字段名和实体类属性名的一一对应的关系。
三、MyBatis 是如何进行分页的?分页插件的原理是什么?
Mybatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的内存分页,而非物理分页。可以在 sql 内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用 Mybatis 提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的 sql,然后重写 sql,根据 dialect 方言,添加对应的物理分页语句和物理分页参数。
四、MyBatis 动态 SQL 了解吗?
- MyBatis 动态 SQL 可以让我们在 XML 映射文件内,以标签的形式编写动态 SQL,完成逻辑判断和动态拼接 SQL 的功能;
- MyBatis 提供了 9 种动态 SQL 标签:trim、where、set、foreach、if、choose、when、otherwise、bind;
- 执行原理:使用 OGNL 从 SQL 参数对象中计算表达式的值,根据表达式的值动态拼接 SQL,以此来完成动态 SQL 的功能。
五、MyBatis 缓存?
一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现 Serializable 序列化接口(可用来保存对象的状态),可在它的映射文件中配置。
对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存 Namespaces)的进行了 cud 操作后,默认该作用域下所有 select 中的缓存将被 clear 掉并重新更新,如果开启了二级缓存,则只根据配置判断是否刷新。
六、ResultType 和 ResultMap 的区别?
如果数据库结果集中的列名和要封装实体的属性名完全一致的话用 resultType 属性。
如果数据库结果集中的列名和要封装实体的属性名有不一致的情况用 resultMap 属性,通过 resultMap 手动建立对象关系映射,resultMap 要配置一下表和类的一一对应关系,所以说就算你的字段名和你的实体类的属性名不一样也没关系,都会给你映射出来。
七、MyBatis 中有哪些设计模式?
Mybatis 至少遇到了以下的设计模式的使用:
- Builder 模式,例如 SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder;
- 工厂模式,例如 SqlSessionFactory、ObjectFactory、MapperProxyFactory;
- 单例模式,例如 ErrorContext 和 LogFactory;
- 代理模式,Mybatis 实现的核心,比如 MapperProxy、ConnectionLogger,用的 jdk 的动态代理;还有 executor.loader 包使用了 cglib 或者 javassist 达到延迟加载的效果;
- 组合模式,例如 SqlNode 和各个子类 ChooseSqlNode 等;
- 模板方法模式,例如 BaseExecutor 和 SimpleExecutor,还有 BaseTypeHandler 和所有的子类例如 IntegerTypeHandler;
- 适配器模式,例如 Log 的 Mybatis 接口和它对 jdbc、log4j 等各种日志框架的适配实现;
- 装饰者模式,例如 Cache 包中的 cache.decorators 子包中等各个装饰者的实现;
- 迭代器模式,例如迭代器模式 PropertyTokenizer。
SpringBoot
一、为什么用 SpringBoot(优点)?
简单回答:
Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手。
二、运行 SpringBoot 有哪几种方式?
- 打包用命令或者放到容器中运行。
- 用 Maven/ Gradle 插件运行。
- 直接执行 main 方法运行。
三、讲一讲 SpringBoot 自动装配的原理
在 Spring Boot 项目中的引导类上有一个注解@SpringBootApplication
,这个注解是对三个注解进行了封装,分别是:
@SpringBootConfiguration
、@EnableAutoConfiguration
、@ComponentScan
。
其中@EnableAutoConfiguration
是实现自动化配置的核心注解。
该注解通过@Import
注解导入对应的配置选择器。关键的是内部就是读取了该项目和该项目引用的 Jar 包的的 classpath 路径下 META-INF/spring.factories 文件中所配置的类的全类名。
在这些配置类中所定义的 Bean 会根据条件注解所指定的条件来决定是否需要将其导入到 Spring 容器中。一般条件判断会有像@ConditionalOnClass
这样的注解,判断是否有对应的 class 文件,如果有则加载该类,把这个配置类的所有的 Bean 放入 spring 容器中使用。
四、讲一讲 SpringBoot 启动流程
springboot 项目在启动的时候, 首先会执行启动引导类里面的SpringApplication.run(AdminApplication.class, args)
方法。
这个 run 方法主要做的事情可以分为三个部分 :
第一部分进行 SpringApplication 的初始化模块,配置一些基本的环境变量、资源、构造器、监听器。
第二部分实现了应用具体的启动方案,包括启动流程的监听模块、加载配置环境模块、及核心的创建上下文环境模块。
第三部分是自动化配置模块,该模块作为 springboot 自动配置核心。
五、Spring Boot 的核心注解是哪个?他由哪几个注解组成的?
Spring Boot 的核心注解是@SpringBootApplication
, 他由几个注解组成 :
@SpringBootConfiguration
:组合了@Configuration
注解,实现配置文件的功能;@EnableAutoConfiguration
:打开自动配置的功能,也可以关闭某个自动配置的选项;@ComponentScan
:Spring 组件扫描。
六、SpringBoot 可以有哪些方式加载配置?
- properties 文件;
- YAML 文件;
- 系统环境变量;
- 命令行参数。
七、Spring Boot 中的 starter 到底是什么?
依赖管理对于项目至关重要。当项目足够复杂时,管理依赖项可能会变成一场噩梦,因为涉及的组件太多了。这就是 Spring Boot 的 starter 就派上用场了。每个 starter 都可以为我们提供所需要的 Spring 技术的一站式服务。并且以一致的方式传递和管理其他所需的依赖关系。所有官方 starter 都在 org.springframework.boot 组下,其名称以 spring-boot-starter-开头。非官方的 starter 的名称在前,如 mybatis-spring-boot-starter。这种命名模式使得查找启动器变得很容易,尤其是在使用支持按名称搜索依赖关系的 IDE 时。但是这个不是绝对的,有些开发者可能不遵从这种契约。
目前大概有超过 50 种官方 starter。
在导入的 starter 之后,SpringBoot 主要帮我们完成了两件事情:
- 相关组件的自动导入;
- 相关组件的自动配置。
这两件事情统一称为 SpringBoot 的自动配置。
八、SpringBoot 常用的 starter 有哪些?
- spring-boot-starter:核心启动器,包括自动配置支持,日志记录和 YAML。
- spring-boot-starter-web (嵌入 tomcat 和 web 开发需要 servlet 与 jsp 支持)。
- spring-boot-starter-test -单元测试和集成测试。
- spring-boot-starter-jdbc -传统的 JDBC。
- spring-boot-starter-security -使用 SpringSecurity 进行身份验证和授权。
- spring-boot-starter-data-jpa (数据库支持)。
- spring-boot-starter-data-redis (redis 数据库支持)。
- spring-boot-starter-data-amqp (MQ 支持)。
- mybatis-spring-boot-starter (第三方的 mybatis 集成 starter)。
九、bootstrap.yml 和 application.yml 有何区别?
SpringBoot 两个核心的配置文件:
- bootstrap(.yml 或者.properties):boostrap 由父 ApplicationContext 加载,比 applicaton 优先加载,配置在应用程序上下文的引导阶段生效。一般来说我们在 SpringCloud Config 或者 Nacos 中会用到它。且 boostrap 里面的属性不能被覆盖。
- application (.yml 或者.properties):由 ApplicatonContext 加载,用于 SpringBoot 项目的自动化配置。