什么是 Spring Boot?
SpringBoot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手。
为什么要用Spring Boot?
Spring Boot 优点非常多,如:
一、独立运行
Spring Boot而且内嵌了各种servlet容器,Tomcat、Jetty等,现在不再需要打成war包部署到容器中,Spring Boot只要打成一个可执行的jar包就能独立运行,所有的依赖包都在一个jar包内。
二、简化配置
spring-boot-starter-web启动器自动依赖其他组件,简少了maven的配置。
过去springmvc的时候或者ssm整合时,使用了大量包
三、自动配置
Spring Boot能根据当前类路径下的类、jar包来自动配置bean,如添加一个spring-boot-starter-web启动器就能拥有web的功能,无需其他配置。
四、无代码生成和XML配置
Spring Boot配置过程中无代码生成,也无需XML配置文件就能完成所有配置工作,这一切都是借助于条件注解完成的,这也是Spring4.x的核心功能之一。(@Conditional根据满足某一个特定条件创建一个特定的Bean。比如说,当某一个jar包在某一个类路径下的时候,自动配置一个或者多个Bean;或者只有某个Bean被创建才会创建另外一个Bean。总的来说,就是根据特定条件来控制Bean的创建行为,这样我们可以利用这个特性进行一些自动的配置。)
用法参考项目:conditional_demo
五、应用监控
Spring Boot提供一系列端点可以监控服务及应用,做健康检测。
Spring
Boot 的核心配置文件有哪几个?它们的区别是什么?
spring cloud官网:
https://cloud.spring.io/spring-cloud-static/Greenwich.SR1/single/spring-cloud.html#_the_bootstrap_application_context
Spring Boot 中有以下两种配置文件:
bootstrap (.yml 或者 .properties)
application (.yml 或者 .properties)
bootstrap/ application 的区别:
Spring Cloud 构建于Spring Boot 之上,在 Spring Boot 中有两种上下文,一种是 bootstrap,,另外一种是application,,bootstrap 是应用程序的父上下文,也就是说 bootstrap 加载优先于 applicaton。bootstrap 主要用于从额外的资源来加载配置信息,还可以在本地外部配置文件中解密属性。这两个上下文共用一个环境,它是任何Spring应用程序的外部属性的来源。bootstrap 里面的属性会优先加载,它们默认也不能被本地相同配置覆盖。
因此,对比 application 配置文件,bootstrap 配置文件具有以下几个特性:
boostrap 由父 ApplicationContext 加载,比 applicaton 优先加载
boostrap 里面的属性不能被覆盖
bootstrap/ application 的应用场景:
application 配置文件这个容易理解,主要用于 Spring Boot 项目的自动化配置。
bootstrap 配置文件有以下几个应用场景:
使用 Spring Cloud Config 配置中心时,这时需要在 bootstrap 配置文件中添加连接到配置中心的配置属性来加载外部配置中心的配置信息;
一些固定的不能被覆盖的属性
一些加密/解密的场景。
Spring
Boot 的配置文件有哪几种格式?它们有什么区别?
.properties 和 .yml,它们的区别主要是书写格式不同。
1).properties
server.port=8081
2).yml
server:
port: 8082
另外,.yml 格式不支持 @PropertySource 注解导入配置。
yml的优先级高于.properties 可以两个配置文件中都配置访问端口号,看哪个配置生效
Spring
Boot 的核心注解是哪个?它主要由哪几个注解组成的?
启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:
@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。
@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能: @SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class })。
@ComponentScan:Spring组件扫描。
开启Spring Boot 特性有哪几种方式?
有以下两种方式:
1. 继承spring-boot-starter-parent项目(普通spring-boot项目)
2. 导入spring-boot-dependencies项目依赖(参考时springcloud项目搭建的方法)
org.springframework.boot
spring-boot-dependencies
${spring-boot.version}
pom
import
dependencyManagement和 dependencies区别
dependencyManagement当使用父子项目创建工程架构时,父项目可以使用该标签
来规定子项目可以使用哪些包,但是并不是直接引入,而是子项目按需引入,并且引入
时不需要加版本号
dependencies使用的话,直接父项目把所有包都引入了,不管子项目是否用得到
import maven默认也是单继承 加上import 相当于父项目中使用了
多继承,既有springcloud的所有包,又有springboot的所有包,子项目,可以直接使用
Spring Boot依赖注意点:
1. 属性覆盖只对继承有效
Spring Boot依赖包里面的组件的版本都是和当前Spring
Boot绑定的,如果要修改里面组件的版本,只需要添加如下属性覆盖即可,但这种方式只对继承有效,导入的方式无效。
1.7.25
如果导入的方式要实现版本的升级,达到上面的效果,这样也可以做到,把要升级的组件依赖放到Spring Boot之前。需要注意,要修改Spring Boot的依赖组件版本可能会造成不兼容的问题。
Spring
Boot 需要独立的容器运行吗?
可以不需要,内置了 Tomcat/Jetty 等容器。
模拟内置tomcat功能,参考项目:embed_tomcat
1,创建普通的java项目
2,引入jar包
org.apache.tomcat.embed
tomcat-embed-core
8.5.51
org.apache.tomcat.embed
tomcat-embed-el
8.5.51
org.apache.tomcat.embed
tomcat-embed-jasper
8.5.51
3,编写启动类
package com.aaa;
import
org.apache.catalina.Context;
import
org.apache.catalina.WebResourceRoot;
import
org.apache.catalina.startup.Tomcat;
import
org.apache.catalina.webresources.DirResourceSet;
import
org.apache.catalina.webresources.StandardRoot;
import
java.io.File;
/**
* fileName:SpringApplication
* description:
* author:zz
* createTime:2020/2/26 18:17
* version:1.0.0
*/
public
class SpringApplication {
/**
*模拟内置tomcat
*/
public static void run(){
//创建tomcat实例
Tomcat tom = new Tomcat();
//设置端口
tom.setPort(8888);
try{
//获取项目编译后的class 路径
String path =SpringApplication.class.getResource("/").getPath();
//获取webapp 文件D:\idea_qy107\embed_tomcat\src\main\webapp
String filePath = newFile("src/main/webapp").getAbsolutePath();
//然后将webapp下的项目添加至tomcat的context容器(context对应一个运行的项目)
Context context=tom.addWebapp("/my_web_app",filePath);
//参数1:一般是项目名 对应请求url中的项目名
//webResourceRoot用于加载 项目的class文件
WebResourceRoot webResource = newStandardRoot(context);
webResource.addPreResources(newDirResourceSet(webResource,"/WEB-INF/classes",path,"/"));
tom.start();
}catch (Exception e) {
e.printStackTrace();
}
//阻塞
,等待前端连接
tom.getServer().await();
}
}
运行 Spring Boot 有哪几种方式?
1)打包用命令或者放到容器中运行
在jar所在位置,shift+鼠标右键 打开命令行,输入命令:
java -jar spring_boot_interview_question.jar [启动类]
2)用 Maven/Gradle 插件运行
进入项目目录,执行下面命令
mvn spring-boot:run
启动测试:
http://localhost:8082/showEntity
ctrl+c终止运行,如果是cmd命令窗口,直接关闭就可以了
3)直接执行main 方法运行
Spring
Boot 自动配置原理是什么?
为自动配置做铺垫:
@import三种用法:
直接将pojo类注入到Spring IOC容器
1, 创建java类:
public class PojoClass {
//空构造
public PojoClass() {
System.out.println("PojoClass交给了spirngioc管理了。。。 ");
}
}
2,在@Configuration注解的类上加入@Import(value = {PojoClass.class})
3,测试
把它注入到任意一个已经交给spring管理的类中
@Autowired
private PojoClass pojoClass;
public Emp getById(Integer empNo){
System.out.println("springioc容器中是否存在pojoClass对象:"+pojoClass);
return empService.getById(empNo);
}
通过ImportBeanDefinitionRegistrar将类注入到Spring IOC容器。
1, 创建java类:
public class BeanDefinitionRegisterClass {
public BeanDefinitionRegisterClass() {
System.out.println("通过ImportBeanDefinitionRegistrar接口把该类交给springioc容器进行管理。。。");
}
}
2,创建ImportBeanDefinitionRegistrar实现类
public class MyImportBeanDefinitionRegisterimplements ImportBeanDefinitionRegistrar {
@Override
public voidregisterBeanDefinitions(AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry) {
//交给springioc容器管理的是BeanDefinition bean定义
RootBeanDefinition rootBeanDefinition=new RootBeanDefinition(BeanDefinitionRegisterClass.class);
registry.registerBeanDefinition("beanDefinitionRegisterClass",rootBeanDefinition);
}
}
3,在@Configuration注解的类上加入@Import(value ={MyImportBeanDefinitionRegister.class})
4,测试
@Autowired
private BeanDefinitionRegisterClass beanDefinitionRegisterClass;
publicEmp getById(Integer empNo){
System.out.println("springioc容器中是否存在pojoClass对象:"+pojoClass);
System.out.println("springioc容器中是否存在beanDefinitionRegisterClass对象:"+beanDefinitionRegisterClass);
return empService.getById(empNo);
}
通过ImportSelector方式注入Bean
1,创建多个java类
publicclass ImportSelectorClassA {
public ImportSelectorClassA() {
System.out.println("通过ImportSelector接口把该类ImportSelectorClassA交给springioc容器进行管理。。。");
}
}
2,创建ImportSelector的实现类
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return newString[]{"com.aaa.sbac.ac2.entity.ImportSelectorClassA",
"com.aaa.sbac.ac2.entity.ImportSelectorClassB"};
}
}
3,在@Configuration注解的类上加入@Import(value ={MyImportSelector.class})
4,测试
测试同上
参考项目:spring_boot_auto_configuration第3个例子:com.aaa.sbac.ac3包的例子:
Spring Boot的自动配置注解是@EnableAutoConfiguration, 从上面的@Import的类可以找到下面自动加载自动配置的映射。
URL url =
urls.nextElement();
这个方法会加载类路径及所有jar包下META-INF/spring.factories配置中映射的自动配置的类。
public
static final String FACTORIES_RESOURCE_LOCATION =
"META-INF/spring.factories";
查看Spring
Boot自带的自动配置的包:org.springframework.boot:spring-boot-autoconfigure-2.2.4.RELEASE.jar,打开其中的META-INF/spring.factories文件会找到自动配置的映射。
再来看看数据源自动配置的实现注解
@Configuration,@ConditionalOnClass就是自动配置的核心,首先它得是一个配置文件,其次根据类路径下是否有这个类去自动配置。