当前位置: 首页 > article >正文

SpringBoot(八) --- SpringBoot原理

目录

一、配置优先级

二、Bean的管理

1. Bean的作用域

2. 第三方Bean

三、SpringBoot原理

1. 起步依赖

2. 自动配置

3.  自动配置原理分析

3.1 源码解析

3.2 @Conditional


一、配置优先级

SpringBoot项目当中支持三类配置文件:

  • application.properties

  • application.yml

  • application.yaml

如果这三种配置文件同时存在,并且都配置了同一属性,如:Tomcat端口号,到底哪一份配置文件生效呢?

如下图所示,在application.properties配置文件中端口号设置为8081,在application.yml和application.yaml中端口号设置为8082。发现运行的端口号为8081.

properties、yaml、yml三种配置文件,优先级最高的是properties。

当properties不存在时,yaml、yml两种配置文件同时存在。会发现端口号为8083。

yaml、yml 两种配置文件,优先级最高的是yml。

总结:

配置文件的优先级为:properties配置文件、yml配置文件、yaml配置文件。但是目前主流使用的的配置文件为yml格式的。

二、Bean的管理

IOC容器中管理的就是Bean对象。

1. Bean的作用域

IOC容器中,默认bean对象是单例的 (只有一个实例对象)。Spring中支持五种作用域,后三种作用域在Web环境下才生效。(Web环境指的是传统Web开发,Spring环境指的是利用SSM框架开发的Web项目)。

可以借助Spring中的@Scope注解来配置作用域。

当设置Bean对象为单例时,例如下述代码:

//默认bean的作用域为:singleton (单例)
@RestController
@RequestMapping("/depts")
public class DeptController {@Autowiredprivate DeptService deptService;public DeptController(){System.out.println("DeptController constructor ....");}//省略其他代码...
}

测试类如下:

@SpringBootTest
class SpringbootWebConfig2ApplicationTests {@Autowiredprivate ApplicationContext applicationContext; //IOC容器对象//bean的作用域@Testpublic void testScope(){for (int i = 0; i < 10; i++) {DeptController deptController = applicationContext.getBean(DeptController.class);System.out.println(deptController);}}
}

结果如下图,可以发现,每一次创建的Bean实例都是同一个。

如果设置Bean的作用域非单例:

@Scope("prototype") //bean作用域为非单例
@RestController
@RequestMapping("/depts")
public class DeptController {@Autowiredprivate DeptService deptService;public DeptController(){System.out.println("DeptController constructor ....");}//省略其他代码...
}

结果如下图,可以发现,IOC容器创建了多个Bean实例,每一次使用Bean对象就会创建一个新的实例。

2. 第三方Bean

之前所配置的Bean,像controller、service,dao三层体系下编写的类,这些类都是我们在项目当中自己定义的类(自定义类)。当我们要声明这些bean,也非常简单,我们只需要在类上加上@Component以及它的这三个衍生注解(@Controller@Service@Repository),就可以来声明这个bean对象了。

当某个类不是我们自己编写的,而是我们引入的第三方依赖当中提供的,那么此时我们是无法使用 @Component 及其衍生注解来声明bean的,此时就需要使用@Bean注解来声明bean 了。

此时有两种方式来声明第三方类的Bean,一种是在启动类中直接声明这个Bean【不推荐】,另一种是将第三方的Bean对象进行集中管理,通过@Configuration 注解声明一个配置类。【推荐】。

这里只介绍第二种方式。创建一个包,专门用来存在配置类,下面代码是将阿里云操作的工具类进行Bean注入。

@Configuration
public class OSSConfig {@Beanpublic AliyunOSSOperator aliyunOSSOperator(AliyunOSSProperties ossProperties) {return new AliyunOSSOperator(ossProperties);}
}

这是将Redis的相关第三方类进行Bean注入:

@Configuration
@Slf4j
public class RedisConfiguration {@Beanpublic RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {log.info("开始创建redis模版对象..");RedisTemplate redisTemplate = new RedisTemplate<>();// 设置redis的连接工厂对象redisTemplate.setConnectionFactory(redisConnectionFactory);// 设置redis key的序列化器redisTemplate.setKeySerializer(new StringRedisSerializer());return redisTemplate;}
}

然后,就可以直接在Controller层使用这个第三方类,例如下面代码:

@RestController("userShopController")
@RequestMapping("/user/shop")
@Slf4j
public class ShopController {private static final String KET = "SHOP_STATUS";@Autowiredprivate RedisTemplate redisTemplate;/*** 获取店铺营业状态*/@GetMapping("/status")public Result getStatus() {Integer status = (Integer) redisTemplate.opsForValue().get(KET);log.info("获取营业状态为:{}", status == 1? "营业中" : "已打样");return Result.success(status);}
}

三、SpringBoot原理

Spring中的所有框架都是基于一个基础框架SpringFramework(也就是Spring框架)。SpringBoot框架的底层同样也是SpringFramework。

SpringBoot框架之所以使用起来更简单更快捷,是因为SpringBoot框架底层提供了两个非常重要的功能:一个是起步依赖,一个是自动配置

通过SpringBoot所提供的起步依赖,就可以大大的简化pom文件当中依赖的配置,从而解决了Spring框架当中依赖配置繁琐的问题。通过自动配置的功能就可以大大的简化框架在使用时bean的声明以及bean的配置。我们只需要引入程序开发时所需要的起步依赖,项目开发时所用到常见的配置都已经有了,我们直接使用就可以了。

1. 起步依赖

假如我们没有使用SpringBoot,用的是Spring框架进行web程序的开发,此时我们就需要引入web程序开发所需要的一些依赖。

但是如果使用SpringBoot,当我们引入了 spring-boot-starter-web 之后,maven会通过依赖传递特性,将web开发所需的常见依赖都传递下来。就不需要我们一个一个的去引用了。

简单理解就是,假如你想吃一份火锅。传统方式(老Spring)下,你需要单独下单锅底、肉、蔬菜等等东西,同时还要考虑选的菜品适不适合这个锅底等等。但是如果有了SpringBoot的起步依赖,就相当于你直接点了一个火锅套餐,你不需要考虑任何东西,只需要说一声“我要一个spring-boot-starter-web套餐”,后台就会自动将Web开发所需要的东西打包好。不需要一个一个找依赖,也不用担心版本冲突。

2. 自动配置

SpringBoot的自动配置就是当spring容器启动后,一些配置类、bean对象就自动存入到了IOC容器中,不需要我们手动去声明,从而简化了开发,省去了繁琐的配置操作。

例如,我们要将一个对象转为json,直接注入一个Gson,然后就可以直接使用了。而我们在我们整个项目中,也并未配置Gson这个类型的bean,为什么可以直接注入使用呢? 原因就是因为这个bean,springboot中已经帮我们自动配置完毕了,我们是可以直接使用的。

自动配置是Spring Boot在启动时,根据你项目的实际依赖​(类路径上有啥)和当前环境​(比如有没有配数据源URL),​自动判断并创建好一大堆常用的Bean(对象)和配置。它背后靠一堆@ConditionalOn...(条件满足才生效)的智能开关实现。

3.  自动配置原理分析

3.1 源码解析

要搞清楚SpringBoot的自动配置原理,要从SpringBoot启动类上使用的核心注解@SpringBootApplication开始分析:

元注解就是在注解上的注解,是必需的,不再解释。

先来看第一个注解:@SpringBootConfiguration:

@SpringBootConfiguration注解上使用了@Configuration,表明SpringBoot启动类就是一个配置类。

@Indexed注解,是用来加速应用启动的(不用关心)。

再来看@ComponentScan注解:

@ComponentScan注解是用来进行组件扫描的,扫描启动类所在的包及其子包下所有被@Component及其衍生注解声明的类。

SpringBoot启动类,之所以具备扫描包功能,就是因为包含了@ComponentScan注解。

最后来看@EnableAutoConfiguration注解(自动配置核心注解):

@EnableXxxxx这种格式的注解说白了就是第三方依赖中提供的注解,指定要导入哪些Bean对象或配置类,在使用的时候在启动类上加上@EnableXxxxx注解即可,@SpringBootApplication注解上加了@EnableAutoConfiguration注解,就会自动传递到启动类上。

@EnableAutoConfiguration注解上使用了@Import注解(Import注解才是真正用来导入类的注解,@EnableXxxx只是将其包装了一下)。

AutoConfigurationImportSelector类是ImportSelector接口的实现类。

AutoConfigurationImportSelector类中重写了ImportSelector接口的selectImports()方法,selectImports()方法底层调用getAutoConfigurationEntry()方法,获取可自动配置的配置类信息集合。

getAutoConfigurationEntry()方法通过调用getCandidateConfigurations(annotationMetadata, attributes)方法获取在配置文件中配置的所有自动配置类的集合。

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports配置文件中会指定许多第三方的配置类,例如第三方依赖Gson的配置类:GsonAutoConfiguration。

打开第三方依赖中提供的GsonAutoConfiguration类,可以发现GsonAutoConfiguration类上,添加了注解@AutoConfiguration,因此该类是个配置类

自动配置的原理就是在配置类中定义一个@Bean标识的方法,而Spring会自动调用配置类中使用@Bean标识的方法,并把方法的返回值注册到IOC容器中。

自动配置源码小结:

自动配置原理源码入口就是 @SpringBootApplication 注解,在这个注解中封装了3个注解,分别是:

  • @SpringBootConfiguration

    • 声明当前类是一个配置类

  • @ComponentScan

    • 进行组件扫描(SpringBoot中默认扫描的是启动类所在的当前包及其子包)

  • @EnableAutoConfiguration

      在实现类重写的selectImports()方法,读取当前项目下所有依赖jar包中META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports两个文件里面定义的配置类(配置类中定义了@Bean注解标识的方法)。

    • 封装了@Import注解(Import注解中指定了一个ImportSelector接口的实现类)

当SpringBoot程序启动时,就会加载配置文件当中所定义的配置类,并将这些配置类信息(类的全限定名)封装到String类型的数组中,最终通过@Import注解将这些配置类全部加载到Spring的IOC容器中,交给IOC容器管理。

但是并不是把文件中的所有Bean都注册到IOC容器当中,因为在声明Bean对象的时候,会有一个@Conditional开头的注解,这个注解的作用就是按照指定的条件进行装配,只有满足条件,,响应的Bean才会注册到IOC容器当中。

3.2 @Conditional

  • 作用:按照一定的条件进行判断,在满足给定条件后才会注册对应的bean对象到Spring的IOC容器中。

  • 位置:方法、类

  • @Conditional本身是一个父注解,派生出大量的子注解:

    • @ConditionalOnClass:判断环境中有对应字节码文件,才注册bean到IOC容器。

    • @ConditionalOnMissingBean:判断环境中没有对应的bean(类型或名称),才注册bean到IOC容器。

    • @ConditionalOnProperty:判断配置文件中有对应属性和值,才注册bean到IOC容器。

@ConditionalOnClass注解

@Configuration
public class HeaderConfig {@Bean@ConditionalOnClass(name="io.jsonwebtoken.Jwts")//环境中存在指定的这个类,才会将该bean加入IOC容器public HeaderParser headerParser(){return new HeaderParser();}//省略其他代码...
}

@ConditionalOnMissingBean注解(最常用)

@Configuration
public class HeaderConfig {@Bean@ConditionalOnMissingBean //不存在该类型的bean,才会将该bean加入IOC容器public HeaderParser headerParser(){return new HeaderParser();}//省略其他代码...
}

此时再来看看GsonAutoConfiguration这个配置类,@EnableConfigurationProperties(GsonProperties.class),这个注解明确告知SpringBoot框架,GsonProperties类是一个配置属性类(标注了 @ConfigurationProperties需要将配置文件(如application.yml)中前缀匹配的属性注入到该类的字段中:        

自动配置原理简要可体现为下图:

http://www.lryc.cn/news/2402182.html

相关文章:

  • SpringBoot自动化部署全攻略:CI/CD高效实践与避坑指南
  • idea json生成实体类
  • C# 类和继承(抽象成员)
  • gitlab rss订阅失败
  • 鸿蒙仓颉语言开发实战教程:商城登录页
  • JavaScript 数组与流程控制:从基础操作到实战应用
  • STM32中自动生成Flash地址的方法
  • Matlab | MATLAB 中的插值详解
  • SkyWalking架构深度解析:分布式系统监控的利器
  • vue2中的render函数
  • 逆向工程开篇(连载中)
  • this.$set() 的用法详解(Vue响应式系统相关)
  • PARADISE:用于新生儿缺氧缺血性脑病(HIE)疾病识别与分割的个性化和区域适应性方法|文献速递-深度学习医疗AI最新文献
  • RabbitMQ 监控与调优实战指南(二)
  • WordPress子主题RiPro-V5van无授权全开源版(源码下载)
  • 保姆级Elasticsearch集群部署指导
  • PyQt实现3维数组与界面TableWidget双向绑定
  • StoreView SQL,让数据分析不受地域限制
  • 护网面试题目2025
  • Figma 与 Cursor 深度集成的完整解决方案
  • UCRT 和 MSVC 的区别(Windows 平台上 C/C++ 开发相关)
  • rabbitmq Fanout交换机简介
  • 【机器学习】集成学习与梯度提升决策树
  • Palo Alto Networks Expedition存在命令注入漏洞(CVE-2025-0107)
  • WebFuture:Ubuntu 系统上在线安装.NET Core 8 的步骤
  • JAVA-springboot JUnit单元测试
  • hot100 -- 6.矩阵系列
  • PyCharm中运行.py脚本程序
  • 吴恩达MCP课程(5):research_server_prompt_resource.py
  • [论文阅读] 人工智能+项目管理 | 当 PMBOK 遇见 AI:传统项目管理框架的破局之路