首页 > 解决方案 > 春天框架。根据请求参数在运行时注入bean

问题描述

假设我们有一个 FileLoader 接口:

public interface FileLoader {

  default String loadFile(String fileId) {
    // Default business logic
    return "Default implementation for FileLoader. Loading file" + fileId;
  }
}

以及针对不同国家/地区的不同实现:

public class USAFileLoader implements FileLoader {

  @Override
  public String loadFile(String fileId) {
    // ... Specific business logic for USA
    return "USA implementation for FileLoader. Loading file" + fileId;
  }
}
public class FRAFileLoader implements  FileLoader {

  @Override
  public String loadFile(String fileId) {
    // ... Specific business logic for France
    return "France implementation for FileLoader. Loading file" + fileId;
  }
}

我们创建一个端点来加载文件:

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FileUploadController {

  FileLoader fileLoader;

  @PostMapping("/load/{fileId}/{countryCode}")
  public String loadFile(@PathVariable String fileId, @PathVariable String countryCode) {

    fileLoader = ... // Inject the right loader based on countryCode

    return fileLoader.loadFile(fileId);
  }
}

如何FileLoader在运行时为每个请求注入权利,基于countryCode?我在 Spring 中发现了一个名为FactoryBean的东西,它显然可以工作,但我现在确定它是否是正确的工具,或者这是否是解决此问题的正确方法。另外,我不知道注入将如何处理同时处理的请求。

标签: javaspringspring-bootdependency-injection

解决方案


您可以在这里使用运行时多态性做的最好的事情,在国家代码abstract的界面中再添加一个方法FileLoader

public interface FileLoader {

 default String loadFile(String fileId) {
   // Default business logic
  return "Default implementation for FileLoader. Loading file" + fileId;
 }

 public abstract String getCountryCode();
}

然后在每个实现类中实现它并返回适当的国家代码

public class USAFileLoader implements FileLoader {

  @Override
  public String loadFile(String fileId) {
    // ... Specific business logic for USA
    return "USA implementation for FileLoader. Loading file" + fileId;
   }

  public String getCountryCode(){
   return "USA";
  }
}

然后您可以将Autowire所有类型的 beanFileLoader放入List并调用loadFile适当的 bean

@RestController
public class FileUploadController {

 @Autowire
 List<FileLoader> fileLoaders;

  @PostMapping("/load/{fileId}/{countryCode}")
  public String loadFile(@PathVariable String fileId, @PathVariable String countryCode) {

return fileLoaders.stream()
                  .filter(f->f.getCountryCode().equlas(countryCode))
                  .findFirst()
                  .map(loader->loader.loadFile(fileId))
                  .orElse(()-> FileLoader.super.loadFile(fileId));  //calling interface default method
  }
} 

推荐阅读