SpringBoot原理
配置
- SpringBoot中支持三种格式的配置文件
.properties
.yml
.yaml
虽然Springboot支持多种文件配置,但是通常在项目开发中,我们一般推荐使用yml文件配置
优先级
在SpringBoot项目中,常见的属性配置有5种,3种配置文件加上两种外部的配置,生效优先级
- SrpingBoot配置优先级(低 -> 高):
1.application.yaml(忽略)
2.application.yml
3.application.properties
4.java系统属性(-Dxxx=xxx)
5.命令行参数(--xxx=xxx)
Bean管理
获取Bean
默认情况下,Springboot项目在启动的时候会自动创建IOC容器,并在创建好的bean对象存放在IOC容器当中,以供应用程序直接进行依赖注入
我们有三种方式可以从IOC容器中获取Bean
- 根据name获取bean
- 根据类型获取bean
- 根据name获取bean(带类型转换)
我们要先拿到IOC容器对象,才能获取bean对象
我们直接将IOC容器对象注入进来就可以
测试类:
@SpringBootTest class SpringbootWebConfig2ApplicationTests { @Autowired private ApplicationContext applicationContext; //IOC容器对象 //获取bean对象 @Test public void testGetBean(){ //根据bean的名称获取 DeptController bean1 = (DeptController) applicationContext.getBean("deptController"); System.out.println(bean1); //根据bean的类型获取 DeptController bean2 = applicationContext.getBean(DeptController.class); System.out.println(bean2); //根据bean的名称 及 类型获取 DeptController bean3 = applicationContext.getBean("deptController", DeptController.class); System.out.println(bean3); } }
测试类输出后的bean对象地址值是一样的,这说明IOC容器中的bean对象只有一个
Bean作用域
在IOC容器中,默认bean对象是单例模式,也就是上面案例输出的bean对象地址值相同,即容器中同名称的bean只有一个实例
在Spring中支持五种作用域,后三种在Web环境中才生效
作用域 | 说明 |
---|---|
singleton | 容器内同名称的bean只有一个实例(单例)(默认) |
prototype | 每次使用该bean时会创建新的实例(非单例) |
request | 每个请求范围内会创建新的实例(web环境中,了解) |
session | 每个会话范围内会创建新的实例(web环境中,了解) |
application | 每个应用范围内会创建新的实例(web环境中,了解) |
在IOC容器中默认是单例模式,我们可以通过Spring中的@Scope注解来进行配置作用域
@Scope("prototype")
IOC容器中的bean在容器启动时被创建,可以使用@Lazy注解来延迟初始化(延迟到第一次使用时)
第三方Bean
我们在项目中自己定义的类,如果我们要声明这些bean,我们只需要在类上加上@Component以及它的三个衍生注解@Controller,@Service,@Repository.就可以来声明这个bean对象
但是如果在项目开发中,有类不是我们自己编写的,而是我们引入的第三方依赖当中提供的。
当我们需要使用其他类时,我们无法在第三方类上添加@Component注解或衍生注解,那么如何定义第三方的bean呢,我们就需要用到@Bean注解
列如我们要使用SAXReader的方法我们只需要在启动类上添加@Bean标识的方法就可以了
- 在启动类上添加@Bean标识的方法
@SpringBootApplication public class SpringbootWebConfig2Application { public static void main(String[] args) { SpringApplication.run(SpringbootWebConfig2Application.class, args); } //声明第三方bean @Bean //将当前方法的返回值对象交给IOC容器管理, 成为IOC容器bean public SAXReader saxReader(){ return new SAXReader(); } }
xml文件:
<?xml version="1.0" encoding="UTF-8"?> <emp> <name>Tom</name> <age>18</age> </emp>
测试类:
@SpringBootTest class SpringbootWebConfig2ApplicationTests { @Autowired private SAXReader saxReader; //第三方bean的管理 @Test public void testThirdBean() throws Exception { Document document = saxReader.read(this.getClass().getClassLoader().getResource("1.xml")); Element rootElement = document.getRootElement(); String name = rootElement.element("name").getText(); String age = rootElement.element("age").getText(); System.out.println(name + " : " + age); } //省略其他代码... }
重启SpringBoot服务,执行测试方法后,控制台输出日志:
Tom : 18
注意:在项目中我们自己定义的类,我们想要把这些类交给IOC容器管理,我们可以直接使用@Component或者衍生注解来声明就可以,
但如果这个类不是我们自己定义的,而是引入的第三方依赖当中提供的类,我们想把这个类交给IOC容器管理,此时我们就需要在配置类中定义一个方法,在方法上加上一个@Bean注解
SpringBoot原理
前言
我们接下来来刨析一下SpringBoot的底层原理,因为SpringBoot能够是我们更加简单的进行业务能力的开发,不必过多的关注框架本身的配置使用。
Spring是世界上最流行Java框架,他可以帮助我们更加快速的,更加容易的构建Java项目。在Spring家族中有很多的优秀的框架,而所有的框架都是基于一个基础框架的SpringFramework。
由于Spring框架直接进行项目开发,会比较繁琐
- 在pom.xml中依赖配置比较繁琐,在项目开发时,需要自己去找到对应的依赖,还需要找到依赖它所配套的依赖以及对应版本,否则就会出现版本冲突问题。
- 在使用Spring框架进行项目开发时,需要在Spring的配置文件中做大量的配置,这就造成Spring框架入门难度较大,学习成本较高。
所以我们在Spring框架4.0版本之后,又推出了一个全新的框架SpringBoot,我们可以通过SpringBoot来简化Spring框架的开发,直接基于SpringBoot来构建Java项目
为什么要使用SpringBoot来构建开发呢?
主要有两个特别重要的功能
- 起步依赖
- 自动配置
起步依赖
我们没有使用SpringBoot,用的是Spring框架进行web程序的开发,此时我们就需要引入web程序开发所需要的一些依赖。
spring-webmvc依赖:这是Spring框架进行web程序开发所需要的依赖
servlet-api依赖:Servlet基础依赖
jackson-databind依赖:JSON处理工具包
如果要使用AOP,还需要引入aop依赖、aspect依赖
项目中所引入的这些依赖,还需要保证版本匹配,否则就可能会出现版本冲突问题。
如果我们使用SpringBoot,就只需要引入一个依赖就可以了,这就是Web开发的起步依赖:springboot-starter-web
原理是 Maven的依赖传递
在起步依赖中以提供了当前程序开发所需要的所有常见依赖,只需要引入这一个依赖,其他依赖就会自动的通过Maven的依赖传递进来
自动配置
自动配置就是当Spring容器启动后,一些配置类,bean对象就自动存入IOC容器中。不需要手动声明,简化操作。
SpringBoot项目在启动时通过自动配置完成了bean对象的创建。
在启动类中,有一个注解@SpringBootApplication,点进注解,有三个注解是比较重要的。
-
@SpringBootConfiguration:进去这个注解我们可以发现底层是Configuaration注解,也就是支持JavaConfig的方式来进行配置(使用Configuration配置类等同于XML文件)
-
@EnableAutoConfiguration:开启自动配置功能
-
@ComponentScan:扫描注解,默认是扫描当前类下的package。将
`@Controller/@Service/@Component/@Reposito
ry`等注解加载到IOC容器中
“约定大于配置”,在SpringBoot中是怎么做的呢,其实靠的就是@EnableAutoConfiguration,简单来说,这个注解可以帮助我们自动载入应用程序所需要的所有默认配置,点进去我们会发现
@AutoConfigurationPackage
:自动配置包@Import
:给IOC容器导入组件
我们再进入@AutoConfigurationPackage
可以发现,依靠的还是@Import
注解,再点进去查看,我们发现重要的就是以下的代码:
@Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { register(registry, new PackageImport(metadata).getPackageName()); }
在默认的情况下就是将:主配置类(@SpringBootApplication
)的所在包及其子包里边的组件扫描到Spring容器中。
我们回到@Import(AutoConfigurationImportSelector.class)
这句代码上,再点进去AutoConfigurationImportSelector.class
-
FACTORIES_RESOURCE_LOCATION
的值是META-INF/spring.factories
-
Spring启动的时候会扫描所有jar路径下的
META-INF/spring.factories
,将其文件包装成Properties对象 -
从Properties对象获取到key值为
EnableAutoConfiguration
的数据,然后添加到容器里边。其中
@EnableAutoConfiguration
是关键(启用自动配置),内部实际上就去加载META-INF/spring.factories
文件的信息,然后筛选出以EnableAutoConfiguration
为key的数据,加载到IOC容器中,实现自动配置功能!
常见方案
当我们在工程中,导入utils工程包时,我们如果在xml文件中通过坐标引入依赖。我们在测试方法中是无法找到bean对象的
原因
- 原因在我们之前讲解IOC的时候有提到过,在类上添加@Component注解来声明bean对象时,还需要保证@Component注解能被Spring的组件扫描到。
- SpringBoot项目中的@SpringBootApplication注解,具有包扫描的作用,但是它只会扫描启动类所在的当前包以及子包。
- 当前包:com.itheima, 第三方依赖中提供的包:com.example(扫描不到)
使用@ComponentScan组件扫描(启动类)
@SpringBootApplication @ComponentScan({"com.itheima","com.example"}) //指定要扫描的包 public class SpringbootWebConfig2Application { public static void main(String[] args) { SpringApplication.run(SpringbootWebConfig2Application.class, args); } }
@Import导入
- 导入形式主要有以下几种:
- 导入普通类
- 导入配置类
- 导入ImportSelector接口实现类
1). 使用@Import导入普通类:
@Import(TokenParser.class) //导入的类会被Spring加载到IOC容器中 @SpringBootApplication public class SpringbootWebConfig2Application { public static void main(String[] args) { SpringApplication.run(SpringbootWebConfig2Application.class, args); } }
2). 使用@Import导入配置类:
- 配置类
@Configuration public class HeaderConfig { @Bean public HeaderParser headerParser(){ return new HeaderParser(); } @Bean public HeaderGenerator headerGenerator(){ return new HeaderGenerator(); } }
- 启动类
@Import(HeaderConfig.class) //导入配置类 @SpringBootApplication public class SpringbootWebConfig2Application { public static void main(String[] args) { SpringApplication.run(SpringbootWebConfig2Application.class, args); } }
3). 使用@Import导入ImportSelector接口实现类:
- ImportSelector接口实现类
public class MyImportSelector implements ImportSelector { public String[] selectImports(AnnotationMetadata importingClassMetadata) { //返回值字符串数组(数组中封装了全限定名称的类) return new String[]{"com.example.HeaderConfig"}; } }
- 启动类
@Import(MyImportSelector.class) //导入ImportSelector接口实现类 @SpringBootApplication public class SpringbootWebConfig2Application { public static void main(String[] args) { SpringApplication.run(SpringbootWebConfig2Application.class, args); } }
本文作者:开卷日记
本文链接:https://www.cnblogs.com/yifan0820/p/17919388.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步