1
votes

Spring DI ayant deux constructeurs en même temps

Ceci est un anti-pattern, mais je suis curieux de savoir ce qui va réellement se passer.

Si vous définissez explicitement un constructeur no-args et un constructeur avec un paramètre auto-câblé, comment le framework Spring va-t-il l'initialiser exactement?

@Service
class Clazz {

    private MyBean myBean;

    public Clazz(){}

    @Autowired
    public Clazz(MyBean myBean){
        this.myBean = myBean;
    }
}


0 commentaires

3 Réponses :


0
votes

Le constructeur marqué par @Autowired sera utilisé par spring. Vous pouvez le valider en exécutant le code suivant.

public class Main {
  @Component
  static class MyBean {}

  @Service
  static class Clazz {
    private MyBean myBean;

    public Clazz(){
      System.out.println("empty");
    }

    @Autowired
    public Clazz(MyBean myBean){
      this.myBean = myBean;
      System.out.println("non-empty");
    }
  }

  @Component
  @ComponentScan("my.package")
  private static class Configuration {
  }

  public static void main(String[] args) {
    var ctx = new AnnotationConfigApplicationContext();
    ctx.register(Configuration.class);
    ctx.refresh();
    ctx.getBean(Clazz.class);
  }
}

Le code imprime non-empty.


0 commentaires

0
votes

Spring choisit d'abord le constructeur par les plus grand nombre de paramètres

Les constructeurs de tri envisagent de préférer les constructeurs publics à ceux avec un nombre maximum d'arguments.

Signification Clazz (MyBean myBean)

Voici le Comparateur utilisé :

(e1, e2) -> {
    int result = Boolean.compare(Modifier.isPublic(e2.getModifiers()), Modifier.isPublic(e1.getModifiers()));
    return result != 0 ? result : Integer.compare(e2.getParameterCount(), e1.getParameterCount());


0 commentaires

2
votes

En plus des réponses ci-dessus, s'il n'y a qu'un seul constructeur déclaré sans @autowire, spring utilise le même constructeur pour l'injection.

S'il y a plusieurs constructeurs, Spring utilise un constructeur qui est @autowired.

Mentionné dans Spring Doc https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/htmlsingle/#beans-autowired-annotation

Depuis Spring Framework 4.3, une annotation @Autowired sur un tel constructeur n'est plus nécessaire si le bean cible n'en définit qu'un constructeur pour commencer. Cependant, si plusieurs constructeurs sont disponible, au moins un doit être annoté pour enseigner le contenant qui un à utiliser


0 commentaires