Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在运行时动态确定要使用的服务类_Java_Spring_Spring Boot_Dependency Injection_Autowired - Fatal编程技术网

Java 如何在运行时动态确定要使用的服务类

Java 如何在运行时动态确定要使用的服务类,java,spring,spring-boot,dependency-injection,autowired,Java,Spring,Spring Boot,Dependency Injection,Autowired,对于某些上下文,我有一个java应用程序,它接受一个JSON文件,并根据文件中的信息使用自定义规则进行一些处理。我目前的问题是,我试图动态地确定在运行时使用哪个服务类来处理文件。以下是我目前的执行情况: 接口 实施1 实施2 执行情况3 利用类 因此,正如您所看到的,DataRunner类中的init方法在这一点上只是一厢情愿。是否可以通过Spring引导动态确定在运行时使用哪个服务类?或者我应该做一些完全不同的事情来实现我在这里想要的吗?间接寻址是解决计算问题的好方法。我将直接注入DataSe

对于某些上下文,我有一个java应用程序,它接受一个JSON文件,并根据文件中的信息使用自定义规则进行一些处理。我目前的问题是,我试图动态地确定在运行时使用哪个服务类来处理文件。以下是我目前的执行情况:

接口

实施1

实施2

执行情况3

利用类


因此,正如您所看到的,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();
  }
}