猿问

如何在 Spring 中使用自动装配的 bean 创建简单工厂模式?

我有一个控制器,它有 4 个非常相似的方法,调用远程服务器上的 API 来对不同类型的用户执行不同的操作。这些 API 调用之间的变化只是端点和一些参数。


因此,这 4 个方法都以非常相似的代码调用服务:它们从服务器获取令牌、设置参数、返回 API 的响应。由于稍后将添加更多操作,因此我决定使用使用工厂方法模式创建 ServiceFactory 并在服务上使用模板模式以避免代码重复。


我的问题是,为了让工厂自动装配服务,它需要与它们耦合,我必须对@Autowire每个实现进行。有更好的解决方案吗?


这是我到目前为止的代码:


休息控制器

@RestController

public class ActionController {

  @Autowired

  private SsoService ssoService;


  // this is the factory

  @Autowired

  private ServiceFactory factory;


  @PostMapping("/action")

  public MyResponse performAction(@RequestBody MyRequest request, HttpServletRequest req) {

    // template code (error treatment not included)

    request.setOperator(ssoService.getOperator(req));

    request.setDate(LocalDateTime.now());

    return serviceFactory.getService(request).do();

  }

}

服务工厂

@Component

public class ServiceFactory {


  @Autowired private ActivateUserService activateUserService;

  @Autowired private Action2UserType2Service anotherService;

  //etc


  public MyService getService(request) {

    if (Action.ACTIVATE.equals(request.getAction()) && UserType.USER.equals(request.getUserType()) {

      return activateUserService;

    }

    // etc

    return anotherService;

  }

}

Service Base,实现MyService接口

public abstract class ServiceBase implements MyService {


  @Autowired private ApiService apiService;

  @Autowired private ActionRepository actionRepository;

  @Value("${api.path}") private String path;


  @Override

  public MyResponse do(MyRequest request) {

    String url = path + getEndpoint();

    String token = apiService.getToken();


    Map<String, String> params = getParams(request);

    // adds the common params to the hashmap


    HttpResult result = apiService.post(url, params); 

    if (result.getStatusCode() == 200) {

      // saves the performed action

      actionRepository.save(getAction());

    }

    // extracts the response from the HttpResult

    return response;

  }

}


米琪卡哇伊
浏览 155回答 1
1回答

慕哥9229398

您可以@Autowireda Listof MyService,这将创建一个List实现该MyService接口的所有 bean。然后您可以添加一个方法来MyService接受一个MyRequest对象并决定它是否可以处理该请求。List然后,您可以过滤MyService以找到MyService可以处理请求的第一个对象。例如:public interface MyService {&nbsp; &nbsp; public boolean canHandle(MyRequest request);&nbsp; &nbsp; // ...existing methods...}@Servicepublic class ActivateUserService extends ServiceBase {&nbsp; &nbsp; @Override&nbsp; &nbsp; public boolean canHandle(MyRequest request) {&nbsp; &nbsp; &nbsp; &nbsp; return Action.ACTIVATE.equals(request.getAction()) && UserType.USER.equals(request.getUserType());&nbsp; &nbsp; }&nbsp; &nbsp; // ...existing methods...}@Componentpublic class ServiceFactory {&nbsp; &nbsp; @Autowired&nbsp; &nbsp; private List<MyService> myServices;&nbsp; &nbsp; public Optional<MyService> getService(MyRequest request) {&nbsp; &nbsp; &nbsp; &nbsp; return myServices.stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(service -> service.canHandle(request))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .findFirst();&nbsp; &nbsp; }}请注意,ServiceFactory上面的实现使用 Java 8+。如果 Java 8 或更高版本无法实现,则可以ServiceFactory通过以下方式实现该类:@Componentpublic class ServiceFactory {&nbsp; &nbsp; @Autowired&nbsp; &nbsp; private List<MyService> myServices;&nbsp; &nbsp; public Optional<MyService> getService(MyRequest request) {&nbsp; &nbsp; &nbsp; &nbsp; for (MyService service: myServices) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (service.canHandle(request)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return Optional.of(service);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return Optional.empty();}有关使用@Autowiredwith的更多信息List,请参阅Autowire 将 bean 引用到按类型列表中。该解决方案的核心是将决定MyService实现是否可以处理MyRequest来自ServiceFactory(外部客户端)的逻辑转移到MyService实现本身。
随时随地看视频慕课网APP

相关分类

Java
我要回答