简体   繁体   English

Spring 框架。 根据请求参数在运行时注入bean

[英]Spring Framework. Inject bean at runtime based on request parameter

Say we have a FileLoader Interface:假设我们有一个 FileLoader 接口:

public interface FileLoader {

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

And different implementations for different countries:以及针对不同国家/地区的不同实现:

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;
  }
}

And we create an endpoint to load files:我们创建一个端点来加载文件:

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);
  }
}

How can I inject the right FileLoader at runtime for every request, based on countryCode ?如何根据countryCode在运行时为每个请求注入正确的FileLoader I've found something in Spring called FactoryBean that apparently may work, but I'm now sure if it's the right tool, or if this is the right way to address this problem.我在 Spring 中发现了一些名为FactoryBean的东西,它显然可以工作,但我现在确定它是否是正确的工具,或者这是否是解决此问题的正确方法。 Also, I don't know how injection will behave with requests being proccessed at the same time.另外,我不知道注入将如何处理同时处理的请求。

The best thing you can do here using run time polymorphism, add one more abstract method in interface FileLoader for country code你可以在这里使用运行时多态性做的最好的事情,在接口FileLoader中为国家代码添加一个abstract方法

public interface FileLoader {

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

 public abstract String getCountryCode();
}

And then implement it in every implementation class with return the appropriate country code然后在每个实现 class 中实现它,并返回相应的国家代码

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";
  }
}

And then you can Autowire all beans of type FileLoader into List and call loadFile on appropriate bean然后您可以Autowire类型的所有 bean FileLoaderList并在适当的 bean 上调用loadFile

@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
  }
} 

You can receive a bean with another way at runtime using ApplicationContext::getBean :您可以在运行时使用ApplicationContext::getBean以另一种方式接收 bean:

@Autowired
ApplicationContext

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

    FileLoader fileloader = (FileLoader) applicationContext.getBean(countryCode);
    return fileLoader.loadFile(fileId);
}

However, I'd recommend creating a service layer that aggregates the country-specific implementations and uses a factory pattern.但是,我建议创建一个服务层来聚合特定国家/地区的实现并使用工厂模式。 There is nothing bad on such implementation.这样的实现没有什么不好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM