当前开发环境:
Spring Boot 2.4
Spring 5
java 8
Maven 3
参考官方文档版本:2.4.1
个人学习记录
依赖管理
依赖管理
<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>
几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制
不过版本可以自己选的,在当前项目里重写配置(Maven就近原则)
starter:
- 见到很多 spring-boot-starter-* : *就某种场景
- 只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
- SpringBoot所有支持的场景
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter - 见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
- 所有场景启动器最底层的依赖
Spring Boot自动配置的核心依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
引入依赖一般可以不写版本号
自动配置
自动配置Tomcat
自动配置好SpringMVC,引入全套组件
自动配置好Web常见功能
@SpringBootApplication
public class SecondApplication {
public static void main(String[] args) {
//返回IOC容器
ConfigurableApplicationContext run = SpringApplication.run(SecondApplication.class, args);
//查看容器组件
String[] names = run.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
}
主程序所在的包及其下面的子包里的组件都会被默认扫描进来。
改变扫描路径
@SpringBootApplication(scanBasePackages="com.example") 或者: @ComponentScan("xxxx") //指定扫描路径 不过上面的注解包含了下面的注解,使用的时候不能一起用
容器功能
组件添加
@Configuration 👌 配置类
@Configuration
是配置类的注解
配置类本身也是组件
给容器中注册的这两个组件,默认是单实例的。
proxyBeanMethods参数
proxyBeanMethods参数 :是否代理Bean的方法
如果是true,获取到的就是代理对象调用方法
会先检测容器里有没有组件
有就直接拿
没有再调用方法返回一个组件@Configuration(proxyBeanMethods = true)
此时外部无论对配置类中的组件注册方法调用多少次获取的都是之前注册容器中的单实例对象。
将proxyBeanMethods设置为false,配置类不再是代理对象@Configuration(proxyBeanMethods = false)
Configuration的两种配置
- Full 模式:@Configuration(proxyBeanMethods = true) 全模式
- Lite 模式:@Configuration(proxyBeanMethods = false) 轻量级模式
解决组件依赖场景
- false模式SpringBoot不会检查容器中有没有这个组件,这样启动会比较快。如果只是给容器注册组件,也没有依赖组件,设置成false可以提高加载速度。
- 如果组件依赖了另一个组件,就设置成True,这样可以保证它依赖的组件就是容器中的组件。
其他组件注解
@Component
//组件
@Controller
//控制器
@Service
//业务逻辑
@Repository
//数据库层组件
只需要组件写在包扫描范围内
@ComponentScan 通过包扫描指定包扫描规则
@Import 👌 组件导入
@Import要写在一个容器中的组件的类上
将指定类型的组件导入
给容器自动创建出指定类的无参构造器返回的组件@Import({User.class,XXX.class})
所以这里User类有两个组件
@Conditional 👌 条件装配
条件装配:满足指定条件,则进行组件注入
条件不满足所以没有。
不过这里有个问题,,其实不管怎么样结果都会是false,这个条件会失效。
原因是:
在配置类中定义Bean,如果使用@ConditionalOnBean注解依赖的Bean是通过配置类触发解析的,则执行结果依赖配置类加载顺序
包括其他条件装配直接测试可能也会有一些问题,但是SpringBoot的底层使用了很多条件装配,,,,,,
原生配置文件引入
@ImportResource
如果组建的注入还是使用xml文件的话
可以使用
//通过xml配置文件导入
@ImportResource("classpath:beans.xml")
配置绑定
@ConfigurationProperties+@Component
@Component:注入到容器中作为组件
@ConfigurationProperties:和配置文件绑定
测试:
可以看到和配置文件已经绑定
@EnableConfigurationProperties
@EnableConfigurationProperties:开启指定类的属性配置功能,并且注入到容器中
和配置文件绑定还是要绑定的。
自动配置原理 ✍
@SpringBootApplication
- @SpringBootConfiguration 当前是核心配置类
- @EnableAutoConfiguration !
- @ComponentScan 包扫描
@EnableAutoConfiguration
- @AutoConfigurationPackage
- @Import(AutoConfigurationImportSelector.class)
@AutoConfigurationPackage
导入Registar类
利用Register手工注册一个Bean:
ImportBeanDefinitionRegistar
这个Bean可以用来注册扫描路径到全局变量,提供查询
将指定的一个包下的所有组件导入进来 main所在的包下
–>就是为什么默认的包路径是main程序所在的包
@Import(AutoConfigurationImportSelector.class)
selectImports方法会返回一个字符串数组,数组里放的是类的全路径,最后会加载到IOC容器中,最后成为Bean。
上图中的组件都是默认要导入到容器中的,通过getCandidateConfigurations方法获取所有的候选配置。
通过SpringFactoriesLoader.loaderFactoryNames加载META-INF/Spring.factories中的EnableAutoConfiguration
再追溯
再追溯
从圈住的这个位置加载一个文件,默认扫描当前系统所有该位置的文件
spring-boot-autoconfigure-2.4.2.jar这个包里也有META-INF/Spring-factories
配置文件里已经写好了SpringBoot一启动要给容器加载的所有配置类
虽然这130+个场景的所有自动配置启动的时候默认全部加载,但是最终会按需配置。
按需开启自动配置项
按照条件装配规则,最终会按需配置
查看自动配置
想看自动配置都配置了哪些可以这样:
开启自动配置报告
修改Banner