1. 前言 学习历程 javase: OOP的思想
mysql: 持久化
html+css+js+jquery+框架: 视图层
javaweb: 独立开发原始的MVC三层框架网站
SSM: 框架,简化开发流程,但配置也开始复杂
war: tomcat运行
spring再简化: SpringBoot-jar: 内嵌tomcat; 微服务架构
服务越来越多: 出现了springcloud
Spring是怎么简化开发的
基于POJO的轻量级和最小侵入性编程,所有东西都是bean;
通过IOC,依赖注入(DI)和面向接口实现松耦合;
基于切面(AOP)和惯例进行声明式编程;3
通过切面和模版减少样式代码,RedisTemplate,xxxTemplate;
什么是SpringBoot 一个javaweb的开发框架,和SpringMVC类似,对比其他javaweb框架的好处,官方说是简化开发,约定大于配置, you can “just run”,能迅速的开发web应用,几行代码开发一个http接口。
所有的技术框架的发展似乎都遵循了一条主线规律:从一个复杂应用场景衍生一种规范框架,人们只需要进行各种配置而不需要自己去实现它,这时候强大的配置功能成了优点;发展到一定程度之后,人们根据实际生产应用情况,选取其中实用功能和设计精华,重构出一些轻量级的框架;之后为了提高开发效率,嫌弃原先的各类配置过于麻烦,于是开始提倡约定大于配置 ,进而衍生出一些一站式的解决方案,这就是Java企业级应用->J2EE->spring->springboot的过程。
Spring Boot 基于 Spring 开发,Spirng Boot 本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于 Spring 框架的应用程序。也就是说,它并不是用来替代 Spring 的解决方案,而是和 Spring 框架紧密结合用于提升 Spring 开发者体验的工具。Spring Boot 以约定大于配置的核心思想 ,默认帮我们进行了很多设置,多数 Spring Boot 应用只需要很少的 Spring 配置。同时它集成了大量常用的第三方库配置(例如 Redis、MongoDB、Jpa、RabbitMQ、Quartz 等等),Spring Boot 应用中这些第三方库几乎可以零配置的开箱即用
简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架 。
Spring Boot的主要优点:
为所有Spring开发者更快的入门
开箱即用 ,提供各种默认配置来简化项目配置
内嵌式容器简化Web项目
没有冗余代码生成和XML配置的要求
2.微服务阶段 单体应用架构 所谓单体应用架构(all in one)是指,我们将一个应用中的所有应用服务都封装在一个应用中
无论是ERP、CRM,都把数据库访问,web访问等功能发到一个war包内
好处:易于开发与测试;也十分方便部署;当需要拓展时,只需要将war复制多分,然后放到多个服务器上,再做个负载均衡就可以了
缺点:小的修改都需要停掉整个服务,重新打包、部署war包。如果是大型应用,如何维护、分工合作会成为大问题好处
微服务架构 打破之前all in one的架构方式,把各个功能元素独立出来,把独立出来的功能元素的动态组合,需要的功能元素才去组合,需要多一些时可以整合多个功能元素。所以微服务架构是对功能元素进行复制,而没有对整个应用进行复制。
这样做的好处:
节省了调用资源
每个功能元素的服务都是一个可替换的、可独立升级的软件代码
martinfowler的微服务论文
如何搭建微服务 一个大型系统的微服务架构,就像一个复杂交织的神经网络,每一个神经元就是一个功能元素,他们各自完成自己的功能,然后通过http相互请求调用。比如一个电商系统,查缓存、连数据库、浏览页面、结账、支付等服务都是一个个独立的功能服务,都被微化了,他们作为一个个微服务共同构建了一个完整的系统。如果要修改其中一个功能,只需要更新一个功能单元即可。
但是这种庞大的系统架构给部署和运维带来很大困难。于是,spring为我们带来了构建大型分布式微服务的全套、全程产品:
构建一个个功能独立的微服务应用单元,可以使用springboot,可以帮我们快速构建一个应用;
大型分布式网络服务的调用,这部分由springcloud来完成,实现分布式;
在分布式中间,进行流式数据计算、批处理,我们有spring cloud data flow
spring为我们想清楚了整个从开始构建应用到大型分布式应用全流程方案
3.第一个springboot项目 准备工作 我们将学习如何快速的创建一个Spring Boot应用,并且实现一个简单的Http请求处理。通过这个例子对Spring Boot有一个初步的了解,并体验其结构简单、开发快速的特性。
创建基础项目说明 创建方式一:使用Spring Initializr Spring官方提供了非常方便的工具让我们快速构建应用 Spring Initializr
进入Spring Initializr页面,选择leaguage,project,springboot版本,项目信息,JDK版本以及依赖之后点击生成,得到一个压缩包,解压并用IDEA以Maven项目导入即可
创建方式二:使用 IDEA 直接创建项目 本质也是进入Spring Initializr ,先填写项目信息
再选择依赖,然后等待项目构建完成即可
项目结构分析 通过上面步骤完成了基础项目的创建。就会自动生成以下文件。
程序的主启动类,程序入口 SpringbootApplication.java
一个 application.properties 配置文件,但更推荐yml格式的配置文件
一个 测试类
pom.xml
pom.xml 打开pom.xml,看看Spring Boot项目的依赖:
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 <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.7.5</version > <relativePath /> </parent > <groupId > com.hanser</groupId > <artifactId > springboot</artifactId > <version > 0.0.1-SNAPSHOT</version > <name > springboot</name > <description > springboot</description > <properties > <java.version > 1.8</java.version > </properties > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-test</artifactId > <scope > test</scope > </dependency > </dependencies > <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > </plugin > </plugins > </build > </project >
基础配置 端口号 再配置文件application.properties或者application.yml里配置
banner图案
就是这个项目启动时的图案
在resources目录下新建一个banner.txt文件
在线生成自己想要的图案
将图案复制到banner.txt中
4.springboot自动装配原理浅析 pom.xml(依赖) 我们发现本项目的父依赖spring-boot-starter-parent还有一个父依赖spring-boot-dependencies
在spring-boot-dependencies里面有很多依赖的版本,这里是springboot的版本控制中心
以后我们导入依赖默认是不需要写版本;但是如果导入的包没有在依赖中管理着就需要手动配置版本了;
启动器 spring-boot-starter 1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter</artifactId > </dependency >
主启动类 1 2 3 4 5 6 7 8 9 10 @SpringBootApplication public class SpringbootApplication { public static void main (String[] args) { SpringApplication.run(SpringbootApplication.class, args); } }
注解 点进@SpringBootApplication发现有三个主要注解
1 2 3 @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan
@ComponentScan 就是一个包扫描注解,代表扫描主启动类所在目录下的所有包
@SpringBootConfiguration 这个注解下有一个@Configuration注解,点进去发现有@Component注解,代表他是一个spring的一个组件
@EnableAutoConfiguration 自动配置核心注解
@AutoConfigurationPackage 1 2 3 4 5 6 7 8 9 10 11 12 13 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage { String[] basePackages() default {}; Class<?>[] basePackageClasses() default {}; }
@Import({AutoConfigurationImportSelector.class}) AutoConfigurationImportSelector:自动导入包的核心
getAutoConfigurationEntry()方法:获得自动配置类的实体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 protected AutoConfigurationEntry getAutoConfigurationEntry (AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } AnnotationAttributes attributes = getAttributes(annotationMetadata); List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); configurations = removeDuplicates(configurations); Set<String> exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = getConfigurationClassFilter().filter(configurations); fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationEntry (configurations, exclusions); }
getCandidateConfigurations:获取候选的配置
1 2 3 4 5 6 7 8 9 protected List<String> getCandidateConfigurations (AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = new ArrayList <>( SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader())); ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you " + "are using a custom packaging, make sure that file is correct." ); return configurations; }
loadFactoryNames() :获取所有的加载配置
1 2 3 4 5 6 7 8 9 public static List<String> loadFactoryNames (Class<?> factoryType, @Nullable ClassLoader classLoader) { ClassLoader classLoaderToUse = classLoader; if (classLoader == null ) { classLoaderToUse = SpringFactoriesLoader.class.getClassLoader(); } String factoryTypeName = factoryType.getName(); return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList()); }
getSpringFactoriesLoaderFactoryClass:标注了EnableAutoConfiguration注解的类(主启动类)
1 2 3 protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; }
loadSpringFactories(): 获取所有的配置
它做了一件事:遍历FACTORIES_RESOURCE_LOCATION下的所有资源,并把这些资源封装成Properties供我们使用
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 private static Map<String, List<String>> loadSpringFactories (ClassLoader classLoader) { Map<String, List<String>> result = cache.get(classLoader); if (result != null ) { return result; } result = new HashMap <>(); try { Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION); while (urls.hasMoreElements()) { URL url = urls.nextElement(); UrlResource resource = new UrlResource (url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); for (Map.Entry<?, ?> entry : properties.entrySet()) { String factoryTypeName = ((String) entry.getKey()).trim(); String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String) entry.getValue()); for (String factoryImplementationName : factoryImplementationNames) { result.computeIfAbsent(factoryTypeName, key -> new ArrayList <>()) .add(factoryImplementationName.trim()); } } } result.replaceAll((factoryType, implementations) -> implementations.stream().distinct() .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList))); cache.put(classLoader, result); } catch (IOException ex) { throw new IllegalArgumentException ("Unable to load factories from location [" + FACTORIES_RESOURCE_LOCATION + "]" , ex); } return result; }
我们发现有这样一行
1 Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
从FACTORIES_RESOURCE_LOCATION里获取资源,然后它是一个静态变量
1 public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories" ;
我们在对应lib目录下找到这个文件,所有的自动配置类都在这里
2.7.0版本之后自动配置类的配置位置变化,现在自动配置类需要放到文件META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
中,该文件中每一行都是一个自动配置类的全路径名,其格式可以参考这个官方文档 。不过为了保持向后兼容,SpringBoot依然会处理spring.factories
文件中的自动配置类。
点进autoconfigure包,发现有不少autoConfiguration类,点进aop自动配置类,可以看到出现了大量的@ConditionalOnXXX注解,这是自动配置的核心注解,括号内的条件满足,这个类才会生效
总结 springboot的所有自动配置都是在启动时扫描并加载,META-INF/spring.factories
里有不少自动配置类,但是不一定生效,大多数自动配置类都有一个叫@ConditionalOnXXX的注解,里面条件满足了,自动配置才会生效,我们才可以使用对应方法。
5.主启动类 了解一下主启动类怎么运行
SpringApplication 这个类主要做了以下四件事情:(查看构造器)
推断应用的类型是普通的项目还是Web项目
查找并加载所有可用初始化器 , 设置到initializers属性中
找出所有的应用程序监听器,设置到listeners属性中
推断并设置main方法的定义类,找到运行的主类
run方法
6.yaml springboot配置文件 SpringBoot使用一个全局的配置文件 , 配置文件名称是固定的(pom.xml里父项目规定的)
application.properties
application.yml
application.yaml
配置文件的作用: 修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们自动配置好了;
yaml概述 YAML是 “YAML Ain’t a Markup Language” (YAML不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言),这种语言以数据作为中心,而不是以标记语言为重点!
以前的配置文件,大多数都是使用xml来配置;比如一个简单的端口配置,我们来对比下yaml和xml
1 2 3 <server > <port > 8081<port > </server >
.properties文件的形式是k=v(键值对)的形式
.yml则是k: v的形式,冒号后面有空格
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 name: hanser student: name: hanser age: 22 student1: {name: hanser ,age: 13 }pets: - cat - dog - ppp pets1: [cat ,dog ,ppp ]
注意:
字面量(数字,布尔值,字符串)直接写在后面就可以 , 字符串默认不用加上双引号或者单引号;
“ ” 双引号,会转义字符串里面的特殊字符 , 特殊字符会作为本身想表示的意思;
‘’ 单引号,不会转义特殊字符 , 特殊字符最终会变成和普通字符一样输出
注入配置文件 yml注入配置文件(推荐) yaml文件更强大的地方在于,他可以给我们的实体类或者配置类注入值
首先在yml文件中写上要配置的值,注意yml中的名称要和属性的的名称一致
1 2 3 4 5 6 7 8 9 people: name: hanser age: 21 happy: false birth: 2001 /06/21 map: {k1: v1 ,k2: v2 } hobbies: - code - game
之后在对应实体类上加上@ConfigurationProperties,这时会报错,如下图,但是不影响测试
如果想削除提示,可以在pom.xml中加入这个依赖
1 2 3 4 5 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-configuration-processor</artifactId > <optional > true</optional > </dependency >
加入@ConfigurationProperties(prefix = “people”),prefix=”yml中的对象名”,注解默认从applacation.yaml里取值
1 2 3 4 5 6 7 8 9 10 11 @Data @Component @ConfigurationProperties(prefix = "people") public class People { private String name; private Integer age; private Boolean happy; private Date birth; private Map map; private List<Object> hobbies; }
去测试类里测试,成功打印出信息
1 2 3 4 5 6 7 8 9 10 11 @SpringBootTest class SpringbootApplicationTests { @Resource private People people; @Test void contextLoads () throws SQLException { System.out.println(people); } }
此外yml还支持各种形式的占位符
1 2 3 4 5 6 7 8 9 10 11 12 people: name: hanser${random.uuid} age: ${random.int} happy: false birth: 2001 /06/21 map: {k1: v1 ,k2: v2 } hobbies: - code - game dog: name: ${people.hello:hanser}_旺财 age: 1
使用.properties文件注入配置(不推荐) @PropertySource:加载指定的配置文件
我们去在resources目录下新建一个peopel.properties文件
注入实体类
1 2 3 4 5 6 7 8 9 @Data @Component @PropertySource(value = "classpath:person.properties") public class Person { @Value("${name}") private String name; }
对比
@ConfigurationProperties只需要写一次即可 , @Value则需要每个字段都添加
松散绑定: 比如我的yml中写的last-name,这个和lastName是一样的,-形式的会自动转化为驼峰命名。这就是松散绑定。
JSR303数据校验 , 这个就是我们可以在字段是增加一层过滤器验证 , 可以保证数据的合法性
复杂类型封装,yml中可以封装对象 , 使用value就不支持
所以更推荐使用yml形式
7.JSR303检验 使用时,在对应类上加上@Validated注解代表启用数据校验
然后在对应属性上加入规则,规则有下面这个,需要详细查看可以点入引入的规则的包下查看源码
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 空检查 @Null 验证对象是否为null @NotNull 验证对象是否不为null, 无法查检长度为0的字符串 @NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格. @NotEmpty 检查约束元素是否为NULL或者是EMPTY. Booelan检查 @AssertTrue 验证 Boolean 对象是否为 true @AssertFalse 验证 Boolean 对象是否为 false 长度检查 @Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内 @Length(min=, max=) Validates that the annotated string is between min and max included. 日期检查 @Past 验证 Date 和 Calendar 对象是否在当前时间之前,验证成立的话被注释的元素一定是一个过去的日期 @Future 验证 Date 和 Calendar 对象是否在当前时间之后 ,验证成立的话被注释的元素一定是一个将来的日期 @Pattern 验证 String 对象是否符合正则表达式的规则,被注释的元素符合制定的正则表达式,regexp:正则表达式 flags: 指定 Pattern.Flag 的数组,表示正则表达式的相关选项。 数值检查 建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为”“,Integer为null @Min 验证 Number 和 String 对象是否大等于指定的值 @Max 验证 Number 和 String 对象是否小等于指定的值 @DecimalMax 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度 @DecimalMin 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度 @Digits 验证 Number 和 String 的构成是否合法 @Digits(integer=,fraction=) 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。 @Range(min=, max=) 被指定的元素必须在合适的范围内 @Range(min=10000,max=50000,message=”range.bean.wage”) @Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证) @CreditCardNumber信用卡验证 @Email 验证是否是邮件地址,如果为null,不进行验证,算通过验证。 @ScriptAssert(lang= ,script=, alias=) @URL(protocol=,host=, port=,regexp=, flags=)]()]()
8.多环境配置 profile是Spring对不同环境提供不同配置功能的支持,可以通过激活不同的环境版本,实现快速切换环境;
多配置文件 我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml , 用来指定多个环境版本;
比如:
application-test.properties 代表测试环境配置
application-dev.properties 代表开发环境配置
但是Springboot并不会直接启动这些配置文件,它默认使用application.properties主配置文件 ;
我们需要通过一个配置来选择需要激活的环境:在主配置文件里加入
1 spring.profiles.active =dev
yaml的多配置文件 和properties配置文件中一样,但是使用yml去实现不需要创建多个配置文件,更加方便了 !
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 server: port: 8081 spring: profiles: active: dev --- server: port: 8082 spring: profiles: dev --- server: port: 8083 spring: profiles: test
注意:如果yml和properties同时都配置了端口,并且没有激活其他环境 , 默认会使用properties配置文件的!
配置文件位置
./代表项目目录,且四个位置配置文件的优先级是从上到下递减的,高优先级的配置会覆盖低优先级的配置
9.自动配置原理再理解 我们能配什么 前面我们知道了springboot是如何进行自动装配的,核心注解是@EnableAutoConfiguration,并且深入到了MATE-INF/spring.factories的一些自动配置类,自动配置类又通过@ConditionalOnXXX注解来确定是否生效,那么以上是Springboot的自动配置,我们怎么能够知道在配置文件里究竟能自定义配置那些东西呢,这就需要我们更深入的进入自动配置类去寻找答案
我们以一个较为简单的HttpEncoding自动配置类作为例子
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 @AutoConfiguration @EnableConfigurationProperties(ServerProperties.class) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnClass(CharacterEncodingFilter.class) @ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true) public class HttpEncodingAutoConfiguration { private final Encoding properties; public HttpEncodingAutoConfiguration (ServerProperties properties) { this .properties = properties.getServlet().getEncoding(); } @Bean @ConditionalOnMissingBean public CharacterEncodingFilter characterEncodingFilter () { CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter (); filter.setEncoding(this .properties.getCharset().name()); filter.setForceRequestEncoding(this .properties.shouldForce(Encoding.Type.REQUEST)); filter.setForceResponseEncoding(this .properties.shouldForce(Encoding.Type.RESPONSE)); return filter; } @Bean public LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer () { return new LocaleCharsetMappingsCustomizer (this .properties); } static class LocaleCharsetMappingsCustomizer implements WebServerFactoryCustomizer <ConfigurableServletWebServerFactory>, Ordered { private final Encoding properties; LocaleCharsetMappingsCustomizer(Encoding properties) { this .properties = properties; } @Override public void customize (ConfigurableServletWebServerFactory factory) { if (this .properties.getMapping() != null ) { factory.setLocaleCharsetMappings(this .properties.getMapping()); } } @Override public int getOrder () { return 0 ; } } }
点进ServerProperties中查看,刚点进去就发现了熟悉的@ConfigurationProperties注解,所以首先是server开头的
1 @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
之后去寻找我们要找的encoding设置
发现encoding是一个内部类对象servlet的一个属性,所以我们推测yaml的格式应该为
1 2 3 server: servlet: encoding:
结果也证明了我们是正确的
总结
XXXAutoConfiguration是一个个的自动配置类
自动配置类根据一个或多个@ConditionalOnXXX注解来判断这个类是否生效
一但这个配置类生效;这个配置类就会给容器中添加各种组件;
这些组件的属性是从对应的properties类中获取的
每一个priperties类又跟配置文件绑定(@ConfigurationProperties)
所有在配置文件中能配置的属性都是在xxxxProperties类中封装着;
这就是自动装配的原理 !
精髓
SpringBoot启动会加载大量的自动配置类
我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中;
我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在在其中,我们就不需要再手动配置了)
给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可;
查看生效的自动配置 在yml文件中debug: true
即可查看生效的(Positive matches)、未生效的自动配置类(Negative matches)、Exclusions、Unconditional classes