【问题标题】:Spring autowire the only implementation without defining the beanSpring自动装配唯一的实现而不定义bean
【发布时间】:2020-05-26 10:49:42
【问题描述】:

我有以下情况:

@Service
interface OrderingService {

}

public class DefaultOrderingService implements OrderingService {

}

@RestController
public class DefaultOrderingRestController {
    private final OrderingService orderingService;
    public DefaultOrderingRestController(OrderingService orderingService) {
        this.orderingService = orderingService;
    }
}

我希望 Spring 通过扫描代码自动连接接口的唯一实现。这可能吗?

换句话说,目前这个问题有两种解决方案,我想问是否还有第三种:

  1. @Service 声明从接口OrderingService 移动到实现DefaultOrderingService
  2. 在Configuration中,定义具体的Bean如下:
 @Configuration 
 public class DefaultConfig {
      @Bean
      public OrderingService orderingService() {
          return new DefaultOrderingService();
      }
 }

问题:是否可以让 Spring 自动扫描(然后 Spring 仅找到 OrderingService 的一种实现)和自动装配?如果是,该怎么做? 如果不是,这不是一个好习惯吗?为什么?

【问题讨论】:

  • @Service 注释放在接口上是错误的,它属于实现(您的解决方案#1)。解决方案 #2 也可以。为什么需要第三种解决方案?只需选择 #1 或 #2 即可。如果没有定义为 Spring bean(通过 @Service@Component 注释或 Spring 配置中的其他方式),则无法让 Spring 自动获取实现。
  • 您可以进行自己的组件扫描,如果您发现接口只有一个实现,请将其注册到应用程序上下文中
  • @Autowired 这样做,对吗?我的意思是,如果只有一个实现,Spring autowires 它。只有当有多个实现时,Springs 才会抛出歧义错误。而且,这就是@Qualifier 出现的时候。那么,你为什么不选择@Autowired
  • @RoyalBg 有趣的建议
  • 不,如果只有一个实例,弹簧自动装配。你可以有任何实现,但在运行时只有一个实例,或者你必须使用 Primary annotation 的 Qualifier。

标签: java spring


【解决方案1】:

我不知道这是否可行,但我有一个不同的方法可能会有所帮助:

添加配置文件来保存你的bean的类型,假设OrderingService有两个实现一个是FAKEDEFAULT为了只有一个在运行时,你必须在项目中声明这两个bean上下文如下:

@Bean
OrderingService fakeOrderingService() {
  return new FakeOrderingService();
}

@Bean
OrderingService defaultOrderingService() {
  return new DefaultOrderingService();
}

如果你想要其中之一,你必须添加 ConditionalOnProperty,如下所示:

@Bean
@ConditionalOnProperty("app.config.type", havingValue = "FAKE")
OrderingService fakeOrderingService()..

@Bean
@ConditionalOnProperty("app.config.type", havingValue = "DEFAULT", matchIfMissing = true)
OrderingService defaultOrderingService()...

matchIfMissing = true 这将有所帮助,如果配置未添加到您的环境中,因此如果属性缺失或属性值为 DEFAULT,spring 将自动装配 defaultOrderingService,如果属性值为 @987654330,则 fakeOrderingService @

希望对你有帮助

【讨论】:

    【解决方案2】:

    您的第三个解决方案的问题在于它依赖于接口的实现。如果没有找到对应的实现,spring 会报错。所以我想这绝对不是一个好习惯。 spring @service 注释也不会被继承。 但是,如果您仍然想要任何替代解决方案。您可能更愿意为每个实现定义单独的 bean,并使用限定符从应用程序上下文中获取 bean。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多