Java 如何在运行时动态确定要使用的服务类
对于某些上下文,我有一个java应用程序,它接受一个JSON文件,并根据文件中的信息使用自定义规则进行一些处理。我目前的问题是,我试图动态地确定在运行时使用哪个服务类来处理文件。以下是我目前的执行情况: 接口 实施1 实施2 执行情况3 利用类Java 如何在运行时动态确定要使用的服务类,java,spring,spring-boot,dependency-injection,autowired,Java,Spring,Spring Boot,Dependency Injection,Autowired,对于某些上下文,我有一个java应用程序,它接受一个JSON文件,并根据文件中的信息使用自定义规则进行一些处理。我目前的问题是,我试图动态地确定在运行时使用哪个服务类来处理文件。以下是我目前的执行情况: 接口 实施1 实施2 执行情况3 利用类 因此,正如您所看到的,DataRunner类中的init方法在这一点上只是一厢情愿。是否可以通过Spring引导动态确定在运行时使用哪个服务类?或者我应该做一些完全不同的事情来实现我在这里想要的吗?间接寻址是解决计算问题的好方法。我将直接注入DataSe
因此,正如您所看到的,DataRunner类中的init方法在这一点上只是一厢情愿。是否可以通过Spring引导动态确定在运行时使用哪个服务类?或者我应该做一些完全不同的事情来实现我在这里想要的吗?间接寻址是解决计算问题的好方法。我将直接注入DataServiceFactory而不是DataService,并在该工厂中传递DataSource枚举。让工厂返回相应的DataService实例。您可以在运行时引入解析器模式来标识您的实现
@Service
public class DataServiceResolver{
@Autowired
private DataService classA;
@Autowired
private DataService classB;
@Autowired
private DataService classC;
public DataService resolve(Whatever whatever) {
//process your input and find the enum dataSource;
DataSource datasource = process(file);
DataService dataService;
switch datasource {
case A:
dataService = classA;
break;
case B:
dataService = classB;
break;
case C:
dataService = classC;
break;
default:
dataService = classB;
}
return dataService
}
}
在DataRunner类中,使用解析器查找所需的实现
@Service
public class DataRunner {
@Autowired
private DataServiceResolver dataServiceResolver;
@Value("${task.file}")
private String taskFile;
@PostConstruct
public void init() {
// process the incoming taskFile and derive an enum called DataSource
//call the resolver and resolve to the needed dataservice. whatever can be your taskFile, etc
DataService dataService = dataServiceResolver.resolve(whatever);
dataService.loadData("/example/file/location"); // what I wish would work
}
}
如果您有数百个不同的处理器,您可以将它们作为列表注册到注册表中。然后,您可以遍历注册列表,查看应该使用哪个处理器。我决定将注册信息作为处理器的一部分来实现
public interface DataProcessor {
public boolean supports(MyInput input);
public MyOutput process(MyInput input);
}
@Service
public class YesDataProcessor implements DataProcessor {
public boolean supports(MyInput input) {
return input.getSomething().equals("yes");
}
public MyOutput process(MyInput input) {
// ... transforming to output
return
}
}
@Service
public class NoDataProcessor implements DataProcessor {
public boolean supports(MyInput input) {
return input.getSomething().equals("no");
}
public MyOutput process(MyInput input) {
// ... transforming to output
return output;
}
}
@Service
public class MyDataProcessorRegistry {
@Autowired
private List<DataProcessor> processors;
public Optional<DataProcessor> getProcessor(MyInput input) {
return processors.stream().filter(p -> p.supports(input)).findFirst();
}
}
假设内容不变,您应该首先读取内容以检查文件类型,然后使用类型和文件创建bean。如果内容需要更改,您可以将所有三个实现注入一个bean,将调用委托给适当的bean。您是指我读入的任务文件中的内容吗?不,这不会改变。你能给我举一个例子,说明你使用类型和文件创建bean的意思吗?见@Jayesh的答案。
@Service
public class ClassC implements DataService {
// some attributes...
public void loadData(String path) {
// implementation
}
}
@Service
public class DataRunner {
@Autowired
private DataService dataService;
@Value("${task.file}")
private String taskFile;
@PostConstruct
public void init() {
// process the incoming taskFile and derive an enum called DataSource
dataService.loadData("/example/file/location"); // what I wish would work
}
}
@Service
public class DataServiceResolver{
@Autowired
private DataService classA;
@Autowired
private DataService classB;
@Autowired
private DataService classC;
public DataService resolve(Whatever whatever) {
//process your input and find the enum dataSource;
DataSource datasource = process(file);
DataService dataService;
switch datasource {
case A:
dataService = classA;
break;
case B:
dataService = classB;
break;
case C:
dataService = classC;
break;
default:
dataService = classB;
}
return dataService
}
}
@Service
public class DataRunner {
@Autowired
private DataServiceResolver dataServiceResolver;
@Value("${task.file}")
private String taskFile;
@PostConstruct
public void init() {
// process the incoming taskFile and derive an enum called DataSource
//call the resolver and resolve to the needed dataservice. whatever can be your taskFile, etc
DataService dataService = dataServiceResolver.resolve(whatever);
dataService.loadData("/example/file/location"); // what I wish would work
}
}
public interface DataProcessor {
public boolean supports(MyInput input);
public MyOutput process(MyInput input);
}
@Service
public class YesDataProcessor implements DataProcessor {
public boolean supports(MyInput input) {
return input.getSomething().equals("yes");
}
public MyOutput process(MyInput input) {
// ... transforming to output
return
}
}
@Service
public class NoDataProcessor implements DataProcessor {
public boolean supports(MyInput input) {
return input.getSomething().equals("no");
}
public MyOutput process(MyInput input) {
// ... transforming to output
return output;
}
}
@Service
public class MyDataProcessorRegistry {
@Autowired
private List<DataProcessor> processors;
public Optional<DataProcessor> getProcessor(MyInput input) {
return processors.stream().filter(p -> p.supports(input)).findFirst();
}
}