Spring Boot 如何在Sping Boot 中动态排序具有默认值的接口的实现列表?

wgmfuz8q  于 2023-06-22  发布在  Spring
关注(0)|答案(3)|浏览(154)

我有一个扩展java.util.function.Function的接口,有2个接口的进一步实现,比如说A类,B类实现了Base接口;

interface Base extends Function<Object, Object> {

  @Override
  default Object apply(Object object) {
    return object;     // simply do nothing
  }

  default boolean accept(String str) {
    return true;     // for choosing the right instance
  }
}
@Service
class A implements Base {

  String validationString = "some-random-string";

  @Override
  public Object apply(Object object) {
    // update the object ....
    return object;
  }

  @Override
  public boolean accept(String str) {
    return str.equals(validationString);
  }
}
@Service
class B implements Base {

  String validationString = "some-random-string-2";

  @Override
  public Object apply(Object object) {
    // update the object ....
    return object;
  }

  @Override
  public boolean accept(String str) {
    return str.equals(validationString);
  }
}
@Service
@RequiredArgsConstructor
class SomeService {

  List<Base> baseList;

  public void callingClass(String str) {

    // in below 
    // I want to order it in such a way that 
    // if str matches A.validationString then give back A's instance
    // else if str matches B.validationString then give back B's instance
    // else return Base's instance
    Base base = baseList.stream()
        .filter(baseImpl -> baseImpl.accept(str))
        .findFirst().orElseThrow();

  }
}

所以,我试图实现的是,如果有任何方法,我不需要手动创建一个工厂类(工厂模式)和动态过滤示例A,B使用accept(),如果没有找到,然后返回Base示例(默认)。
有人能帮忙吗?

carvr3hs

carvr3hs1#

结合@k314159和@atish.s解决方案并改进:
将DefaultBase类公开为另一个bean,但添加@Order注解以将其放在列表的最后

@Component
@Order(Precedence.LAST)
class DefaultBase implements Base {
    default accepts(Object obj){
        return true;
    }
}

然后将Service方法更改为:

public Base callingClass(String str) { 
    return baseList.stream()
        .filter(baseImpl -> baseImpl.accept(str))
        .findFirst()
        .orElseThrow();
}
juud5qan

juud5qan2#

您可以通过提供Base的默认实现来实现这一点;

// no need to annotate it with @service
class DefaultBase implements Base {

}

然后在你的工厂方法中,

private static final Base DEFAULT_BASE = new DefaultBase();

public void callingClass(String str) {
  Base base = baseList.stream()
      .filter(baseImpl -> baseImpl.accept(str))
      .findFirst()
      .orElseGet(DEFAULT_BASE);
}
ercv8c1e

ercv8c1e3#

通过自动装配获取实现接口的服务类列表。
然后,创建一个默认示例(它可以是一个匿名类,也可以是atish的答案中的命名类)。它不能是Spring服务,因为您不希望它包含在您的autowired列表中。在方法中,如果未找到服务类,则返回此默认示例。

@Service
@RequiredArgsConstructor
class SomeService {
  private static final Base DEFAULT_BASE = new Base() {};

  @Autowired
  private List<Base> baseList;

  public void callingClass(String str) {

    Base base = baseList.stream()
        .filter(baseImpl -> baseImpl.accept(str))
        .findFirst()
        .orElse(DEFAULT_BASE);

  }
}

相关问题