Aller au contenu principal

Quiz: Beans et Contexte Spring

Testez vos connaissances sur les beans et le contexte applicatif.

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


Questions 1-15: Beans​

Question 1: Qu'est-ce qu'un bean Spring?

Réponse: Un bean est un objet géré par le conteneur Spring IoC:

  • Créé et configuré par Spring
  • Injection de dépendances automatique
  • Cycle de vie géré
  • Singleton par défaut

Question 2: Comment déclarer un bean avec une annotation?

Réponse:

// Avec stéréotype (scan automatique)
@Component
public class MyService { }

@Service
public class UserService { }

@Repository
public class UserRepository { }

@Controller
public class UserController { }

Question 3: Comment déclarer un bean avec @Bean?

Réponse:

@Configuration
public class AppConfig {

@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}

@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper()
.registerModule(new JavaTimeModule());
}
}

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

Réponse:

@Component@Bean
Sur une classeSur une méthode
Auto-détecté par scanDéclaré explicitement
Classes que vous contrôlezClasses tierces
Configuration limitéeContrôle total

Question 5: Quel est le nom par défaut d'un bean?

Réponse: Le nom de la classe en camelCase:

@Component
public class UserService { }
// Nom: userService

@Bean
public RestTemplate myRestTemplate() { }
// Nom: myRestTemplate

Personnaliser:

@Component("customName")
@Bean("customName")

Question 6: Comment récupérer un bean par son nom?

Réponse:

@Autowired
private ApplicationContext context;

public void example() {
UserService service = context.getBean("userService", UserService.class);

// Ou par type
UserService service = context.getBean(UserService.class);
}

Question 7: Qu'est-ce que le cycle de vie d'un bean?

Réponse:

  1. Instanciation: création de l'objet
  2. Injection: injection des dépendances
  3. Initialisation: méthodes @PostConstruct
  4. Utilisation: bean prêt
  5. Destruction: méthodes @PreDestroy

Question 8: Comment exécuter du code après l'initialisation?

Réponse:

@Component
public class DataLoader {

@PostConstruct
public void init() {
log.info("Bean initialisé");
loadData();
}
}

// Ou avec @Bean
@Bean(initMethod = "init")
public MyService myService() { }

Question 9: Comment exécuter du code avant la destruction?

Réponse:

@Component
public class ResourceManager {

@PreDestroy
public void cleanup() {
log.info("Nettoyage des ressources");
closeConnections();
}
}

// Ou avec @Bean
@Bean(destroyMethod = "close")
public DataSource dataSource() { }

Question 10: Qu'est-ce que InitializingBean et DisposableBean?

Réponse: Interfaces alternatives pour le cycle de vie:

@Component
public class MyBean implements InitializingBean, DisposableBean {

@Override
public void afterPropertiesSet() {
// Après injection
}

@Override
public void destroy() {
// Avant destruction
}
}

Préférer @PostConstruct/@PreDestroy pour moins de couplage.


Question 11: Comment implémenter ApplicationRunner?

Réponse:

@Component
public class StartupRunner implements ApplicationRunner {

@Override
public void run(ApplicationArguments args) {
log.info("Application démarrée");
// Arguments: args.getOptionValues("config")
}
}

Exécuté après le démarrage complet du contexte.


Question 12: Comment implémenter CommandLineRunner?

Réponse:

@Component
public class DataInitializer implements CommandLineRunner {

private final UserRepository repository;

@Override
public void run(String... args) {
repository.save(new User("Admin"));
log.info("Données initialisées");
}
}

Question 13: Comment ordonner l'exécution des runners?

Réponse:

@Component
@Order(1)
public class FirstRunner implements CommandLineRunner { }

@Component
@Order(2)
public class SecondRunner implements CommandLineRunner { }

Question 14: Comment créer un bean conditionnel?

Réponse:

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

@Bean
@ConditionalOnMissingBean(DataSource.class)
public DataSource defaultDataSource() { }

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

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

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

@Component
@Lazy
public class HeavyService {
public HeavyService() {
// Appelé seulement au premier accès
}
}

// Ou à l'injection
public MyController(@Lazy HeavyService service) { }

Questions 16-30: Contexte et Scopes​

Question 16: Qu'est-ce que l'ApplicationContext?

Réponse: Le conteneur central de Spring qui:

  • Gère tous les beans
  • Fournit l'injection de dépendances
  • Publie des événements
  • Charge les ressources
  • Gère l'internationalisation

Question 17: Quels sont les scopes de beans disponibles?

Réponse:

ScopeDescription
singletonUne instance par contexte (défaut)
prototypeNouvelle instance à chaque demande
requestUne instance par requête HTTP
sessionUne instance par session HTTP
applicationUne instance par ServletContext

Question 18: Comment définir le scope d'un bean?

Réponse:

@Component
@Scope("prototype")
public class PrototypeBean { }

@Bean
@Scope("request")
public RequestContext requestContext() { }

// Ou avec constantes
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

Question 19: Quel problème survient en injectant un prototype dans un singleton?

Réponse: Le singleton garde toujours la même instance du prototype:

@Component  // Singleton
public class SingletonService {

private final PrototypeBean proto; // Toujours la même instance!

public SingletonService(PrototypeBean proto) {
this.proto = proto;
}
}

Solution: utiliser ObjectProvider ou @Lookup.


Question 20: Comment utiliser ObjectProvider?

Réponse:

@Component
public class SingletonService {

private final ObjectProvider<PrototypeBean> protoProvider;

public void doWork() {
PrototypeBean proto = protoProvider.getObject(); // Nouvelle instance
}
}

Question 21: Comment utiliser @Lookup?

Réponse:

@Component
public abstract class SingletonService {

@Lookup
protected abstract PrototypeBean getPrototype();

public void doWork() {
PrototypeBean proto = getPrototype(); // Nouvelle instance
}
}

Question 22: Comment écouter les événements du contexte?

Réponse:

@Component
public class ContextListener {

@EventListener
public void onContextRefreshed(ContextRefreshedEvent event) {
log.info("Contexte rafraîchi");
}

@EventListener
public void onContextClosed(ContextClosedEvent event) {
log.info("Contexte fermé");
}
}

Question 23: Comment publier un événement personnalisé?

Réponse:

// Événement
public class UserCreatedEvent extends ApplicationEvent {
private final User user;

public UserCreatedEvent(Object source, User user) {
super(source);
this.user = user;
}
}

// Publication
@Service
public class UserService {

private final ApplicationEventPublisher publisher;

public void createUser(User user) {
userRepository.save(user);
publisher.publishEvent(new UserCreatedEvent(this, user));
}
}

// Écoute
@Component
public class UserEventListener {

@EventListener
public void onUserCreated(UserCreatedEvent event) {
log.info("Utilisateur créé: {}", event.getUser().getName());
}
}

Question 24: Comment écouter un événement de façon asynchrone?

Réponse:

@EnableAsync
@Configuration
public class AsyncConfig { }

@Component
public class AsyncListener {

@Async
@EventListener
public void onEvent(MyEvent event) {
// Exécuté dans un autre thread
}
}

Question 25: Comment accéder à l'environnement Spring?

Réponse:

@Component
public class ConfigService {

private final Environment env;

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

public void showConfig() {
String property = env.getProperty("app.name");
String[] profiles = env.getActiveProfiles();
boolean isDev = env.acceptsProfiles(Profiles.of("dev"));
}
}

Question 26: Comment charger des ressources externes?

Réponse:

@Component
public class ResourceLoader {

@Value("classpath:data/config.json")
private Resource configResource;

public void load() throws IOException {
String content = new String(configResource.getInputStream().readAllBytes());
}
}

Question 27: Comment implémenter EnvironmentPostProcessor?

Réponse:

public class CustomEnvProcessor implements EnvironmentPostProcessor {

@Override
public void postProcessEnvironment(ConfigurableEnvironment env, SpringApplication app) {
// Modifier l'environnement avant le démarrage
Map<String, Object> props = new HashMap<>();
props.put("custom.property", "value");
env.getPropertySources().addFirst(new MapPropertySource("custom", props));
}
}

Enregistrer dans META-INF/spring.factories.


Question 28: Comment utiliser les profils Spring?

Réponse:

// Bean actif uniquement en dev
@Component
@Profile("dev")
public class DevOnlyService { }

// Bean actif sauf en prod
@Component
@Profile("!prod")
public class NonProdService { }

// Plusieurs profils
@Component
@Profile({"dev", "test"})
public class DevTestService { }

Question 29: Comment définir des beans dans des configurations séparées?

Réponse:

@Configuration
public class DatabaseConfig {
@Bean
public DataSource dataSource() { }
}

@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain() { }
}

@Configuration
@Import({DatabaseConfig.class, SecurityConfig.class})
public class AppConfig { }

Question 30: Comment tester un contexte Spring?

Réponse:

@SpringBootTest
class ContextTest {

@Autowired
private ApplicationContext context;

@Test
void contextLoads() {
assertThat(context).isNotNull();
assertThat(context.getBean(UserService.class)).isNotNull();
}

@Test
void beanExists() {
assertThat(context.containsBean("userService")).isTrue();
}
}

Score​

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

Retour au Module 5