3
votes

Injection de spring bean entre deux beans - implémentation de la même interface

J'ai deux classes Spring Bean qui implémentent la même interface.

 @Service
 public class Demo
  {

  @Autowired
  private Abc abc;

  }

  }

Les deux classes sont

 @Service
 public class SomeClass implements abc
  {

  @Override
  public class getNumber()
  {


  }

 }


 @Service
 public class SomeClass1 implements abc
 {

  @Override
  public class getNumber()
  {

  }
  }

Dans ma classe Service .

 public interface Abc()
  {
    String getNumber();
  }

J'ai eu une erreur "requis un seul bean, mais 2 ont été trouvés"

Pour cette erreur, je peux avoir la chance de mettre @Primary dans le haut de l'un des bean.

Mais je n'ai qu'un moyen de dire «configuration d'un bean» en fonction de la valeur que j'obtiendrai au moment de l'exécution (à partir de la base de données).

Pouvez-vous me suggérer un moyen.


3 commentaires

stackoverflow.com/questions/40830548/…


Je ne comprends pas entièrement la question, mais il existe une annotation @Qualifier pour gérer plusieurs implémentations de spring bean.


La question n'est pas claire sur ce que vous voulez. Cependant, si vous cherchez à avoir des beans basés sur des propriétés externes, vous pouvez utiliser @ConditionalOnProperty. En savoir plus sur Spring Docs pour un cas d'utilisation.


3 Réponses :


6
votes

Vous pouvez télécharger automatiquement une liste d'interfaces, puis choisir la bonne. Vous pouvez écrire:

@Autowired
List<Abc> abcs;

cela se traduira par une liste d'implémentations de l'interface. Dans le corps de votre méthode, vous pouvez ensuite choisir la bonne.


0 commentaires

2
votes

Deux méthodes vous permettent de câbler automatiquement l'implémentation correcte.

Remplacez le nom de votre champ auto-câblé par le même nom que la classe d'implémentation (dans camelcase)

@Autowired
@Qualifier("someClass")
private Abc SomeClass;

essayez de trouver une implémentation de l'interface 'Abc' avec le nom de classe 'SomeClass'.

Une autre façon est d'ajouter un nom de bean à votre annotation de service

@Service("someClass")
public class SomeClass implements abc

Cela peut ensuite être câblé automatiquement comme suit

@Autowired
private Abc someClass;


1 commentaires

Êtes-vous sûr que Sping autowires interfaces comme vous l'avez décrit dans la première option? Et si un avait SomeClass1 et SomeClass2?



1
votes

Je pense que le problème qu'il pose est de savoir comment configurer deux implentations et comment utiliser dynamiquement le bon bean (basé sur les données de DB). Il semble que ce soit un exemple de modèle d'usine

Code Psuedo

Class SomeFactory{
 @Autowired
 private Abc someClass;
  @Autowired
  private Abc someClass1;// keeping bean Name same as class name would solve bean finding issue

public Abc getBeanFor(String type) {
if("someClass".equals(type)
    return someClass;
  return someClass1;
} 
}

Class TestClass{
 @Autowired
   private SomeFactory factory ;
  private void someProcess() {
   // Read type from DB for data

   factory.getBeanFor(typeReadFromData)
                .process();
 } 
} 


0 commentaires