4

通常,合格的组件将被注入具有相同限定符的注释字段:

@Component        class Apple1 implements IApple {}
@Component @Black class Apple2 implements IApple {}

class User {
    @Inject        IApple apple;        // -> Apple1
    @Inject @Black IApple blackApple;   // -> Apple2
    @Inject @Red   IApple redApple;     // -> Error: not defined
}

我想要的是,如果没有定义具有特定限定符的组件,我想给一个默认的,所以redApple上面的例子中将注入一个Apple1.

可能吗?或者我可以为 Spring DI 实施特定的限定符匹配策略吗?

** 编辑 **

我知道子类会起作用,但这是一个描述问题的例子,所以子类在这里不适用。

4

1 回答 1

4

如果你尝试注入一些不存在 bean 的符合条件的东西, @Inject @Red IApple redApple;那么你会得到一个:NoSuchBeanDefinitionException

无论您是否使用,都会发生此异常:

  • @注入
  • @资源
  • @Autowire

原因很简单:Spring DI 首先搜索确定所有自动装配候选者。

  • 如果正好有一个,它使用这个候选人
  • 如果没有候选人,它会引发 NoSuchBeanDefinitionException
  • 如果有多个,它会尝试从候选中确定初级候选。

@参见 org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency

第 785..809 行(3.0.4.RELEASE)

因此,您需要做的是将后备(Apple)之一放入候选集,但请确保仅在没有其他候选者时使用它。因为没有办法将 bean 标记为 fall back 或 less importend,所以您需要将普通 bean 标记为更重要@primary

所以(证明的)解决方案将是注释

  • 带有@Black 和@Red 以及@Primary 的黑色和红色苹果。
  • 默认后备 Apple (Apple1),带有 @Red 和 @Black,但没有 @Primary。

例子:

@Component @Red @Black public class Apple1 implements IApple {} //fall back
@Component @Black @Primary public class Apple2 implements IApple {}

@Component public class AppleEater {
  @Inject @Black IApple blackApple; // -> Apple2
  @Inject @Red IApple redApple; // -> Apple1
}

可能的改进:如果您不喜欢将所有注释(@Black、@Red、@AllOtherStangeColors)添加到您的后备 bean,您可以尝试实现您自己的AutowireCandiateResolver,以便将后备 bean 添加到所有候选列表所需类型(Apple) @see 参考文档:3.9.4 CustomAutowireConfigurer

于 2011-03-16T12:39:21.657 回答