Pour un certain contexte, j'ai une application Java qui prend un fichier JSON et fait un certain traitement à l'aide de règles personnalisées en fonction des informations à l'intérieur du fichier. Le problème que j'ai actuellement est que j'essaie de déterminer de manière dynamique quelle classe de service à utiliser pour traiter le fichier au moment de l'exécution. Vous trouverez ci-dessous ma mise en œuvre actuelle:
implémentation 1 strong> p> implémentation 2 strong> p> Mise en œuvre 3 strong> p> @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
}
}
3 Réponses :
L'indirection est un excellent moyen de résoudre des problèmes informatiques. J'injecterais directement un DataServiceFactory au lieu de DataService et, dans cette usine, passerais l'énumération DataSource. Demandez à l'usine de renvoyer l'instance appropriée de DataService.
Vous pouvez introduire un modèle de résolveur pour identifier votre implémentation pendant l'exécution
@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 } }
et dans votre classe DataRunner, vous utilisez le résolveur pour trouver l'implémentation nécessaire
@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 } }
Si vous avez des centaines de processeurs différents, vous pouvez les enregistrer (injecter) dans un registre sous forme de liste. Vous pouvez ensuite parcourir la liste des enregistrements pour voir, quel processeur doit être utilisé (j'ai décidé d'implémenter les informations d'enregistrement dans le cadre du processeur)
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(); } }
En supposant que le contenu ne change pas, vous devez d'abord lire le contenu pour vérifier le type de fichier, puis créer votre bean en utilisant le type et le fichier. Si le contenu est censé changer, vous pouvez injecter les trois implémentations dans un bean qui délègue l'appel au bean approprié.
Voulez-vous dire le contenu dans le fichier de tâches que j'ai lu? Non ça ne change pas. Pourriez-vous me montrer un exemple de ce que vous entendez par "Créer votre haricot à l'aide du type et du fichier?"
Voir la réponse de @Jayesh.