Aller au contenu principal

Quiz: Injection de Dépendances

Testez vos connaissances sur l'injection de dépendances avancée.

30 questions - Cliquez sur chaque question pour révéler la réponse.


Questions 1-15: Types d'Injection​

Question 1: Quels sont les trois types d'injection de dépendances?

Réponse:

  1. Injection par constructeur (recommandée)
  2. Injection par setter
  3. Injection par champ (field injection)

Question 2: Pourquoi l'injection par constructeur est-elle recommandée?

Réponse:

  • Dépendances immutables (final)
  • Obligatoires - pas d'objet sans dépendances
  • Testable - facile à mocker
  • Détection des cycles à la compilation
  • Pas besoin de @Autowired (Spring 4.3+)

Question 3: Comment faire une injection par setter?

Réponse:

@Service
public class UserService {

private UserRepository userRepository;

@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}

Utilisé pour les dépendances optionnelles ou reconfigurables.


Question 4: Pourquoi éviter l'injection par champ?

Réponse:

  • Impossible de rendre la dépendance final
  • Difficile à tester sans Spring
  • Masque les dépendances (pas visible dans le constructeur)
  • Facilite les violations de SRP (trop de dépendances)
// À éviter
@Autowired
private UserRepository repo;

Question 5: Quand @Autowired est-il optionnel?

Réponse: Depuis Spring 4.3, si une classe a un seul constructeur, @Autowired est implicite.

@Service
public class UserService {
private final UserRepository repo;

// @Autowired optionnel
public UserService(UserRepository repo) {
this.repo = repo;
}
}

Question 6: Comment gérer plusieurs constructeurs?

Réponse: Marquer explicitement le constructeur à utiliser:

@Service
public class UserService {

public UserService() { }

@Autowired // Spring utilisera celui-ci
public UserService(UserRepository repo) {
this.repo = repo;
}
}

Question 7: Comment rendre une dépendance optionnelle?

Réponse: Plusieurs façons:

// 1. required = false
@Autowired(required = false)
private CacheService cache;

// 2. Optional (recommandé)
public MyService(Optional<CacheService> cache) {
this.cache = cache.orElse(null);
}

// 3. @Nullable
public MyService(@Nullable CacheService cache) { }

Question 8: Comment injecter toutes les implémentations d'une interface?

Réponse:

@Service
public class NotificationManager {

private final List<NotificationService> services;

public NotificationManager(List<NotificationService> services) {
this.services = services;
}

public void notifyAll(String msg) {
services.forEach(s -> s.send(msg));
}
}

Question 9: Comment injecter un Map de beans?

Réponse:

@Service
public class ProcessorManager {

// Clé = nom du bean, Valeur = instance
private final Map<String, Processor> processors;

public ProcessorManager(Map<String, Processor> processors) {
this.processors = processors;
}

public void process(String type, Data data) {
processors.get(type).process(data);
}
}

Question 10: À quoi sert @Primary?

Réponse: Désigner le bean par défaut quand plusieurs implémentations existent:

@Service
@Primary
public class EmailNotification implements NotificationService { }

@Service
public class SmsNotification implements NotificationService { }

// EmailNotification sera injecté par défaut

Question 11: À quoi sert @Qualifier?

Réponse: Spécifier quel bean injecter:

@Service("email")
public class EmailNotification implements NotificationService { }

@Service("sms")
public class SmsNotification implements NotificationService { }

// Injection
public MyService(@Qualifier("sms") NotificationService notif) { }

Question 12: Comment créer un @Qualifier personnalisé?

Réponse:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
public @interface Premium { }

@Service
@Premium
public class PremiumNotification implements NotificationService { }

// Utilisation
public MyService(@Premium NotificationService notif) { }

Question 13: Qu'est-ce que @Lazy?

Réponse: Retarde la création du bean jusqu'au premier accès:

@Service
@Lazy
public class HeavyService { }

// Ou à l'injection
public MyService(@Lazy HeavyService heavy) { }

Utilisé pour: performance au démarrage, dépendances circulaires.


Question 14: Comment résoudre une dépendance circulaire?

Réponse:

  1. Refactorer (meilleur choix)
  2. Utiliser @Lazy sur une des dépendances
  3. Utiliser setter injection
@Service
public class A {
public A(@Lazy B b) { this.b = b; }
}

@Service
public class B {
public B(A a) { this.a = a; }
}

Question 15: Comment injecter des valeurs de configuration?

Réponse: Avec @Value:

@Service
public class EmailService {

@Value("${app.email.sender}")
private String sender;

@Value("${app.email.enabled:true}")
private boolean enabled;

// Ou via constructeur
public EmailService(@Value("${app.email.host}") String host) { }
}

Questions 16-30: Cas Avancés​

Question 16: Quelle est la différence entre @Autowired et @Resource?

Réponse:

  • @Autowired: Spring, injection par type
  • @Resource: Java EE (JSR-250), injection par nom
@Autowired  // Par type
private UserService userService;

@Resource(name = "specificService") // Par nom
private UserService userService;

Question 17: Comment injecter le contexte Spring lui-même?

Réponse:

@Service
public class DynamicBeanLoader implements ApplicationContextAware {

private ApplicationContext context;

@Override
public void setApplicationContext(ApplicationContext ctx) {
this.context = ctx;
}

public Object getBean(String name) {
return context.getBean(name);
}
}

Question 18: Comment obtenir un bean de façon programmatique?

Réponse:

@Service
public class BeanFactory {

private final ApplicationContext context;

public BeanFactory(ApplicationContext context) {
this.context = context;
}

public UserService getUserService() {
return context.getBean(UserService.class);
}
}

Question 19: Qu'est-ce que ObjectProvider?

Réponse: Une façon sûre d'obtenir des beans optionnels ou multiples:

@Service
public class MyService {

private final ObjectProvider<CacheService> cacheProvider;

public MyService(ObjectProvider<CacheService> cacheProvider) {
this.cacheProvider = cacheProvider;
}

public void doWork() {
cacheProvider.ifAvailable(cache -> cache.put(...));
}
}

Question 20: Comment injecter un bean prototype dans un singleton?

Réponse: Utiliser ObjectProvider ou @Lookup:

// Option 1: ObjectProvider
@Service
public class SingletonService {
private final ObjectProvider<PrototypeBean> provider;

public void doWork() {
PrototypeBean bean = provider.getObject(); // Nouvelle instance
}
}

// Option 2: @Lookup
@Service
public abstract class SingletonService {
@Lookup
protected abstract PrototypeBean getPrototype();
}

Question 21: Qu'est-ce que @DependsOn?

Réponse: Force l'ordre de création des beans:

@Service
@DependsOn("databaseInitializer")
public class UserService {
// Créé APRÈS databaseInitializer
}

Question 22: Comment exclure un bean de l'auto-configuration?

Réponse:

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class MyApp { }

// Ou dans application.yml
spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

Question 23: Comment créer un bean conditionnel?

Réponse:

@Bean
@ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
public CacheManager cacheManager() { }

@Bean
@ConditionalOnMissingBean
public DefaultService defaultService() { }

@Bean
@Profile("dev")
public DevService devService() { }

Question 24: Qu'est-ce que @Order?

Réponse: Définit l'ordre de priorité pour les beans collectés:

@Component
@Order(1)
public class FirstFilter implements Filter { }

@Component
@Order(2)
public class SecondFilter implements Filter { }

// Injection dans l'ordre
public MyService(List<Filter> filters) {
// FirstFilter, SecondFilter
}

Question 25: Comment injecter l'environnement Spring?

Réponse:

@Service
public class ConfigService {

private final Environment env;

public ConfigService(Environment env) {
this.env = env;
}

public String getProperty(String key) {
return env.getProperty(key);
}

public boolean isDev() {
return Arrays.asList(env.getActiveProfiles()).contains("dev");
}
}

Question 26: Comment tester un service avec injection?

Réponse:

@ExtendWith(MockitoExtension.class)
class UserServiceTest {

@Mock
private UserRepository userRepository;

@InjectMocks
private UserService userService;

@Test
void shouldFindUser() {
when(userRepository.findById(1L)).thenReturn(Optional.of(user));

User result = userService.findById(1L);

assertThat(result).isNotNull();
}
}

Question 27: Comment injecter des propriétés groupées?

Réponse: Avec @ConfigurationProperties:

@ConfigurationProperties(prefix = "app.mail")
public class MailProperties {
private String host;
private int port;
private boolean ssl;
// getters/setters
}

// Injection
@Service
public class MailService {
public MailService(MailProperties props) { }
}

Question 28: Quelle est la différence entre @Component et @Bean?

Réponse:

@Component@Bean
Sur classeSur méthode
Auto-détecté par scanDéclaré explicitement
Configuration limitéeContrôle total

Utiliser @Bean pour les classes externes ou configuration complexe.


Question 29: Comment avoir plusieurs instances du même bean?

Réponse:

@Configuration
public class DataSourceConfig {

@Bean
@Qualifier("primary")
public DataSource primaryDataSource() { }

@Bean
@Qualifier("secondary")
public DataSource secondaryDataSource() { }
}

// Injection
public MyService(
@Qualifier("primary") DataSource primary,
@Qualifier("secondary") DataSource secondary) { }

Question 30: Quels sont les problèmes courants d'injection?

Réponse:

  1. NoSuchBeanDefinitionException: bean manquant
  2. NoUniqueBeanDefinitionException: plusieurs candidats
  3. BeanCurrentlyInCreationException: dépendance circulaire
  4. UnsatisfiedDependencyException: injection échouée

Solutions: vérifier annotations, @Qualifier, @Primary, @Lazy.


Score​

ScoreNiveau
27-30Excellent - Injection maîtrisée
21-26Bien - Quelques révisions
15-20Moyen - Relisez le chapitre
Moins de 15À revoir

Retour au Module 5