0
votes

Comment déterminer dynamiquement la classe de service à utiliser au moment de l'exécution

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:

interface forte> p> xxx pré>

implémentation 1 strong> p> xxx

implémentation 2 strong> p> xxx pré>

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 commentaires

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.


3 Réponses :


2
votes

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.


0 commentaires

3
votes

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

    }
}


0 commentaires

1
votes

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


0 commentaires