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
相关产品推荐
相关产品推荐

