Tag: spring, java, spring boot, dependency injection, ioc, aop, rest
Livello: intermedio
TL;DR: Panoramica dell'ecosistema Spring: IoC Container, Dependency Injection, bean lifecycle, Spring Boot e gestione REST.
Inversion of Control (IoC): delega la gestione del ciclo di vita degli oggetti al container.
Dependency Injection (DI): pattern per iniettare dipendenze tramite costruttore, setter o campo.
Spring Bean: oggetto istanziato, assemblato e gestito interamente dallo Spring IoC Container.
Scopi dei Bean (Scopes): singleton (default), prototype, request, session, application, websocket.
Iniezione via costruttore: approccio raccomandato per garantire immutabilita e facilitare i test unitari.
ApplicationContext: interfaccia avanzata del container che estende BeanFactory con eventi e messaggistica.
Spring Boot: semplifica la configurazione tramite auto-configuration, starter dipendenze e server embedded.
Aspect-Oriented Programming (AOP): separa cross-cutting concerns (logging, sicurezza, transazioni) dalla logica core.
Annotazioni core: @Component, @Service, @Repository, @Controller definiscono i diversi ruoli architetturali.
Transazionalita dichiarativa: gestione automatica del rollback e del commit tramite annotazione @Transactional.
Q: Qual e la differenza tra BeanFactory e ApplicationContext?R: BeanFactory fornisce le funzionalita base di IoC e lazy loading. Io preferisco ApplicationContext perche aggiunge auto-wiring avanzato, supporto a eventi e internazionalizzazione.
Q: Perche e preferibile l'iniezione tramite costruttore rispetto a @Autowired su campo?R: L'iniezione via costruttore previene i NullPointerException, garantisce che i bean siano immutabili e permette di istanziare la classe nei test senza riflessione.
Q: Come funziona @Transactional in Spring?R: Spring crea un proxy AOP attorno al bean che apre una transazione, intercetta eventuali eccezioni runtime per il rollback ed esegue il commit al termine del metodo.
Invocazione interna di metodi annotati con @Transactional: bypassa il proxy AOP e impedisce l'avvio della transazione.
Dipendenze circolari tra componenti: causano fallimenti all'avvio a meno di refactoring o uso temporaneo di @Lazy.
Dipendenza mutabile iniettata in un bean singleton: rischio concreto di race condition e concorrenza non thread-safe.
Ignorare la distinzione tra eccezioni unchecked (rollback di default) e checked (rollback non eseguito senza clausola rollbackFor).
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Transactional(readOnly = true)
public User findById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException("User not found"));
}
}
Java
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
return ResponseEntity.ok(userService.findById(id));
}
}
[ ] Configurazione di @Transactional(rollbackFor = Exception.class)
[ ] Meccanismo di registrazione dei BeanDefinition nel container
[ ] Differenze tra @ControllerAdvice e @ExceptionHandler
[ ] Funzionamento interno dell'auto-configuration di Spring Boot