Injection par constructeur et dépendances circulaires
Privilégiez l’injection par constructeur pour faciliter les essais, détectez les dépendances circulaires et rompez-les avec @Lazy.
Injection par constructeur et dépendances circulaires est une leçon Java Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Java Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Java Academy comprend 4 leçons au total.
Trois types d’injection
Spring prend en charge l’injection par constructeur (recommandée), l’injection dans les champs (@Autowired sur un champ) et l’injection par méthode d’affectation. L’injection par constructeur est préférable pour faciliter les vérifications et garantir l’immutabilité.
Injection par constructeur
Déclarez les dépendances comme paramètres du constructeur. Spring les injecte automatiquement. S’il n’y a qu’un seul constructeur, @Autowired est facultative (Spring Boot 2.1+).
@Service
public class OrderService {
private final OrderRepository repo;
private final EmailService email;
// @Autowired is optional when there is only one constructor
public OrderService(OrderRepository repo, EmailService email) {
this.repo = repo;
this.email = email;
}
}Pourquoi privilégier l’injection par constructeur
Avec l’injection par constructeur : (1) les dépendances sont final — elles sont immuables, (2) la classe est toujours entièrement initialisée, (3) les vérifications unitaires ne dépendent pas de Spring — il suffit d’appeler new OrderService(mockRepo, mockEmail).
// Unit test — no Spring context needed:
OrderRepository mockRepo = mock(OrderRepository.class);
EmailService mockEmail = mock(EmailService.class);
OrderService service = new OrderService(mockRepo, mockEmail);
// Test service logic directlyInjection dans les champs (à éviter)
L’injection dans les champs avec @Autowired est concise, mais pose des problèmes : les champs ne peuvent pas être final, le composant n’est pas entièrement initialisé après sa construction et les vérifications unitaires nécessitent Spring ou les utilitaires de réflexion de Mockito.
// Avoid in production code:
@Service
public class UserService {
@Autowired // hidden dependency
private UserRepository repo; // cannot be final
}Injection par méthode d’affectation pour les dépendances optionnelles
Utilisez l’injection par méthode d’affectation pour les dépendances optionnelles qui disposent d’une valeur par défaut pertinente — annotez la méthode avec @Autowired(required = false).
@Service
public class NotificationService {
private SmsSender smsSender; // optional
@Autowired(required = false)
public void setSmsSender(SmsSender s) { this.smsSender = s; }
}Qu’est-ce qu’une dépendance circulaire ?
Une dépendance circulaire se produit lorsque A nécessite B et que B nécessite A, directement ou par l’intermédiaire d’autres dépendances. Spring la détecte au démarrage et lève BeanCurrentlyInCreationException.
// CIRCULAR:
@Service class A { A(B b) {} }
@Service class B { B(A a) {} }
// Spring throws: BeanCurrentlyInCreationException: Is there an unresolvable circular reference?Rompre la circularité : extraire un troisième service
La solution la plus propre consiste à extraire la logique commune dans un troisième service dont ni A ni B ne dépend de manière cyclique.
// Before: A <-> B
// After: A -> C, B -> C (no cycle)
@Service class SharedLogic { ... }
@Service class A { A(SharedLogic s) {} }
@Service class B { B(SharedLogic s) {} }Rompre la circularité : @Lazy
Ajoutez @Lazy à un point d’injection. Spring crée immédiatement un objet intermédiaire pour B ; B n’est réellement instancié que lorsque A appelle sa première méthode.
@Service
public class A {
private final B b;
public A(@Lazy B b) { this.b = b; } // breaks the cycle
}Rompre la circularité : recherche dans ApplicationContext
Injectez ApplicationContext dans un composant et recherchez l’autre composant de manière différée via context.getBean() — mais cela réduit la facilité de vérification et la clarté du code.
@Service
public class A implements ApplicationContextAware {
private ApplicationContext ctx;
public void setApplicationContext(ApplicationContext c) { this.ctx = c; }
public void doWork() { ctx.getBean(B.class).help(); }
}Injection par méthode d’affectation pour rompre la circularité
Les composants injectés par méthode d’affectation sont créés en premier (la construction réussit), puis leurs dépendances sont définies. Cela permet les dépendances circulaires au prix d’une perte d’immutabilité.
@Service
public class A {
private B b;
@Autowired public void setB(B b) { this.b = b; } // Spring sets after construction
}spring.main.allow-circular-references (Spring Boot 2.6+)
Spring Boot 2.6+ interdit les dépendances circulaires par défaut. Activez-les explicitement uniquement comme mesure temporaire pendant la refactorisation : spring.main.allow-circular-references=true.
# application.properties (temporary workaround only):
spring.main.allow-circular-references=trueVérification rapide
Pourquoi l’injection par constructeur est-elle préférable à l’injection dans les champs ?
Récapitulatif
Privilégiez l’injection par constructeur : elle est immuable, vérifiable et explicite. Évitez l’injection dans les champs. Utilisez @Lazy ou extrayez un service commun pour rompre les dépendances circulaires. Spring Boot 2.6+ signale les références circulaires au démarrage — considérez-les comme des avertissements de conception.
Questions Fréquemment Posées
La leçon « Injection par constructeur et dépendances circulaires » est-elle gratuite ?
Oui — le texte complet de « Injection par constructeur et dépendances circulaires » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Java Academy, passe à CoddyKit PRO. Le cours Java Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Injection par constructeur et dépendances circulaires » ?
Privilégiez l’injection par constructeur pour faciliter les essais, détectez les dépendances circulaires et rompez-les avec @Lazy. Tu pratiques Java Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Java Academy ?
Aucune expérience préalable n'est requise. Java Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « Injection par constructeur et dépendances circulaires » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Java Academy ?
Oui. Chaque leçon Java Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Auto-configuration et starters Spring Boot
- Propriétés d’application et profils
- Câblage des beans : @Component, @Service, @Repository
- Injection par constructeur et dépendances circulaires