You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring 6中如何通过功能性BeanDefinitions注入带Qualifier的属性值?

在Spring 6中通过BeanDefinition注册实现带Qualifier的集合注入

问题场景

我在Spring 6项目里定义了一批带@Qualifier注解的Foo类型Bean:

// 带有“A”限定符的Foo实例
@Bean @Qualifier("A") Foo adventure () { return new Foo("Adventure"); }
@Bean @Qualifier("A") Foo afternoon () { return new Foo("Afternoon"); }
@Bean @Qualifier("A") Foo air       () { return new Foo("Air");       }
@Bean @Qualifier("A") Foo animal    () { return new Foo("Animal");    }
@Bean @Qualifier("A") Foo apple     () { return new Foo("Apple");     }
@Bean @Qualifier("A") Foo award     () { return new Foo("Award");     }

// 带有“B”限定符的Foo实例
@Bean @Qualifier("B") Foo basket  () { return new Foo("Basket");  }
@Bean @Qualifier("B") Foo bee     () { return new Foo("Bee");     }
@Bean @Qualifier("B") Foo blanket () { return new Foo("Blanket"); }
@Bean @Qualifier("B") Foo bicycle () { return new Foo("Bicycle"); }
@Bean @Qualifier("B") Foo bucket  () { return new Foo("Bucket");  }
@Bean @Qualifier("B") Foo button  () { return new Foo("Button");  }

通过注解可以轻松注入指定Qualifier的Foo集合:

@Autowired
public void setFoos(@Qualifier("A") final List<Foo> foos) { 
   this.foos = foos;
}

但在通过功能性方式注册BeanDefinition时,找不到直接对应上述注解注入的API(比如设想的QualifiedRuntimeBeanReference并不存在),需要实现相同的注入效果。

解决方案

Spring 6没有直接提供封装好的QualifiedRuntimeBeanReference,但可以通过手动创建DependencyDescriptor并附加Qualifier注解的方式,让Spring自动解析并注入符合条件的Bean集合:

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionBuilder;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.core.MethodParameter;

import java.lang.reflect.Method;
import java.util.List;

public void registerBar(final BeanDefinitionRegistry registry) throws NoSuchMethodException {
    // 创建Bar的BeanDefinition并设置基础属性
    BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Bar.class)
            .addPropertyValue("id", "bar_0001")
            .getBeanDefinition();

    // 移除直接属性赋值,改用依赖注入方式处理foos属性
    beanDefinition.getPropertyValues().remove("foos");

    // 对应Bar类中setFoos方法的参数描述
    Method setFoosMethod = Bar.class.getMethod("setFoos", List.class);
    MethodParameter methodParameter = new MethodParameter(setFoosMethod, 0);

    // 创建带Qualifier的DependencyDescriptor
    DependencyDescriptor descriptor = new DependencyDescriptor(methodParameter, true) {
        @Override
        public Annotation[] getAnnotations() {
            // 动态生成@Qualifier("A")注解
            return new Annotation[]{
                    new Qualifier() {
                        @Override
                        public String value() {
                            return "A";
                        }

                        @Override
                        public Class<? extends Annotation> annotationType() {
                            return Qualifier.class;
                        }
                    }
            };
        }
    };

    // 将DependencyDescriptor作为属性值添加,Spring会自动解析依赖并注入符合条件的Foo集合
    beanDefinition.getPropertyValues().add("foos", descriptor);

    registry.registerBeanDefinition("bar", beanDefinition);
}

原理说明

Spring的依赖注入处理器(如AutowiredAnnotationBeanPostProcessor)在处理属性注入时,若检测到属性值为DependencyDescriptor类型,会根据该描述符的元数据(包括附加的Qualifier注解)去容器中查找匹配的Bean,最终自动注入符合条件的List<Foo>集合,效果与注解方式完全一致。

内容的提问来源于stack exchange,提问作者sawprogramming

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 14:47:52