1.SpringBoot简介
- springboot是什么?
SpringBoot是整合Spring技术栈的一站式框架
SpringBoot是简化Spring技术栈的快速开发脚手架 - SpringBoot优点
创建独立Spring应用
内嵌web服务器
自动starter依赖,简化构建配置
自动配置Spring以及第三方功能
提供生产级别的监控、健康检查及外部化配置
无代码生成、无需编写XML - SpringBoot缺点
人称版本帝,迭代快,需要时刻关注变化
封装太深,内部原理复杂,不容易精通
官网文档架构
2.springboot 入门
2.1环境搭建
- 系统要求
• Java 8 & 兼容java14 .
• Maven 3.3+
• idea - maven配置
配置阿里云镜像;配置使用1.8编译
2.2 HelloWorld
需求:浏览发送/hello请求,响应 Hello,Spring Boot 2
- 创建maven工程
- 引入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.4</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
- 创建主程序()
@SpringBootApplication // 来标注一个主程序类,说明这是一个Spring Boot应用
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class,args);
}
}
注意:@SpringBootApplication默认的扫描位置就是主程序所在类的包及子包。所以我们在创建主程序类时应在组件的上一层包内创建主程序类
- 编写业务
@RestController //是 @ResponseBody和@Controller的组合写法
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "Hello, Spring Boot 2!";
}
}
-
测试
启动主程序类的面方法 -
简化配置
可以在resources下创建application.properties文件直接进行参数配置
-
简化部署(将这个应用打成jar包,直接使用java -jar的命令进行执行;)
<!-- 这个插件,可以将应用打包成一个可执行的jar包;-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
注意点:取消掉cmd的快速编辑模式(防止启动时点击鼠标会造成启动异常)
3.了解自动配置原理*****
3.1依赖管理和自动配置
3.1.1依赖管理
在2.2的helloword测试中我们看到只引入了一个父依赖和一个starter就完成了测试这就是spring给我们提供的版本仲裁和starter场景启动器
3.1.1.1开发导入starter场景启动器
疑问:helloword测试中我们并没有手动引入web相关的jar就完成了各个jar包的引入?
原理:这就是starter场景启动器起的作用。helloword测试中,我们引入了spring-boot-starter-web依赖,这个starter依赖或这个starter依赖的子依赖,帮我们引入了所有我们在使用web功能可能需要使用的jar包
- 以后我们在springboot中会见到很多见到很多 spring-boot-starter-xx格式的场景启动器,这个xx就是我们所需要使用的功能->例:spring-boot-starter-aop
- 只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
- 以后见到的 *-spring-boot-starter: 第这就是三方为我们提供的简化开发的场景启动器。
- 所有场景启动器最底层的依赖:spring-boot-starter
3.1.1.2版本仲裁
疑问 hello测试中我们并没有对引入的jar包进行版本号的指定
原理:上图的spring-boot-starter-parent它的父项目依赖是下图
而在spring-boot-dependencies中spring为我们提供了我们项目中几乎能用到的所有jar包的版本依赖,这就是springboot给我们提供的版本仲裁机制。
注:引入依赖默认都可以不写版本,引入非版本仲裁的jar,要写版本号
**疑问:**版本仲裁机制为我们指定了jar的版本若我们不想使用spring提供的依赖该怎么办?
答:在当前项目里面重写配置
<properties>
<mysql.version>5.1.</mysql.version>
</properties>
3.1.2自动配置
疑问:虽然自动依赖帮我们引入好了jar包但是我们并没有对tomcat、springmvc、web组件的功能进行配置,为什么我们就可以使用这些功能了?
原理:点开spring-boot-starter-web我们可以看到里面引入了如下
依赖,而这些依赖不仅引入了需要的jar包而且还对这些组件进行了默认的配置,
- 各种自动配置都拥有默认值:配置文件的值最终会绑定每个类上,这个类会在容器中创建对象。
- spring为我们提供了很多的start:引入了哪些场景start,这个场景的自动配置才会开启,SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面。
- 默认的包结构:springboot默认扫描主程序所在包及其下面的所有子包里面的组件想要改变扫描路径可以使用,@SpringBootApplication(scanBasePackages=“xxx包名”)指定扫描的组件包
4.容器功能*****
4.1组件添加
4.1.1@Configuration
简介:标注在类上,告诉spring这是一个配置类;可以使用这个注解标注的类代替xml文件
- 配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
- 配置类本身也是组件
- proxyBeanMethods属性:代理获取的bean是单例还是多例的
proxyBeanMethods = true:返回的组件都是单实例 也称Full模式
proxyBeanMethods = false:每次获取都创建新的实例 也称Lite模式
疑问:proxyBeanMethods属性值如何选择?
配置类组件之间无依赖关系(一个bean中引用了另一个bean)用Lite模式加速容器启动过程,减少判断;
配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式。
4.1.2@Bean、@Component、@Controller、@Service、@Repository
@bean:标注在方法上,给容器中添加组件,组件的id、类型、实例,分别为方法的方法名、返回类型、返回值。
其余4个用法相似都标注在类上:表示给容器中添加组件:组件id、类型、实例分别为类名的首字母小写、当前类名、构造方法返回值;
4.1.3@ComponentScan、@Import
@ComponentScan:一般标注在主程序类或spring配置类上,表示扫描那个包及子包下的组件,常用属性value(“xxx包名”),可使用属性设置过滤规则。
@Import({xxx.class}):只能使用在了类上不能使用在方法上;
-
xxx为普通的类:将xxx类,注入到容器中 经测试通过run.getBean("user/User’)获取不到实例,通过@Autowired可以获取到实例
-
xxx为@Configuration标注的配置类:会将配置类中所有的的组件(@bean)注入到容器中
-
xxx为ImportSelector的具体实现:
创建ImportSelector的实现类,实现selectImports方法,返回要加载的@Configuation或者具体Bean类的全限定名的String数组。
-
xxx为ImportBeanDefinitionRegistrar的具体实现
4.1.4@Conditional
条件装配:满足Conditional指定的条件,则进行组件注入。
- @ConditionalOnBean:当前上下文中存在某个对象时
- @ConditionalOnMissingBean:当前上下文中不存在某个对象时
- @ConditionalOnExpression:SpEL表达式为true的时候
- @ConditionalOnClass:系统中有指定的类
- @ConditionalOnMissingClass:系统中没有指定的类
- @ConditionalOnWebApplication:当前是web应用
- @ConditionalOnNotWebApplication:当前不是web应用
- @ConditionalOnSingleCandidate:容器中只有一个bean,或者这个bean是首选bean
- @ConditionalOnProperty:系统中指定的属性有指定的值
- @ConditionalOnResource:类路径下是否存在指定资源文件
4.2原生配置文件的引入@ImportResource
例如我们现在有一个spring工程想升级成springboot工程,这时我的xml文件中有大量的bean标签和配置,而我们不想手动的去将这些配置文件迁移成配置类,就可以在任意一个配置类上使用@ImportResource(“配置文件路径”) 引入原来的xml文件,使xml文件中的组件生效;
4.3配置绑定
疑问:如何读取properties文件中的内容,并且把它封装到组件的属性中?
注:只有在容器中的组件,才会拥有SpringBoot提供的强大功能
4.3.1@ConfigurationProperties+@Component
ConfigurationProperties标注在类上,将配置文件的每个属性的值,映射到这个组件中,告诉Springboot将本类中的所有属性和配置文件中的配置进行绑定;
示例
配置文件中添加固定值开头的属性
在组件上使用@Component和@ConfigurationProperties注解并指定前缀
输出:User{name=‘小明’, age=20}
4.3.2@EnableConfigurationProperties+ @ConfigurationProperties
作用:使配置文件中的@ConfigurationProperties(xxx.class)生效,并且把xxx组件自动注册到容器中
示例:使用EnableConfigurationProperties注解标注在主程序上或者配置类上
配置文件中添加固定值开头的属性
使用ConfigurationProperties注解标注在想要赋值的类上
书写controller
启动容器访问/bean接口就会将配置文件中的属性值绑定到对应的实例中
5.自动配置原理入门*****
5.1@SpringBootApplication为我们做了什么?
进入SpringBootApplication注解的源码可以看到这个注解主要分三部分
5.1.1@SpringBootConfiguration
作用:声明当前类为一个配置类
5.1.2@ComponentScan
作用:组件扫描,并且使用到了两个是spring自定义的扫描器
5.1.3@EnableAutoConfiguration开启自动配置.(重点)
进入源码看到EnableAutoConfiguration内部由两个注解组成
-
@AutoConfigurationPackage
AutoConfigurationPackage源码
Registrar源码
Registrar里面,利用Registrar给容器中导入一系列组件,将主程序所在的包下的所有组件导入进来,这也就是之前我们在2.2中提到为什么要把组件写到主程序所在包及子包下的原因。 -
@Import(AutoConfigurationImportSelector.class)
AutoConfigurationImportSelector源码
作用:利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
getAutoConfigurationEntry源码
作用:调用List configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类
调用loadFactoryNames
FACTORIES_RESOURCE_LOCATION的值为
综上所述:springboot从META-INF/spring.factories位置来加载一个文件。
默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件;
而文件里面写死了spring-boot一启动就要给容器中加载的所有配置类;
spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories
5.2按需开启自动配置项
疑问:spring.factories给我们定义了这么多的组件,那么启动时是将所有的组件全部注入到容器中吗?
原理:虽然我们127个场景的所有自动配置启动的时候默认全部加载。但是在xxxxAutoConfiguration
配置中组件上用到了大量的@Conditional,而这个注解会按照指定的规则进行组件的注册与否。
5.3修改默认配置
疑问1:springboot虽然为我们提供了默认的自动配置项,那我们如何使用自定义的组件呢?
使用自定义组件:SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先,可以直接在配置类中注入组件,启动容器会默认先加载这些配置类中的组件
疑问2:如何多springboot提供的组件进行属性值修改
修改对应的配置:直接在application.properties文件中对相应组件的属性进行修改
疑问3:为什么对application.properties中对相应组件的属性进行修改会修改组件的属性?
原理:
- SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration;
- xxxxxAutoConfiguration给容器中注入了很多的组件;
- 每个组件都会绑定默认配置文件xxxxProperties指定的值;
- 而xxxProperties有个application.properties进行了绑定。
5.4使用springboot开发的步骤
- 引入场景启动器依赖
各种start名称 - 查看自动配置了哪些
配置文件中debug=true开启自动配置报告,启动控制台输出。Negative(不生效)\Positive(生效) - 是否需要修改自动配置的值
(1)参照文档修改配置项;
(2)自己看源码中的xxxxxAutoConfiguration对应的xxxxProperties中哪些属性绑定了配置文件 - 自定义加入或者替换组件
@Bean、@Component。。。 - 自定义器 XXXXXCustomizer;(后面分析)
6. 开发小技巧
6.1lombok
lombok是一个可以帮助我们简化java代码编写的工具类,通过采用注解的方式,代替类中的构造方法,getter/setter等代码,当我们的字段发生改变时,lombok也会对相应的getter方法进行改变。
- 导入依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
- idea中搜索plugis安装lombok插件
- lombok中常用注解使用
直接在javabean的类名上标注
- @Data 注解在类上;提供类所有属性的 getting 和 setting 方法,此外还提供了equals、canEqual、hashCode、toString 方法
- @Setter :注解在属性上;为属性提供 setting 方法
- @Getter:注解在属性上;为属性提供 getting 方法
- @Log4j :注解在类上;为类提供一个 属性名为log 的 log4j 日志对象
- @NoArgsConstructor :注解在类上;为类提供一个无参的构造方法
- @AllArgsConstructor :注解在类上;为类提供一个全参的构造方法
- @Cleanup : 可以关闭流
- @Builder : 被注解的类加个构造者模式
- @Synchronized : 加个同步锁
- @SneakyThrows : 等同于try/catch 捕获异常
- @NonNull : 如果给参数加个这个注解 参数为null会抛出空指针异常
- @Value : 注解和@Data类似,区别在于它会把所有成员变量默认定义为private final修饰,并且不会生成set方法。
6.2dev-tools
在开发时,若我们改变代码需要手动的去重启项目,很麻烦,可以使用dev-tools热更新来解决,修改项目代码后使用Ctrl+F9;重新编译项目;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
但这个dev-tools提供的并不是真正的热部署,我们可以看到就是工具给我们做了一个自动启动的操作;
若想使用热部署可以使用付费插件Jrebel插件
6.3Spring Initailizr(项目初始化向导)
直接使用Spring Initailizr创建springboot项目,它会自动帮我们创建项目结构、引入pom文件中的依赖、主程序类