8--SpringBoot原理分析、注解-详解(面试高频提问点)

目录

@SpringBootApplication

1.元注解 --->元注解

@Target

@Retention

@Documented

@Inherited

2.@SpringBootConfiguration

@Configuration

@Component

@Indexed

3.@EnableAutoConfiguration(自动配置核心注解)

4.@ComponentScan

@Conditional

@ConditionalOnClass

@ConditionalOnMissingBean

@ConditionalOnProperty

自动配置原理


Java注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释

注解他本身是没有任何作用的,比如@RequestMapping,在controller层@RequestMapping基本上可以说是必见的,我们都知道他的作用是请求映射,通过他来设置请求的url地址,举例:将@RequestMapping("config")写在方法上,然后我们就可以通过url地址访问到这个方法了,但是记住这并不是@RequestMapping注解的功能,SpringMVC会通过反射将注解当中设置的属性值config拿到,然后将url和你声明注解的方法进行绑定。记住:注解只是用来标记,而这个注解真正的功能都是由框架通过反射来实现的。

Java注解-最通俗易懂的讲解_java 注解-CSDN博客

@SpringBootApplication

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

@SpringBootApplication注解中包含了:

  • 元注解(不再解释)
  • @SpringBootConfiguration表示是配置类
  • @EnableAutoConfiguration 由Enable开头的注解
  • @ComponentScan组件扫描

1.元注解 --->元注解

写在注解定义上的注解叫元注解(注解是给程序提供信息,写在注解上的注解是给注解提供信息,给信息提供信息的叫元信息)。

@Target

用于指定注解的使用范围或目标,描述定义的注解可以在哪里(包、类、接口、类成员方法、类成员变量、方法参数、局部变量、枚举类型)使用。不写就是表示可以用在所有位置上

  • ElementType.TYPE:类、接⼝、注解、枚举
  • ElementType.FIELD:字段、枚举常量
  • ElementType.METHOD:⽅法
  • ElementType.PARAMETER:形式参数
  • ElementType.CONSTRUCTOR:构造⽅法
  • ElementType.LOCAL_VARIABLE:局部变量
  • ElementType.ANNOTATION_TYPE:注解
  • ElementType.PACKAGE:包
  • ElementType.TYPE_PARAMETER:类型参数
  • ElementType.TYPE_USE:类型使⽤

@Retention

描述注解的作用范围,即注解的有效范围。表示生命周期。告诉注解信息保留到哪个阶段,如果注释类型声明中不存在 Retention 注释,则保留策略默认为 RetentionPolicy.CLASS。

JDK定义了三种有效范围,分别是:注解作用于源代码(编译器可读取注解)、注解作用于类文件(在类文件中可读取注解)、注解作用于运行过程(用反射技术读取注解)。

JDK定义了RetentionPolicy枚举类型用于描述注解作用范围,RetentionPolicy有如下枚举值:

  • RetentionPolicy.SOURCE:注解作用于源代码(编译器要丢弃的注解)
  • RetentionPolicy.CLASS:注解作用于类文件(编译器将把注解记录在类文件中,但在运行时 JVM 不需要保留注释)
  • RetentionPolicy.RUNTIME:注解作用于运行时(编译器将把注解记录在类文件中,在运行时JVM 将保留注解,因此可以反射性地读取)

@Documented

表示是否将我们的注解生成在Javadoc中。如果一个注解定义时间使用了该元注解,那么产生的javadoc文档就会把注解显示出来。

@Inherited

表示该注解具有继承性,用于子类是可以继承父类中的注解。

2.@SpringBootConfiguration

@Configuration

--> @Configuration 

声明一个类为配置类,用于取代bean.xml配置文件注册bean对象。

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

类。

底层代码就两个属性,一个用于声明配置类的名称,一个用于声明是否是代理对象方法(重点)。

由于有@Component注解的加持,因此它自己本身也是一个bean对象

@Component

-->@Component

标注Spring管理的Bean,使用@Component注解在一个类上,表示将此类标记为Spring容器中的一个Bean。

基于@Component拓展的注解

  • @controller: controller控制器层(注入服务)
  • @service : service服务层(注入dao)
  • @repository : dao持久层(实现dao访问)
  • @component: 标注一个类为Spring容器的Bean,(把普通pojo实例化到spring容器中,相当于配置文件中的)
  • @Service用于标注业务层组件
  • @Controller用于标注控制层组件(如struts中的action)
  • @Repository用于标注数据访问组件,即DAO组件.
  • @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注,标识为一个Bean。

@Indexed

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

3.@EnableAutoConfiguration(自动配置核心注解)

使用@Import注解,导入了实现ImportSelector接口的实现类。

AutoConfigurationImportSelector类是ImportSelector接口的实现类。

AutoConfigurationImportSelector类中重写了ImportSelector接口的selectImports()方法:

 selectImports()方法底层调用getAutoConfigurationEntry()方法,获取可自动配置的配置类信息集合

getAutoConfigurationEntry()方法通过调用getCandidateConfigurations(annotationMetadata,

attributes)方法获取在配置文件中配置的所有自动配置类的集合

getCandidateConfigurations方法的功能:

获取所有基于META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件、META-INF/spring.factories文件中配置类的集合

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件和META-INF/spring.factories文件这两个文件在哪里呢?

通常在引入的起步依赖中,都有包含以上两个文件

4.@ComponentScan

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

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

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

  • @SpringBootConfiguration 声明当前类是一个配置类
  • @ComponentScan 进行组件扫描(SpringBoot中默认扫描的是启动类所在的当前包及其子包)
  • @EnableAutoConfiguration 封装了@Import注解(Import注解中指定了一个ImportSelector接口的实现类) 在实现类重写的selectImports()方法,读取当前项目下所有依赖jar包中META-INF/spring.factories、META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports两个文件里面定义的配置类(配置类中定义了@Bean注解标识的方法)。

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

问题:在META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中定义的配置类非常多,而且每个配置类中又可以定义很多的bean,那这些bean都会注册到Spring的IOC容器中吗?

答案:并不是。 在声明bean对象时,上面有加一个以@Conditional开头的注解,这种注解的作用就是按照条件进行装配,只有满足条件之后,才会将bean注册到Spring的IOC容器中

在跟踪SpringBoot自动配置的源码的时候,在自动配置类声明bean的时候,除了在方法上加了一个@Bean注解以外,还会经常用到一个注解,就是以Conditional开头的这一类的注解。以Conditional开头的这些注解都是条件装配的注解。下面来介绍下条件装配注解。

@Conditional

按照一定的条件进行判断,在满足给定条件后才会注册对应的bean对象到Spring的IOC容器
中。
位置:方法、类
@Conditional本身是一个父注解,派生出大量的子注解: 
  • @ConditionalOnClass:判断环境中有对应字节码文件,才注册bean到IOC容器。
  • @ConditionalOnMissingBean:判断环境中没有对应的bean(类型或名称),才注册bean到IOC容器。
  • @ConditionalOnProperty:判断配置文件中有对应属性和值,才注册bean到IOC容器。

@ConditionalOnClass

@ConditionalOnClass注解

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

pom.xml

<!--JWT令牌-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>

测试类

@SpringBootTest
public class AutoConfigurationTests {
@Autowired
private ApplicationContext applicationContext;
@Test
public void testHeaderParser(){
System.out.println(applicationContext.getBean(HeaderParser.class));
}
//省略其他代码...
}

@ConditionalOnMissingBean

@ConditionalOnMissingBean注解

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

@ConditionalOnProperty

@ConditionalOnProperty注解(这个注解和配置文件当中配置的属性有关系)

先在application.yml配置文件中添加如下的键值对:

name: itheima

在声明bean的时候就可以指定一个条件@ConditionalOnProperty

@Configuration
public class HeaderConfig {
@Bean
@ConditionalOnProperty(name ="name",havingValue = "itheima")//配置文件中存在指定
属性名与值,才会将bean加入IOC容器
public HeaderParser headerParser(){
return new HeaderParser();
}
@Bean
public HeaderGenerator headerGenerator(){
return new HeaderGenerator();
}
}

自动配置原理

自动配置的核心就在@SpringBootApplication注解上,SpringBootApplication这个注解底层包含

了3个注解,分别是:

  • @SpringBootConfiguration
  • @ComponentScan
  • @EnableAutoConfiguration

@EnableAutoConfiguration这个注解是自动配置的核心

它封装了一个@Import注解,Import注解里面指定了一个ImportSelector接口的实现类。

在这个实现类中,重写了ImportSelector接口中的selectImports()方法。而selectImports()方法中会去读取两份配置文件,并将配置文件中定义的配置类做为selectImports()方法的返回值返回,返回值代表的就是需要将哪些类交给Spring的IOC容器进行管理。

问题:那么所有自动配置类的中声明的bean都会加载到Spring的IOC容器中吗?

答案:并不会,因为这些配置类中在声明bean时,通常都会添加@Conditional开头的注解,这个注解就是进行条件装配。而Spring会根据Conditional注解有选择性的进行bean的创建。

@Enable 开头的注解底层,它就封装了一个注解 import 注解,它里面指定了一个类,是ImportSelector 接口的实现类。在实现类当中,我们需要去实现 ImportSelector 接口当中的一个方法 selectImports 这个方法。这个方法的返回值代表的就是我需要将哪些类交给spring 的 IOC容器进行管理。

此时它会去读取两份配置文件,一份是 spring.factories,另外一份是autoConfiguration.imports。而在 autoConfiguration.imports 这份儿文件当中,它就会去配置大量的自动配置的类。

问题:而前面我们也提到过这些所有的自动配置类当中,所有的 bean都会加载到 spring 的 IOC 容器当中吗?

答案:其实并不会,因为这些配置类当中,在声明 bean 的时候,通常会加上这么一类@Conditional 开头的注解。这个注解就是进行条件装配。所以SpringBoot非常的智能,它会根据 @Conditional 注解来进行条件装配。只有条件成立,它才会声明这个bean,才会将这个 bean 交给 IOC 容器管理。

SpringBoot原理:7--SpringBoot-后端开发、原理详解(面试高频提问点)-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/429580.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于PHP的新闻管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于phpMySQL的新闻管理系统。…

JavaWeb--纯小白笔记03:servlet入门---动态网页的创建

笔记&#xff1a;index.html在tomcat中为默认的名字&#xff0c;html里面的语法不严谨。改配置文件要小心&#xff0c;不然容易删掉其他 Servlet&#xff1a;服务器端小程序&#xff0c;写动态网页需要用Servlet&#xff0c;普通的java类通过继承HttpServlet&#xff0c;可以响…

【GUI设计】基于Matlab的图像处理GUI系统(1),用matlab实现

博主简介&#xff1a;matlab图像代码项目合作&#xff08;扣扣&#xff1a;3249726188&#xff09; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于Matlab的图像处理GUI系统&#xff0c;用matlab实现。 本次内容主要分为两部分&a…

Why is OpenAI image generation Api returning 400 bad request in Unity?

题意&#xff1a;为什么 OpenAI 图像生成 API 在 Unity 中返回 400 Bad Request 错误&#xff1f; 问题背景&#xff1a; Im testing out dynamically generating images using OpenAI API in Unity. Amusingly, I actually generated most of this code from chatGPT. 我正在…

【笔记】第二节 轧制、热处理和焊接工艺

2.2 钢轨的轧制工艺 坯料进厂按标准验收, 然后装加热炉加热, 加热好的钢坯经高压水除鳞后进行轧制。轧出的钢轨经锯切、打印到中央冷床冷却, 然后装缓冷坑进行缓冷。缓冷后的钢轨进行矫直、轨端加工和端头淬火。钢轨入库前逐根进行探伤和外观检查。 钢轨的轧制 #mermaid-svg-…

foreach,for in和for of的区别

forEach 不能使用break return 结束并退出循环 for in 和 for of 可以使用break return&#xff1b; for in 遍历的是数组的索引&#xff08;即键名&#xff09;&#xff0c;而for of遍历的是数组元素值。 for of 遍历的只是数组内的元素&#xff0c;而不包括数组的原型属性…

后端-navicat查找语句(单表与多表)

表格字段设置如图 语句&#xff1a; 1.输出 1.输出name和age列 SELECT name,age from student 1.2.全部输出 select * from student 2.where子语句 1.运算符&#xff1a; 等于 >大于 >大于等于 <小于 <小于等于 ! <>不等于 select * from stude…

JdbcTemplate常用方法一览AG网页参数绑定与数据寻址实操

JdbcTemplate是Spring框架中的一个重要组件&#xff0c;主要用于简化JDBC数据库操作。它提供了许多常用的方法&#xff0c;如查询、插入、更新、删除等。本文将介绍JdbcTemplate的常用方法及其使用方式&#xff0c;以及参数绑定和删除数据的方法。 一、JdbcTemplate常用方法 查…

钉钉与MySQL对接集成获取部门列表2.0打通EXECUTE语句

钉钉与MySQL对接集成获取部门列表2.0打通EXECUTE语句 接入系统&#xff1a;钉钉 钉钉是阿里巴巴集团打造的企业级智能移动办公平台&#xff0c;是数字经济时代的企业组织协同办公和应用开发平台。钉钉将IM即时沟通、钉钉文档、钉闪会、钉盘、Teambition、OA审批、智能人事、钉工…

828华为云征文|华为Flexus云服务器搭建Cloudreve私人网盘

一、华为云 Flexus X 实例&#xff1a;开启高效云服务新篇&#x1f31f; 在云计算的广阔领域中&#xff0c;资源的灵活配置与卓越性能犹如璀璨星辰般闪耀。华为云 Flexus X 实例恰似一颗最为耀眼的新星&#xff0c;将云服务器技术推向了崭新的高度。 华为云 Flexus X 实例基于…

基于SpringBoot+Vue的商城积分系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目源码、Python精…

我的AI工具箱Tauri版-MicrosoftTTS文本转语音

本教程基于自研的AI工具箱Tauri版进行MicrosoftTTS文本转语音服务。 MicrosoftTTS文本转语音服务 是自研的AI工具箱Tauri版中的一款功能模块&#xff0c;专为实现高效的文本转语音操作而设计。通过集成微软TTS服务&#xff0c;用户可以将大量文本自动转换为自然流畅的语音文件…

物理学基础精解【9】

文章目录 直线与二元一次方程两直线夹角直线方程斜率两点式方程截距式方程将不同形式的直线方程转换为截距方程直线的一般方程直线一般方程的系数有一个或两个为零的直线 参考文献 直线与二元一次方程 两直线夹角 两直线 y 1 k 1 x b 1 , y 2 k 2 x b 2 形成夹角 a 1 和 a…

关于字节 c++

字节的介绍 字节是计算机中最小的存储单位&#xff0c;通常由8个二进制位组成&#xff0c;用来存储一个字符。在C中&#xff0c;字节也是基本数据类型之一&#xff0c;用关键字"byte"来表示。字节主要用于存储一些较小的数据&#xff0c;如整数、字符等。字节的大小…

【Delphi】通过 LiveBindings Designer 链接控件示例

本教程展示了如何使用 LiveBindings Designer 可视化地创建控件之间的 LiveBindings&#xff0c;以便创建只需很少或无需源代码的应用程序。 在本教程中&#xff0c;您将创建一个高清多设备应用程序&#xff0c;该应用程序使用 LiveBindings 绑定多个对象&#xff0c;以更改圆…

python - self 调用父类方法

Python 子类继承父类构造函数说明 | 菜鸟教程如果在子类中需要父类的构造方法就需要显式地调用父类的构造方法&#xff0c;或者不重写父类的构造方法。 子类不重写 __init__&#xff0c;实例化子类时&#xff0c;会自动调用父类定义的 __init__。 实例 [mycode3 typepython] cl…

Linux基础---13三剑客及正则表达式

一.划水阶段 首先我们先来一个三剑客与正则表达式混合使用的简单示例&#xff0c;大致了解是个啥玩意儿。下面我来演示一下如何查询登录失败的ip地址及次数。 1.首先&#xff0c;进入到 /var/log目录下 cd /var/log效果如下 2.最后&#xff0c;输入如下指令即可查看&#xf…

基于协同过滤+python+django+vue的音乐推荐系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于协同过滤pythondjangovue…

Linux使用常见问题指南

普通用户sudo权限问题 我在普通用户Sun下,编写了一个.cc文件,然后用sudo权限安装gcc/g去运行该文件,却提示我如下: 原因 当前的用户没有加入到sudo的配置文件里 #切换到root用户 su #编辑配置文件 vim /etc/sudoers #增加配置, 在打开的配置文件中&#xff0c;找到root ALL(A…

【iOS】ViewController的生命周期

相关函数 init: 初始化ViewController。viewDidLoad:在我之前学习中最多使用的方法&#xff0c;在创建类后无论视图展示还是消失&#xff0c;该方法只调用一次在布局中&#xff0c;类成员对象和变量的初始化都会放在这个方法中。viewWilAppear:如同英语含义一样&#xff0c;在…