Spring Boot自动装配(三)

本文深入探讨了Spring Boot的自动装配机制,重点关注条件化自动装配的实现,包括Class条件注解如@ConditionalOnClass和@ConditionalOnMissingClass,以及Bean条件注解如@ConditionalOnBean和@ConditionalOnMissingBean。文章详细阐述了这些注解的工作原理,如OnClassCondition和OnBeanCondition,并解析了如何根据BeanDefinition进行匹配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring Boot自动装配(三)

​ 在EnableAutoConfiguration类中,还存在一个注解AutoConfigurationPackage

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
//将标注类所在的package添加至BasePacks中,为后续扫描组件提供来源。
public @interface AutoConfigurationPackage {
   
	
}

​ 同样的套路,我们去分析AutoConfigurationPackages.Registrar.class

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
   

   @Override
   public void registerBeanDefinitions(AnnotationMetadata metadata,
         BeanDefinitionRegistry registry) {
   
      register(registry, new PackageImport(metadata).getPackageName());
   }

   @Override
   public Set<Object> determineImports(AnnotationMetadata metadata) {
   
      return Collections.singleton(new PackageImport(metadata));
   }

}
public static void register(BeanDefinitionRegistry registry, String... packageNames) {
   
  //判断org.springframework.boot.autoconfigure.AutoConfigurationPackages是否已经被注册过。
  //Bean是一个常量为AutoConfigurationPackages.class.getName();
  //这里是考虑到,@EnableAutoConfiguration被标注在多个类上,这样,Registrar就会被多次@Import。
  if (registry.containsBeanDefinition(BEAN)) {
   
   	  //直接从容器中拿到bean
      BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);
     //获取constructorArgumentValues,并添加包路径。
      ConstructorArgumentValues constructorArguments = beanDefinition
            .getConstructorArgumentValues();
      constructorArguments.addIndexedArgumentValue(0,
            addBasePackages(constructorArguments, packageNames));
   }
   else {
   
     //初始化beanDefinition,实例为BasePackages
      GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
      beanDefinition.setBeanClass(BasePackages.class);
     //获取constructorArgumentValues,并添加包路径。
      beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0,
            packageNames);
      beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
     //将初始化的beanDefinition注册到Spring容器中。
      registry.registerBeanDefinition(BEAN, beanDefinition注册到Spring容器中。);
   }
}

​ 在初始化beanDefinition中,beanDefinition.setBeanClass(BasePackages.class);

static final class BasePackages {
   

   private final List<String> packages;

   private boolean loggedBasePackageInfo;
   BasePackages(String... names) {
   
      List<String> packages = new ArrayList<>();
      for (String name : names) {
   
         if (StringUtils.hasText(name)) {
   
            packages.add(name);
         }
      }
      this.packages = packages;
   }

   public List<String> get() {
   
      if (!this.loggedBasePackageInfo) {
   
         if (this.packages.isEmpty()) {
   
            if (logger.isWarnEnabled()) {
   
               logger.warn("@EnableAutoConfiguration was declared on a class "
                     + "in the default package. Automatic @Repository and "
                     + "@Entity scanning is not enabled.");
            }
         }
         else {
   
            if (logger.isDebugEnabled()) {
   
               String packageNames = StringUtils
                     .collectionToCommaDelimitedString(this.packages);
               logger.debug("@EnableAutoConfiguration was declared on a class "
                     + "in the package '" + packageNames
                     + "'. Automatic @Repository and @Entity scanning is "
                     + "enabled.");
            }
         }
         this.loggedBasePackageInfo = true;
      }
      return this.packages;
   }

}

​ 首次构造时,将当前标注类所在的package作为参数传入,后续更改时,获取ConstructArgumentValues,追加其中。后续可以根据get()方法直接获取packages。

​ 应用实例:AutoConfigurationPackages#get()

public static List<String> get(BeanFactory beanFactory) {
   
   try {
   
      return beanFactory.getBean(BEAN, BasePackages.class).get(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值