【问题标题】:Strategy Pattern two usages of @Service duplicate component name策略模式@Service 重复组件名的两种用法
【发布时间】:2020-09-19 21:56:27
【问题描述】:

在 Spring Boot 的帮助下实现了一个非常简单的策略模式:

我有一个界面:

public interface IOneStrategy {
  void executeTheThing();
}

我有一个这样的策略 One 的实现:

@Service("FIRST")
public class OneStrategyFirst implements IOneStrategy {

  @Override
  public void executeTheThing() {
    System.out.println("OneStrategyFirst.executeTheThing");
  }
}

我有一个使用注入实现的类:

@Service
public class ExecuteStrategyOne {
  private Map<String, IOneStrategy> strategies;

  public void executeStrategyOne(String name) {
    if (!strategies.containsKey(name)) {
      throw new IllegalArgumentException("The key " + name + " does not exist.");
    }
    strategies.get(name).executeTheThing();
  }

   
}

这些实现将由 Spring boot 通过使用名称 FIRST、'SECOND' 等自动注入(假设这只是一个 String 等,效果很好。)。

但现在我想通过第二个接口实现另一个策略:

public interface ITwoStrategy {
  void executeTheThing();
}

以及策略的执行服务:

@Service
public class ExecuteStrategyTwo {
  private Map<String, ITwoStrategy> strategies;
  ...
   
}

现在是有问题的部分,因为我的应用程序使用了相同的名称,它应该成为上述地图的键的一部分,我想使用以下内容:

@Service("FIRST")
public class TwoStrategyFirst implements ITwoStrategy {

  @Override
  public void executeTheThing() {
    System.out.println("TwoStrategyFirst.executeTheThing");
  }
}

这当然会导致基于重复 bean 名称的异常。确实需要名称 FIRST 来区分实现。

我已经找到了关于 @Qualifier 的东西,我可以用它来代替 @Service(FIRST)

@Service
@Qualifier(FIRST)
public class TwoStrategyFirst implements ITwoStrategy {

  @Override
  public void executeTheThing() {
    System.out.println("TwoStrategyFirst.executeTheThing");
  }
}

不幸的是,它并没有通过使用限定符的名称将类注入到映射中,这不是我打算做的。

是否存在与@Service("FIRST")相同的策略执行中获取地图键的解决方案?

【问题讨论】:

    标签: java spring-boot spring-framework-beans


    【解决方案1】:

    我可以通过使用限定符注释来使用解决方案,如下所示:

    @Service
    @Qualifier(FIRST)
    public class TwoStrategyFirst implements ITwoStrategy {
    ...
    }
    

    基于此,通过一些代码或多或少有一个简单的解决方案:

    @Service
    public class ExecuteStrategyTwo {
    
    
      private Map<String, ITwoStrategy> strategies;
    
      public ExecuteStrategyOne(List<ITwoStrategy> strategies) {
        this.strategies = strategies.stream()
            .collect(
                Collectors.toMap(k -> k.getClass().getDeclaredAnnotation(Qualifier.class).value(), Function.identity()));
      }
    

    这会将所有实现注入到构造函数的列表中,并通过使用限定符注解转换为映射。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-05
      相关资源
      最近更新 更多