Att*_*lio 7 java spring dependency-injection
是否可以在 spring 中自动装配没有给定限定符的 bean?用例是拥有所有 bean 的列表,但排除一个:
@Autowired
@NotQualifier("excludedBean")    // <-- can we do something like this?
List<SomeBean> someBeanList;
public class Bean1 implements SomeBean {}
public class Bean2 implements SomeBean {}
@Qualifier("excludedBean")
public class Bean3 implements SomeBean {}
在上面的例子中someList应该包含一个Bean1andBean2但不是的实例Bean3。
(备注:我知道相反的方法会起作用,即向Bean1and添加一些限定符Bean2,然后使用该限定符自动装配。)
编辑:一些进一步的说明:
List<SomeBean> someBeanList;,但我想在其他地方自动装配它。您可以使用元注释来引入您自己的@Conditional注释@Qualifier
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
@Conditional(MyCondition.class)
public @interface ExcludeBean {
然后引入可以执行条件逻辑的类
public class MyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return !metadata.equals(ExcludeBean.class);
    }
}
在您的配置类中
  @Bean
  @ExcludeBean
  public BeanA beanA() {
      return new BeanA();
  }
autowire-candidate您还可以通过对特定 bean进行设置或指定来将 bean 排除在自动装配候选对象之外default-autowire-candidates="list of candidates here"  
要点是它的排除 bean 是在上下文中,但没有注入到某些具有排除条件的情况中。
您可以使用自定义注释和 BeanPostProcessor 来排除带有限定符的 bean。(我做了简单案例的示例,用于 bean 类型的集合,但您可以扩展它)
排除的注释:
@Component
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcludeBeanByQualifierForCollectionAutowired {
    String qualifierToExcludeValue();
    Class<?> aClass();
}
带注入的 Bean 后处理器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
@Component
public class ExcludeAutowiredBeanPostProcessor implements BeanPostProcessor {
    @Autowired
    private ConfigurableListableBeanFactory configurableBeanFactory;
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        Field[] fields = bean.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            ExcludeBeanByQualifierForCollectionAutowired myAutowiredExcludeAnnotation = field.getAnnotation(ExcludeBeanByQualifierForCollectionAutowired.class);
            if (myAutowiredExcludeAnnotation != null) {
                Collection<Object> beanForInjection = new ArrayList<>();
                String[] beanNamesOfType = configurableBeanFactory.getBeanNamesForType(myAutowiredExcludeAnnotation.aClass());
                for (String injectedCandidateBeanName : beanNamesOfType) {
                    Object beanCandidate = configurableBeanFactory.getBean(injectedCandidateBeanName);
                    Qualifier qualifierForBeanCandidate = beanCandidate.getClass().getDeclaredAnnotation(Qualifier.class);
                    if (qualifierForBeanCandidate == null || !qualifierForBeanCandidate.value().equals(myAutowiredExcludeAnnotation.qualifierToExcludeValue())) {
                        beanForInjection.add(beanCandidate);
                    }
                }
                try {
                    field.set(bean, beanForInjection);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }
}
和例子:
public class ParentBean {}
public class Bean1Included extends ParentBean {}
public class Bean2Included extends ParentBean {}
public class Bean3Included extends ParentBean {}
@Qualifier("excludedBean")
public class BeanExcluded extends ParentBean {}
配置
@Configuration
public class BeanConfiguration {
    @Bean
    public Bean1Included getBean1(){
        return new Bean1Included();
    }
    @Bean
    public Bean2Included getBean2(){
        return new Bean2Included();
    }
    @Bean
    public Bean3Included getBean3(){
        return new Bean3Included();
    }
    @Bean
    public BeanExcluded getExcludedBean(){
        return new BeanExcluded();
    }
    @Bean
    public ExcludeAutowiredBeanPostProcessor excludeAutowiredBeanPostProcessor(){
        return new ExcludeAutowiredBeanPostProcessor();
    }
}
和结果:
@ExtendWith(SpringExtension.class) // assumes Junit 5
@ContextConfiguration(classes = BeanConfiguration.class)
public class ExcludeConditionTest {
    @Autowired
    private ApplicationContext context;
    @Autowired
    private BeanExcluded beanExcluded;
    @ExcludeBeanByQualifierForCollectionAutowired(qualifierToExcludeValue = "excludedBean" , aClass = ParentBean.class)
    private List<ParentBean> beensWithoutExclude;
    @Test
    void should_not_inject_excluded_bean() {
        assertThat(context.getBeansOfType(ParentBean.class).values())
                .hasOnlyElementsOfTypes(Bean1Included.class,
                                        Bean2Included.class,
                                        Bean3Included.class,
                                        BeanExcluded.class);
        assertThat(beansWithoutExclude)
                .hasOnlyElementsOfTypes(Bean1Included.class,
                                        Bean2Included.class,
                                        Bean3Included.class)
                .doesNotHaveAnyElementsOfTypes(BeanExcluded.class);
        assertThat(beanExcluded).isNotNull();
    }
}
| 归档时间: | 
 | 
| 查看次数: | 4000 次 | 
| 最近记录: |