Spring Boot Architecture & Internals
Deep-dive architectural concepts frequently targeted in Senior / Full-Stack interview loops.
Core Container & Bean Lifecycle
Q1: Explain the step-by-step lifecycle of a Spring Bean.
View Architectural Answer
The Spring Bean lifecycle is handled entirely by the ApplicationContext container via the following deterministic phases:
- Instantiation: The container finds the bean definition (via component scanning or
@Beanconfiguration) and uses reflection to instantiate the bean (essentially executing its constructor). - Populate Properties: Dependency Injection occurs here. The container resolves and injects all
@Autowiredfields, setters, or constructor arguments. - Aware Interfaces Execution: If the bean implements any
Awareinterfaces, Spring invokes them to pass container metadata:BeanNameAware-> passes the bean ID.BeanFactoryAware-> passes the containing BeanFactory.ApplicationContextAware-> passes the current ApplicationContext environment.
- BeanPostProcessor (Pre-Initialization): The
postProcessBeforeInitialization()method of any registeredBeanPostProcessoris executed. (This is where Spring wraps your beans in Proxies if required, such as for AOP or security filters). - Initialization: Custom init logic runs:
- Methods annotated with
@PostConstructare executed first. - If the bean implements
InitializingBean,afterPropertiesSet()runs. - Any custom
init-methoddeclared in your configuration runs.
- Methods annotated with
- BeanPostProcessor (Post-Initialization): The
postProcessAfterInitialization()method executes. At this point, the bean is fully constructed, proxied, and ready for use. - Destruction: When the container closes, resources are cleaned up via
@PreDestroymethods or theDisposableBeaninterface'sdestroy()method.
Transaction Management & AOP
Q2: What happens under the hood when a method is annotated with @Transactional?
View Architectural Answer
Spring leverages Aspect-Oriented Programming (AOP) and Dynamic Proxies to manage declarative transactions.
- Proxy Creation: During application startup (the post-initialization phase of the bean lifecycle), Spring detects the
@Transactionalannotation. Instead of injecting your raw bean class instance directly into other classes, it generates a Dynamic Proxy wrapper around your bean (using standard JDK interfaces or CGLIB subclassing). - Interception: When another class invokes your transactional method, it actually calls the proxy wrapper first.
- Transaction Initialization: The proxy intercepts the call, opens a connection to the database using the configured
PlatformTransactionManager, disables auto-commit (connection.setAutoCommit(false)), and begins a native DB transaction. - Execution: The proxy delegates execution to your real business logic method.
- Outcome Resolution:
- Success: If your method finishes executing without throwing an unhandled exception, the proxy calls
connection.commit(). - Failure: If your method throws a
RuntimeExceptionor an explicitError, the proxy catches it and callsconnection.rollback(). Note: By default, checked exceptions do not trigger a rollback unless explicitly configured via@Transactional(rollbackFor = Exception.class).
- Success: If your method finishes executing without throwing an unhandled exception, the proxy calls
- Resource Cleanup: The proxy closes or returns the database connection back to the connection pool (like HikariCP).