如何动态确定要在运行时使用的服务 Class
How to Dynamically Determine Service Class To Use At Runtime
对于某些上下文,我有一个 java 应用程序,它接受一个 JSON 文件,并根据文件中的信息使用自定义规则进行一些处理。我目前遇到的问题是,我正在尝试动态确定 class 用于在 运行 时间处理文件的服务。下面是我当前的实现:
界面
public interface DataService {
public void loadData(String path);
}
实施 1
@Service
public class ClassA implements DataService {
// some attributes...
public void loadData(String path) {
// implementation
}
}
实施 2
@Service
public class ClassB implements DataService {
// some attributes...
public void loadData(String path) {
// implementation
}
}
实施 3
@Service
public class ClassC implements DataService {
// some attributes...
public void loadData(String path) {
// implementation
}
}
利用Class
@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
}
}
因此,正如您所见,DataRunner 中的 init 方法 class 目前只是一厢情愿。是否可以通过 Spring 开机动态决定 class 在 运行 时使用哪个服务?还是我应该做一些完全不同的事情来实现我在这里想要的?
间接是解决计算问题的好方法。我会直接注入 DataServiceFactory 而不是 DataService,并在该工厂中传递 DataSource 枚举。拥有工厂 return 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 class 中使用解析器找到所需的实现
@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();
}
}
对于某些上下文,我有一个 java 应用程序,它接受一个 JSON 文件,并根据文件中的信息使用自定义规则进行一些处理。我目前遇到的问题是,我正在尝试动态确定 class 用于在 运行 时间处理文件的服务。下面是我当前的实现:
界面
public interface DataService {
public void loadData(String path);
}
实施 1
@Service
public class ClassA implements DataService {
// some attributes...
public void loadData(String path) {
// implementation
}
}
实施 2
@Service
public class ClassB implements DataService {
// some attributes...
public void loadData(String path) {
// implementation
}
}
实施 3
@Service
public class ClassC implements DataService {
// some attributes...
public void loadData(String path) {
// implementation
}
}
利用Class
@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
}
}
因此,正如您所见,DataRunner 中的 init 方法 class 目前只是一厢情愿。是否可以通过 Spring 开机动态决定 class 在 运行 时使用哪个服务?还是我应该做一些完全不同的事情来实现我在这里想要的?
间接是解决计算问题的好方法。我会直接注入 DataServiceFactory 而不是 DataService,并在该工厂中传递 DataSource 枚举。拥有工厂 return 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 class 中使用解析器找到所需的实现
@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();
}
}