Comme je le sais, field injection
n'est pas recommandé. Doit utiliser constructor
à la place.
Ce que j'essaie de faire ici, c'est d'utiliser @Autowired
dans le constructeur de la classe de base, et la rendre accessible à toutes les sous-classes. Dans certaines sous-classes, j'ai également besoin de certains beans spécifiques pour être @Autowired
de leurs constructeurs. Le code de démonstration est le suivant:
Classe de base:
public abstract class Base {
protected final MyDemoService myDemoService;
@Autowired
public Base(MyDemoService myDemoService) {
this.myDemoService = myDemoService;
}
}
Classe (sous) héritée:
public class Sub extends Base {
private final MySubService mySubService;
@Autowired
public Sub(MySubService mySubService) {
this.mySubService = mySubService;
}
}
Cela me donnera une erreur "pas de constructeur par défaut".
C'est similaire à la question: question et réponse similaires , mais cela ne fonctionne pas ici.
Je m'y suis plongé depuis un moment, j'ai trouvé cet article sur dependency injection
: lire la suite
Je pense que c'est le Setter Injection
un bon moyen pour ma question?
Setter injection:
public abstract class Base {
protected MyDemoService myDemoService;
@Autowired
public void setMyDemoService(MyDemoService myDemoService) {
this.myDemoService = myDemoService;
}
}
Je suis nouveau à Java Spring Boot, et je veux obtenir des conseils d'expertise de votre part. Toute discussion sera très appréciée!
Le code que vous fournissez ne sera pas compilé. Tant que dans votre classe de base vous n'avez pas le constructeur par défaut, vous devez appeler super(MyDemoService)
dans child.
Classe (sous) héritée:
public class Sub extends Base {
private final MySubService mySubService;
@Autowired
public Sub(MySubService mySubService, MyDemoService myDemoService){
super(myDemoService);
this.mySubService = mySubService;
}
}
Ou, si MySubService
est une implémentation de MyDemoService
@Autowired
public Sub(MySubService mySubService){
super(mySubService);
}
Tant que votre domaine MyDemoService myDemoService
dans la classe abstraite est protected
vous pouvez l'utiliser dans des sous-classes.
Si vous avez plusieurs implémentations de MyDemoService
, vous devez utiliser @Qualifier
comme décrit dans réponse que vous avez mentionnée .
public Sub(@Qualifier("MySubService") MyDemoService mySubService){
super(mySubService);
}
N'utilisez pas l'injection de champs, utilisez l'injection de constructeur en rappelant les super constructeurs selon le cas.
L'injection du constructeur garantit que votre objet est correctement rempli avant l'instanciation, l'injection de setter ne le fait pas et rend le code plus sujet aux bogues (pas un autre bogue nullpointer ....)
Si vous êtes préoccupé par le code supplémentaire que vous devez écrire, utilisez Project Lombok pour laisser Lombok générer le code constructeur pour vous comme décrit ici Pourquoi l'injection de champs est mauvaise
Soit dit en passant à partir du printemps 4, si vous n'avez qu'un seul constructeur dans votre classe, vous n'avez pas besoin de @Autowired sur le constructeur.
Je suggère d'utiliser @Configuration
Des classes. De cette façon, vous pouvez supprimer entièrement les annotations Spring de vos classes professionnelles:
public class Sub extends Base {
private final MySubService mySubService;
public Sub(MySubService mySubService, MyDemoService myDemoService){
super(myDemoService);
this.mySubService = mySubService;
}
}
Configuration de printemps:
@Configuration
public class SubConfig{
@Bean
public Sub sub(MySubService subService, MyDemoService demoService){
return new Sub(subService, demoService);
}
}
Avec les classes de configuration, vous ne comptez plus sur l'analyse de chemin de classe magique, mais instanciez à nouveau manuellement les beans. Il y a beaucoup moins de surprises dans cette approche.
Ça marche!!!! Constructeur Autowired Qualifier Inheritance Injection
Classe abstraite de base DocumentoBase.
@Qualifier("DocumentServiceBase")
private DocumentService documentService;
@Autowired
public DocumentoBase(@Qualifier("DocumentServiceBase") DocumentService documentService){
this.documentService = documentService;
}
Classe héritée DocumentoController.
@Qualifier("DocumentServiceImplv13")
private DocumentService documentService;
@Autowired
public DocumentoController(@Qualifier("DocumentServiceImplv13") DocumentService documentService){
super(documentService);
this.documentService = documentService;
}