@AutoConfigurationPackage注解详解

news2024/11/20 11:30:48

@AutoConfigurationPackage是在springboot启动类注解@SpringBootApplication下的@EnableAutoConfiguration下。@AutoConfigurationPackage作用是指定springboot扫描包,默认就是扫描启动类同包下的类。可以通过@AutoConfigurationPackage来附加其他路径,然后springboot同样会进行扫描。

扫描包就是指的这个包下使用@Service、@Controller…等注解的会被存入Spring容器。

目录

    • 一、观察@AutoConfigurationPackage结构
    • 二、@Import通过ImportBeanDefinitionRegistrar接口注入
    • 三、分析Registrar结构
    • 四、分析BeanDefinitionRegistry
    • 五、深入分析Registrar类
    • 六、@AutoConfigurationPackage的两个属性
    • 七、包名的作用

一、观察@AutoConfigurationPackage结构

源码当中除了@Import注解以外,其他四个注解都是Java当中的元注解,所以间接的可以理解为他就是@Import扩展注解:

  • @Target({ElementType.TYPE}): 使用范围接口、类、枚举、注解
  • @Retention(RetentionPolicy.RUNTIME): @Retention是用来修饰注解的生命周期的,RetentionPolicy.RUNTIME代表的是不仅被保存到class文件中,jvm加载class文件之后,仍然存在;一直有效!
  • @Documented: @Documented和@Deprecated注解长得有点像,@Deprecated是用来标注某个类或者方法不建议再继续使用,@Documented只能用在注解上,如果一个注解@B,被@Documented标注,那么被@B修饰的类,生成Javadoc文档时,会显示@B。
  • @Inherited: 如果一个类用上了@Inherited修饰的注解,那么其子类也会继承这个注解。

想深入了解元注解的可以看一下这一篇文章:https://blog.csdn.net/weixin_43888891/article/details/126963074

11

通过源码不难发现,他的核心就是@Import({Registrar.class}),再直白点说就是Registrar

RegistrarAutoConfigurationPackages当中的一个内部类,注意这个类实现了ImportBeanDefinitionRegistrar接口。通过@Import注入对象一共有四种方式,通过ImportBeanDefinitionRegistrar接口的实现类注入就是其中一种方式!

在这里插入图片描述

二、@Import通过ImportBeanDefinitionRegistrar接口注入

对@Import注解不是很了解的一定要先了解@Import注解

首先我们先自定义个类,然后通过@Import通过ImportBeanDefinitionRegistrar接口注入的方式将TestBean4放入到容器当中。

public class TestBean4 {
    @Override
    public String toString() {
        return super.toString() + "--我是TestBean4";
    }
}

自定义ImportBeanDefinitionRegistrar 实现类,当然可能您对这块代码还不是很了解,不要慌,接着往下读!

public class ImportBeanByImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(TestBean4.class);
        registry.registerBeanDefinition("TestBean4", rootBeanDefinition);
    }
}

Myconfig放到springboot扫描的路径当中去,这样启动项目就可以将TestBean4给注入到容器当中。

@Configuration
@Import({TestBean1.class,
        ImportBeanByConfig.class,
        ImportBeanByImportSelector.class,
        ImportBeanByImportBeanDefinitionRegistrar.class})
public class Myconfig {
}

对上面@Import注入简单分析一下

通过打断点,可以看出来AnnotationMetadata其实就是@Import所在的类当中的元数据。这个元数据就是@Import所在的类信息,例如这个类的全类名以及所用到了哪些注解等等…

在这里插入图片描述

三、分析Registrar结构

通过以上示例我们最起码掌握了重要的一点,只要使用@Import注入ImportBeanDefinitionRegistrar实现类, 那他就会执行registerBeanDefinitions方法

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
   Registrar() {
   }

   public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
       AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
   }

   public Set<Object> determineImports(AnnotationMetadata metadata) {
       return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata));
   }
}

接下来重点看registerBeanDefinitions方法,他一共有两个参数AnnotationMetadataBeanDefinitionRegistry

四、分析BeanDefinitionRegistry

BeanDefinitionRegistry也是registerBeanDefinitions方法当中一个参数,相对来说比较复杂点了,首先他是一个接口,我们通过断点可以看到他传过来的是DefaultListableBeanFactory实现类!其次我们打开可以看到,他的beanDefinitionMap属性会发现,我们项目注册的bean竟然就都在这个map当中,没错这确实是spring当中最核心的内容,IOC容器!

在这里插入图片描述

我们打开DefaultListableBeanFactory可以发现key是个String类型,就是我们经常所说的Bean 的名称,value 就是对象本身,当然要知道一个正常的对象,他是有很多属性的,例如是否是单例的,以及是否是懒加载的,等等。所以Java就将真正的对象封装成了BeanDefinition对象。BeanDefinition存储着真正的对象,以及对象的相关属性。

在这里插入图片描述
在这里插入图片描述

重新熟悉一下@Import注入ImportBeanDefinitionRegistrar实现类

读到这,相信大家应该知道下面的代码原理了。其实下面代码特别简单,只要设置的@Import注入的是ImportBeanDefinitionRegistrar实现类,他就会执行registerBeanDefinitions方法,并且会传进来两个参数。而这两个参数就是上面讲过的。

通过以上得知map当中的value是BeanDefinition对象,而BeanDefinition是一个接口,而RootBeanDefinition就是BeanDefinition其中一个实现类。

public class ImportBeanByImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(TestBean4.class);
        registry.registerBeanDefinition("TestBean4", rootBeanDefinition);
    }
}

registerBeanDefinition方法就是将对象存入到了map当中。

在这里插入图片描述

五、深入分析Registrar类

首先他会执行register方法。register方法有两个参数,一个是BeanDefinitionRegistry ,还有一个是可变长参数。

public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
   AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
}

通过打断点得知,packageNames传的就是启动类所在的包名,然后这个方法就是判断容器是否注入了BasePackagesBeanDefinition。如果注入了就从容器获取,并将包名赋值给他的basePackages属性,然后执行这块的时候其实是并没有注册的,所以直接执行else。else就是直接创建一个BasePackagesBeanDefinition对象,然后将包名赋值给他的basePackages属性。

在这里插入图片描述

basePackages是个set集合,但是容器当中始终只有一个BasePackagesBeanDefinition对象,也就是只要代码当中添加@AutoConfigurationPackage注解,就会将注解所在的包名添加到basePackages集合当中。

在这里插入图片描述

六、@AutoConfigurationPackage的两个属性

String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};

basePackages就是指定包名,默认是@AutoConfigurationPackage注解所在的包。

@AutoConfigurationPackage(basePackages = "com.gzl")

basePackageClasses 指定一个类,就是读取这个类所在的包。

@AutoConfigurationPackage(basePackageClasses = ImportBeanByConfig.class)

七、包名的作用

其实这个就是springboot默认的扫描包。也就是这个包下的只要使用注入容器相关的注解,就会被放入到IOC容器当中。如下示例,ImportBeanByConfig并不和启动类注解同包,以至于根本就扫描不到他,可以通过@AutoConfigurationPackage(basePackageClasses = ImportBeanByConfig.class),将这个注解放到可以被扫描的类当中即可,启动类是不可以存放的,因为启动类本身就已经有@AutoConfigurationPackage注解了,可以放到@Configuration修饰的类当中,这样项目启动后就会将ImportBeanByConfig注入到容器当中了。

在这里插入图片描述

@Configuration
@AutoConfigurationPackage(basePackageClasses = ImportBeanByConfig.class)
public class Myconfig {
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

asp.net园林绿化服务交易网站

本设计的目的是通过对园林绿化的初步了解&#xff0c;在巩固网站设计所学知识的基础上。运用于实践&#xff0c;在实践中强化理论知识&#xff0c;做到理论联系实践。在设计中学会搜集资料地方法&#xff0c;学会查阅设计规程。掌握设计步骤&#xff0c;同时培养创新能力&#…

【图像评价】基于matlab GUI图像评价系统【含Matlab源码 2185期】

一、图像质量评价 图像质量评价对图像处理算法的可行性分析以及某类算法达成效果的比较都起着非常重要的指导作用。随着图像处理技术的发展&#xff0c;对于图像质量评价的研究也日益深入&#xff0c;新的评价指标和评价算法不断涌现&#xff0c;共同推动了图像质量评价的进步…

【模型训练】YOLOv7旋翼无人机检测

YOLOv7旋翼无人机检测 1、YOLOv7算法旋翼无人机检测模型训练2、YOLOv7模型模型评估3、模型和数据集下载1、本项目采用YOLOv7算法实现对空中旋翼无人机的检测,在一万多张旋翼无人机检测数据集中训练得到,我们训练了YOLOv7模型,经评估我们得出了各个模型的评价指标; 2、目标类…

研发效能工程实践开篇

背景 随着技术的发展&#xff0c;大至一线互联网公司、小至几十人研发团队的公司都开始开展devops运动。大公司有能力自研&#xff0c;小公司则采用开源解决方案。如何实施devops业界已经有非常成熟的方案&#xff0c;所以本系列不再谈devops工具链以及如何实施。本系列想谈谈…

初识C++ - 类与对象(中篇·下半)

目录 赋值运算符重载 以下是一个日期类的运算符重载的案例(重点) 关于流插入与流提取的使用 方法一&#xff1a;定义与声明分离 方法二&#xff1a;使用内联函数 const成员 概念 关于上述日期类代码为什么需要在函数后面加入const 取地址及const取地址操作符重载 …

5G核心网技术基础自学系列 | 网络切片

书籍来源&#xff1a;《5G核心网 赋能数字化时代》 一边学习一边整理内容&#xff0c;并与大家分享&#xff0c;侵权即删&#xff0c;谢谢支持&#xff01; 附上汇总贴&#xff1a;5G核心网技术基础自学系列 | 汇总_COCOgsta的博客-CSDN博客 支持网络切片是设计5G架构的主要驱…

【牛客刷题--SQL篇】必会的常用函数之条件函数SQL26计算25岁以上和以下的用户数量(多种写法)

&#x1f496;个人主页&#xff1a;与自己作战 &#x1f4af;作者简介&#xff1a;CSDN博客专家、CSDN大数据领域优质创作者、CSDN内容合伙人、阿里云专家博主 &#x1f49e;牛客刷题系列篇&#xff1a;【SQL篇】】【Python篇】【Java篇】 &#x1f4cc;推荐刷题网站注册地址&a…

基于WEB的二维码生成系统设计与实现(Asp.net)

目 录 1 引言 6 2 二维码的生成原理 6 2.1基础知识 6 2.1.1定位图案 7 2.1.2功能性数据 8 2.1.3数据码和纠错码 8 2.2数据编码 8 2.3结束符和补齐符 9 2.3.1补齐码&#xff08;Padding Bytes&#xff09; 9 2.3.2纠错码 10 2.4最终编码 11 2.4.1穿插放置 11 2.4.2Remainder Bi…

JWT基础概念

1. 介绍 JWT &#xff08;JSON Web Token&#xff09; 是目前最流行的跨域认证解决方案&#xff0c;是一种基于 Token 的认证授权机制。 从 JWT 的全称可以看出&#xff0c;JWT 本身也是 Token&#xff0c;一种规范化之后的 JSON 结构的 Token。 JWT 自身包含了身份验证所需要…

【正点原子I.MX6U-MINI应用篇】6、嵌入式Linux在LCD屏幕上显示字符

一、原始方式&#xff1a; 取模显示字符 LCD显示屏是由width * height个像素点构成的&#xff0c;显示字符&#xff0c;一个非常容易想到的方法便是对字符取模&#xff0c;然后在LCD屏上打点显示字符&#xff1b;如果大家以前学习过单片机&#xff0c;想必接触过一些显示屏&am…

三次、五次多项式插值(附代码)

文章目录一、三次多项式插值二、五次多项式插值三、matlab代码三次、五次多项式插值在工程实践中很常见。求解多项式的系数最直接的方法是根据端点处的约束条件&#xff0c;列出线性方程组&#xff0c;再写成矩阵方程AXB&#xff0c;然后用通用的方法(如高斯消元法、LU分解等)解…

二叉树广度优先搜索、深度优先搜索(前序、中序、后序)遍历,动图详解-Java/Kotlin双版本代码

自古逢秋悲寂寥&#xff0c;我言秋日胜春朝 二叉树结构说明 本博客使用树节点结构&#xff0c;如下所示&#xff1a; Kotlin 版本 class TreeNode(var value: String, var leftNode: TreeNode? null, var rightNode: TreeNode? null)Java 版本 class TreeNode(){public…

经典排序之插入排序

目录 直接插入排序&#xff1a; 基本思路 图解过程 代码 复杂度分析 希尔排序 基本思想 图解过程 代码 复杂度分析 总结 参赛话题&#xff1a;学习笔记 直接插入排序&#xff1a; 基本思路 直接插入排序的工作方式像许多人排序一手扑克牌。开始时&#xff0c;我们的左手…

【Netty 从成神到升仙系列 大结局】全网一图流死磕解析 Netty 源码

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小黄&#xff0c;独角兽企业的Java开发工程师&#xff0c;Java领域新星创作者。&#x1f4dd;个人公众号&#xff1a;爱敲代码的小黄&#x1f4d5;系列专栏&#xff1a;Java设计模式、数据结构和算法&#x…

第八篇 python 面向对象编程

11 面向对象编程 面向对象编程——Object Oriented Programming&#xff0c;简称OOP&#xff0c;是一种程序设计思想。OOP把对象作为程序的基本单元&#xff0c;一个对象包含了数据和操作数据的函数。 面向过程的程序设计把计算机程序视为一系列的命令集合&#xff0c;即一组…

Python攻防-APK批量化Pull与自动化反编译

文章目录前言Pull APK根据包名列表根据手机路径逆向APK自动化反编译findstr检索…总结前言 日常工作过程中&#xff0c;经常会遇到发现新的攻击模式的情况下&#xff0c;需要全量排查手机上所有 APP 的代码是否存在该类代码缺陷。对于复杂的攻击模式而言&#xff0c;往往需要动…

【MyBatis框架】动态SQL

MyBatis之动态SQL 目录MyBatis之动态SQL1. < if > 元素2. < where >3. < choose >,< when >,< otherwise >元素4. < trim >元素5. < set >元素6. < foreach >元素6.1 添加批量数据6.2 批量删除数据7. < SQL >元素8. 小结…

LVS负载均衡群集

企业群集应用 1. 群集的含义 1.1Cluster&#xff0c;群集&#xff0c;集群 2.1由多台主机构成&#xff0c;但对外&#xff0c;只表现为一个整体&#xff0c;只提供一个访问入口&#xff08;域名或ip地址&#xff09;&#xff0c; 相当于一台大型计算机 2.问题出现 互联网…

Sentinel的学习

1、Sentinel控制台的下载 下载地址&#xff1a;https://github.com/alibaba/Sentinel/releases/tag/1.8.3 2、Sentinel控制台的启动 java -jar sentinel-dashboard-1.8.3.jar3、访问 浏览器输入&#xff1a;localhost:8080 账号密码&#xff1a; sentinel/sentinel 4.sprin…

SARScape中用sentinel-1数据做SBAS-InSAR完整流程(1/2)

SARScape中用sentinel-1数据做SBAS-InSAR完整流程1 SABA-InSAR原理简述2 数据采集和预设2.1 SAR数据采集2.2 DEM数据下载与放置2.3 精密轨道数据下载与放置2.4 制作研究区范围矢量2.5 SARscape Preferences预设3 SAR数据预处理3.1 导入数据3.2 optional files设置3.3 参数设置4…