@AutoConfigurationPackage注解详解
创始人
2024-01-16 03:52:05

@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 {@Overridepublic String toString() {return super.toString() + "--我是TestBean4";}
}

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

public class ImportBeanByImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic 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 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 {@Overridepublic 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 {
}

上一篇:Mastura的薪酬体系

下一篇:生活中的小事

相关内容

热门资讯

苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
阿西吧是什么意思 阿西吧相当于... 即使你没有受到过任何外语培训,你也懂四国语言。汉语:你好英语:Shit韩语:阿西吧(아,씨발! )日...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
阿西吧是什么意思 阿西吧相当于... 即使你没有受到过任何外语培训,你也懂四国语言。汉语:你好英语:Shit韩语:阿西吧(아,씨발! )日...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...