@AutoConfigurationPackage注解详解

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

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

一、观察@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 {
}
  • 7
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
@AutoConfigurationPackage的作用是启用自动配置包。它是Spring Boot中的一个注解,用于指定扫描自动配置类的基础包。通过在@Configuration类上添加@AutoConfigurationPackage注解,并指定basePackageClasses属性为需要扫描的基础包类,可以方便地扫描并加载自动配置类。这样,在启动Spring Boot应用程序时,自动配置类将被自动加载并应用。 @AutoConfigurationPackage注解通常与@EnableAutoConfiguration和@SpringBootApplication注解一起使用。@EnableAutoConfiguration注解用于启用自动配置,@SpringBootApplication注解包含了@EnableAutoConfiguration注解。因此,通过在@SpringBootApplication注解所在的类上添加@AutoConfigurationPackage注解,可以确保自动配置包的扫描和加载。 例如,可以在@Configuration注解所标注的配置类上添加@AutoConfigurationPackage注解,并通过basePackageClasses属性指定需要扫描的基础包类。这样,在启动应用程序时,Spring Boot将自动扫描并加载该配置类中的自动配置包。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [@AutoConfigurationPackage自动包规则原理](https://blog.csdn.net/hanlin_zhao/article/details/126076297)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [@AutoConfigurationPackage注解详解](https://blog.csdn.net/weixin_43888891/article/details/127478734)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怪 咖@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值