Spring Boot 是一个构建在Spring框架顶部的项目。它提供了一种简便,快捷的方式来设置,配置和运行基于Web的简单应用程序。它是一个Spring模块,提供了RAD(快速应用程序开发)功能。它可以用于快速创建独立的基于Spring的应用程序,因为它需要最少的Spring配置就可以运行。简而言之,Spring Boot是 Spring Framework 和嵌入式服务器 的组合。在Spring Boot不需要XML配置(部署描述符)。它使用约定优于配置 的软件设计范例,这意味着可以减少开发人员的工作量。
SpringBoot简介 SpringBoot能做什么 我们应该使用Spring Boot Framework
,因为:
Spring Boot中使用了依赖项注入方法。
它包含强大的数据库事务管理功能。
它简化了与其他Java框架(如JPA/Hibernate ORM,Struts等)的集成。
它减少了应用程序的成本和开发时间。
与Spring Boot框架一起,其他许多Spring姐妹项目也有助于构建满足现代业务需求的应用程序。
Spring姐妹项目如下:
Spring Data: 它简化了来自关系数据库和 NoSQL 数据库的数据访问。
Spring Batch: 它提供了强大的批处理 处理。
Spring Security: 这是一个安全框架,可为应用程序提供强大的安全性 。
Spring Social: 它支持与LinkedIn等社交网络 集成。
Spring Integration: 它是企业集成模式的实现。使用轻量级消息传递和声明性适配器,它有助于与其他企业应用程序 集成。
SpringBoot优缺点
优点:
Create stand-alone Spring applications
Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
Provide opinionated ‘starter’ dependencies to simplify your build configuration
Automatically configure Spring and 3rd party libraries whenever possible
Provide production-ready features such as metrics, health checks, and externalized configuration
Absolutely no code generation and no requirement for XML configuration
SpringBoot是整合Spring技术栈的一站式框架
SpringBoot是简化Spring技术栈的快速开发脚手架
缺点:
迭代快,需要时刻关注变化
封装太深,内部原理复杂,不容易精通
第一个Hello world程序 pom.xml配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <?xml version="1.0" encoding="UTF-8"?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <groupId > com.heavytiger</groupId > <artifactId > Learn_SpringBoot</artifactId > <version > 1.0-SNAPSHOT</version > <properties > <maven.compiler.source > 11</maven.compiler.source > <maven.compiler.target > 11</maven.compiler.target > </properties > <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.3.4.RELEASE</version > </parent > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > </dependencies > </project >
主程序ApplicationMain:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.heavytiger.boot;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication public class MainApplication { public static void main (String[] args) { SpringApplication.run(MainApplication.class, args); } }
业务层HelloController:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.heavytiger.boot;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController public class HelloController { @RequestMapping("/hello") public String handle01 () { return "Hello world, hello Spring Boot!" ; } }
直接运行MainApplication中的main方法即可启动,原因是springboot封装了tomcat服务器
创建application.properties简化全局配置:
修改端口后,通过8088可以访问:
简化部署流程:
在pom.xml
中添加如下插件依赖,可以打包成jar包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 <?xml version="1.0" encoding="UTF-8"?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <groupId > com.heavytiger</groupId > <artifactId > Learn_SpringBoot</artifactId > <version > 1.0-SNAPSHOT</version > <packaging > jar</packaging > <properties > <maven.compiler.source > 11</maven.compiler.source > <maven.compiler.target > 11</maven.compiler.target > </properties > <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.3.4.RELEASE</version > </parent > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > </dependencies > <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > </plugin > </plugins > </build > </project >
执行mvn package
命令后,得到jar包,在shell下可以直接使用语句java -jar abc.jar
运行jar包,启动web服务。
若命令行下启动时卡死,需要禁用cmd的快速编辑模式,之后即可正常运行jar包
SpringBoot自动装配原理 SpringBoot的特点 SpringBoot的依赖管理 我们上一章编写的hello world
服务中,pom.xml
下非常整洁,只导入了一个依赖,就能直接运行相应的功能,但是以往在Spring和SpringMVC中,要导入很多东西。SpringBoot简化的原理是:父项目做依赖管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.3.4.RELEASE</version > </parent > <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-dependencies</artifactId > <version > 2.3.4.RELEASE</version > </parent >
SpringBoot无需关注版本号,自动实现版本仲裁:
引入依赖默认可以不写版本
引入非版本仲裁的jar包,即SpringBoot未声明的依赖,需要写版本号
在spring-boot-dependencies
文件中,引入的mysql驱动是8.0.21
版本,若想将其人为设置成5.1.43
版本,则可以在properties
标签下声明:
1 2 3 4 5 <properties > <mysql.version > 5.1.43</mysql.version > </properties >
Maven提供的特性,就近优先原则
SpringBoot导入starter场景启动器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > Spspring-boot-starter</artifactId > <version > 2.3.4.RELEASE</version > <scope > compile</scope > </dependency >
spring-boot-starter-web的依赖树,可以看到常见的web开发中的依赖均已经被导入,非常简洁明了
自动配置 SpringBoot帮忙做好的事情:
自动配置好Tomcat
1 2 3 4 5 6 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-tomcat</artifactId > <version > 2.3.4.RELEASE</version > <scope > compile</scope > </dependency >
自动配好SpringMVC
引入SpringMVC全套组件
自动配好SpringMVC常用组件(功能)视图解析器,dispatcherServlet等
自动配好Web常见功能
SpringBoot帮我们配置好了所有web开发的常见场景及问题,如:字符编码乱码问题
默认的包结构
各种配置拥有默认值
默认配置最终都是映射到某个类上,如:MultipartProperties
配置文件的值最终会绑定某个类上,这个类会在容器中被创建对象
按需加载所有自动配置项
……
容器功能 组件添加 @Configuration
基本模式@Configuration
,表示该类是一个配置类
Full模式@Configuration(proxyBeanMethods = true)
和Lite模式@Configuration(proxyBeanMethods = false)
建议使用方案:
配置类中,组件之间没有依赖关系,使用Lite模式加速容器的启动,否则每次获取实例都需要判断是否存在实例
配置类中,组件之间存在依赖关系,方法调用必须要得到之前的单实例组件,此时应该用Full模式保证获取到的是同一实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 @Configuration(proxyBeanMethods = false) public class MyConfig { @Bean public User user01 () { User zhangsan = new User("zhangsan" , 18 ); zhangsan.setPet(tomcatPet()); return zhangsan; } @Bean("tom") public Pet tomcatPet () { return new Pet("tomcat" ); } } @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan("com.heavytiger.boot") public class MainApplication { public static void main (String[] args) { ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args); String[] names = run.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } Pet tom01 = run.getBean("tom" , Pet.class); Pet tom02 = run.getBean("tom" , Pet.class); System.out.println("组件:" +(tom01 == tom02)); MyConfig bean = run.getBean(MyConfig.class); System.out.println(bean); User user = bean.user01(); User user1 = bean.user01(); System.out.println(user == user1); User user01 = run.getBean("user01" , User.class); Pet tom = run.getBean("tom" , Pet.class); System.out.println("用户的宠物:" +(user01.getPet() == tom)); } }
@Bean、@Component、@Controller、@Service、@Repository 和之前的SSM中一样,在类上标注注解,可以直接通过名称获取,也可以实现自动装配
@ComponentScan、@Import 1 2 3 4 5 6 7 8 9 @Import({User.class, DBHelper.class}) @Configuration(proxyBeanMethods = false) public class MyConfig { }
@Conditional 条件装配:满足Conditional指定的条件,则进行组件注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 =====================测试条件装配========================== @Configuration(proxyBeanMethods = false) @ConditionalOnMissingBean(name = "tom") public class MyConfig { @Bean public User user01 () { User zhangsan = new User("zhangsan" , 18 ); zhangsan.setPet(tomcatPet()); return zhangsan; } @Bean("tom22") public Pet tomcatPet () { return new Pet("tomcat" ); } } public static void main (String[] args) { ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args); String[] names = run.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } boolean tom = run.containsBean("tom" ); System.out.println("容器中Tom组件:" +tom); boolean user01 = run.containsBean("user01" ); System.out.println("容器中user01组件:" +user01); boolean tom22 = run.containsBean("tom22" ); System.out.println("容器中tom22组件:" +tom22); }
xml配置文件引入 使用@ImportResource
注解,可以把原生的配置文件导入到容器中,适用于公司中存在较老的不方便进行迁移的组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd" > <bean id ="haha" class ="com.atguigu.boot.bean.User" > <property name ="name" value ="zhangsan" > </property > <property name ="age" value ="18" > </property > </bean > <bean id ="hehe" class ="com.atguigu.boot.bean.Pet" > <property name ="name" value ="tomcat" > </property > </bean > </beans >
1 2 3 4 5 6 7 8 @ImportResource("classpath:beans.xml") public class MyConfig {}======================测试================= boolean haha = run.containsBean("haha" );boolean hehe = run.containsBean("hehe" );System.out.println("haha:" +haha); System.out.println("hehe:" +hehe);
配置绑定 使用Java读取properties配置文件中的内容,并把它封装到JavaBean中,以供随时使用
例如:
1 2 3 mycar.brand = BYD mycar.price = 100000
方案一:@Component + @ConfigurationProperties 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 @Component @ConfigurationProperties(prefix = "mycar") public class Car { private String brand; private Integer price; public String getBrand () { return brand; } public void setBrand (String brand) { this .brand = brand; } public Integer getPrice () { return price; } public void setPrice (Integer price) { this .price = price; } @Override public String toString () { return "Car{" + "brand='" + brand + '\'' + ", price=" + price + '}' ; } }
方案二:@EnableConfigurationProperties + @ConfigurationProperties 若使用第三方的组件,不可能去给类上添加一个@Component
,因此只能在需要使用到组件的配置类上添加@EnableConfigurationProperties
1 2 3 4 5 @EnableConfigurationProperties(Car.class) public class MyConfig {}
自动配置原理入门 引导加载自动配置类 1 2 3 4 5 @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication{}
从@SpringBootConfiguration
中开始查询实现:
1.@SpringBootConfiguration
里面的注解有@Configuration代表当前是一个配置类
2.@ComponentScan
指定扫描哪些内容,哪些包
3.@EnableAutoConfiguration
1 2 3 @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {}
4.@AutoConfigurationPackage
自动配置包,指定了默认的包的规则
1 2 3 4 @Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage {}
5.@Import(AutoConfigurationImportSelector.class)
1、利用getAutoConfigurationEntry(annotationMetadata);
给容器中批量导入一些组件 2、调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)
获取到所有需要导入到容器中的配置类 3、利用工厂加载Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);
得到所有的组件 4、从META-INF/spring.factories
位置来加载一个文件。 默认扫描我们当前系统里面所有META-INF/spring.factories
位置的文件 spring-boot-autoconfigure-2.3.4.RELEASE.jar
包里面也有META-INF/spring.factories
按需开启自动配置项
虽然一共有127个场景在自动配置启动的时候会被默认全部加载,但是由于各个场景的xxxAutoConfiguration
会按照条件装配规则(@Conditional
),最终实现按需分配
修改默认设置 1 2 3 4 5 6 7 8 9 10 @Bean @ConditionalOnBean(MultipartResolver.class) @ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) public MultipartResolver multipartResolver (MultipartResolver resolver) { return resolver; }
SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先
1 2 3 4 @Bean @ConditionalOnMissingBean public CharacterEncodingFilter characterEncodingFilter () { }
总结:
SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
生效的配置类就会给容器中装配很多组件
只要容器中有这些组件,相当于这些功能就有了
定制化配置
用户直接自己@Bean替换底层的组件
用户去看这个组件是获取的配置文件什么值就去修改。
xxxxxAutoConfiguration —> 组件 —> xxxxProperties里面拿值 —-> application.properties
最佳实现
引入场景依赖
查看自动配置了哪些(选做)
自己分析,引入场景对应的自动配置一般都生效了
配置文件中设置debug=true
开启自动配置报告。Negative(不生效)\Positive(生效)
是否需要修改
自定义加入或者替换组件
自定义器 XXXXXCustomizer ;
参考资料
[1] 尚硅谷雷神SpringBoot2零基础入门springboot全套完整版(spring boot2)_哔哩哔哩_bilibili
[2] SpringBoot2核心技术与响应式编程 · 语雀 (yuque.com)