Java 如何在运行时动态更改依赖关系

Java 如何在运行时动态更改依赖关系,java,spring,Java,Spring,我是一名spring开发人员 在开发过程中,需要动态更改依赖关系 如果模块B出现故障,则调用模块A 由于A和B模块是调用不同API的类似API,我创建了一个带有接口的抽象,并将其注入到使用其依赖项的地方 接口和实现如下所示 public interface BookService {     <T> Optional <ResponseEntity <T >> findBookListByQuery (BookSearchRequestUriVariables

我是一名spring开发人员

在开发过程中,需要动态更改依赖关系

如果模块B出现故障,则调用模块A

由于A和B模块是调用不同API的类似API,我创建了一个带有接口的抽象,并将其注入到使用其依赖项的地方

接口和实现如下所示

public interface BookService {
    <T> Optional <ResponseEntity <T >> findBookListByQuery (BookSearchRequestUriVariables variables, Class <T> clazz);
}
公共接口图书服务{
可选findBookListByQuery(BookSearchRequestUriVariables变量,类clazz);
}
@Slf4j
@服务
@初级的
公共类KakaoBookService实现BookService{
@覆盖
公共可选findBookListByQuery(BookSearchRequestUriVariables变量,类clazz){
试一试{
ResponseEntity exchange=restemplate.exchange(kakaoProperties.getBookSearchURL(),
HttpMethod.GET,
新的HttpEntity(httpHeaders),
克拉兹,
variables.getUriVariables());
返回可选。不可用(交换);
}catch(异常e){
log.info(“findBookListByQuery异常:{}”,e.getMessage());
返回Optional.empty();
        }
    }
}
@服务
公共类NaverBookService实现BookService{
@凌驾
公共可选findBookListByQuery(BookSearchRequestUriVariables变量,类clazz){
ChangeKakao变量平均变量(变量);
返回Optional.of(restemplate.exchange(url,HttpMethod.GET,新的HttpEntity(httpHeaders),clazz,variables.getUriVariables());
    }
private BookSearchRequestUriVariables ChangeKaKaoVariablesToAverVariables(BookSearchRequestUriVariables变量){
Map uriVariables=variables.getUriVariables();
uriVariables.put(“page”,String.valueOf((Integer.parseInt(variables.getUriVariables().get(“page”)*10)+1));
String sort=variables.getUriVariables().Get(“sort”);
如果(sort.equals(“精度”))sort=“sim”;
否则,如果(sort.equals(“latest”))sort=“date”;
uriVariables.put(“sort”,sort);
返回变量;
    }
}
实际使用地点如下所示。首先要做的是调用kakao API。如果出现错误,请调用Naver API

public BookSearchKakaoResponse findBookListByQuery (BookSearchRequestUriVariables variables) {

        saveToBookHistory (getJwtMember (). getMemberName (), variables.getUriVariables (). get ("query"));
        Optional <ResponseEntity <BookSearchKakaoResponse >> bookListByKakao = kakaoBookService.findBookListByQuery (variables, BookSearchKakaoResponse.class);

        if (! bookListByKakao.isPresent ()) {// call NAVER API
            return naverBookService.findBookListByQuery (...);
        }
        return bookListByKakao.get (). getBody ();
    }
public booksearchkakao响应findBookListByQuery(BookSearchRequestUriVariables){
saveToBookHistory(getJwtMember().getMemberName(),variables.getUriVariables().get(“查询”);
可选bookListByKakao=kakaoBookService.findBookListByQuery(变量,BookSearchKakaoResponse.class);
如果(!bookListByKakao.isPresent()){//调用NAVER API
返回naverBookService.findBookListByQuery(…);
        }
返回bookListByKakao.get().getBody();
    }
我有
kakaoBookService
,我想把
naverBookService
bookService
结合起来

如果调用kakao API的模块失败,我想将调用naver API的模块注入bookService

请告诉我该怎么办

我认为根据依赖倒置原则和开闭原则将它们结合起来是个好主意

请让我知道我考虑的方向是否是代码设计问题


谢谢。

您可以使用@Qualifier annotation来实现同样的效果。当bean提供给您时,容器将自动连接所有依赖项。您可以根据用例使用正确的服务

@Slf4j
@Service
@Primary
@Qualifier("kakao")
public class KakaoBookService implements BookService {}


@Service
@Qualifier("naver")
public class NaverBookService implements BookService {}
现在,将两个bean自动关联到使用它的服务

@Autowired @Qualifier("kakao")
    BookService kakaoBookService;

@Autowired @Qualifier("naver")
    BookService naverBookService;

虽然有可能在条件允许的情况下从应用程序上下文动态获取bookService bean,但自动关联依赖项是一种更干净的方法。

如果kakao API失败,如果我正确理解需求,您需要调用naver API。如果这是错误的,请更正。为什么要将其注入bookService?您可以通过限定符注释来实现这一点,注入两个服务bean,并在第一个失败时调用另一个
@Slf4j
@Service
@Primary
@Qualifier("kakao")
public class KakaoBookService implements BookService {}


@Service
@Qualifier("naver")
public class NaverBookService implements BookService {}
@Autowired @Qualifier("kakao")
    BookService kakaoBookService;

@Autowired @Qualifier("naver")
    BookService naverBookService;