Spring / Spring7 basics Interview questions
1. What is Spring Framework 7?
Spring Framework 7 is the current major generation of the Spring Framework, reaching general availability on November 13, 2025 alongside Spring Boot 4. It keeps Java 17 as its minimum baseline while fully supporting Java 25, the latest LTS release, so teams can use records, sealed classes, and pattern matching without being forced onto a new JDK immediately.
On the server side, it aligns with Jakarta EE 11 (Servlet 6.1, WebSocket 2.2, Bean Validation 3.1, JPA 3.2), which means deployment now targets Tomcat 11+ or Jetty 12.1+. New capabilities include built-in API versioning, JSpecify-based null safety, a programmatic BeanRegistrar contract, and stronger AOT/GraalVM native image support.
2. What is the minimum Java version required by Spring Framework 7?
Spring Framework 7 keeps Java 17 as its minimum supported version, the same baseline Spring 6 introduced back in 2022. This was a deliberate, pragmatic choice: rather than forcing every team onto the newest JDK the moment a major Spring version ships, the framework lets you stay on a widely adopted LTS release.
At the same time, Spring Framework 7 fully supports and recommends Java 25, the newest LTS, so applications that do upgrade can take advantage of virtual threads, the Class-File API, and other modern JVM improvements. Java 11 and earlier are no longer supported at all, and Spring Boot 4 follows the same Java 17 floor.
3. What is Jakarta EE 11 support in Spring Framework 7?
Spring Framework 7 migrates its enterprise APIs from Jakarta EE 10 to Jakarta EE 11. In practice this raises the baseline to Servlet 6.1, WebSocket 2.2, Bean Validation 3.1, and JPA 3.2, replacing the older generations that Spring 6 relied on.
Because these specifications moved forward, the servlet containers you deploy to must move forward too - Spring Framework 7 applications need Tomcat 11+ or Jetty 12.1+. JPA 3.2 is only a minor version bump on paper, but it effectively requires Hibernate ORM 7, which is a much bigger upgrade for most existing projects than the spec number suggests.
4. What is Inversion of Control in Spring?
Inversion of Control (IoC) is the design principle where an object no longer creates or looks up its own collaborators; instead, control over object creation and wiring is handed to a container. In a plain Java program, a class typically instantiates the objects it depends on with new. Under IoC, that responsibility moves outward to the Spring container.
Spring implements IoC through its IoC container, represented by the BeanFactory and ApplicationContext interfaces, which read configuration (annotations, Java config, or XML) and construct, configure, and manage the lifecycle of every bean. The main benefit is loose coupling: classes depend on abstractions rather than concrete implementations, which makes code easier to test, swap, and extend.
5. What is Dependency Injection in Spring?
Dependency Injection (DI) is the specific technique Spring uses to implement IoC: rather than a bean looking up or constructing the objects it needs, the container "injects" those dependencies into it, usually through a constructor, a setter, or a field.
For example, an OrderService that needs a PaymentGateway simply declares a constructor parameter of that type; Spring resolves a matching bean and passes it in automatically. This keeps classes free of wiring logic and lookup code, so the service never calls new StripeGateway() directly - it just asks for a PaymentGateway and trusts the container to supply one, which makes swapping implementations or mocking dependencies in tests straightforward.
6. What are the types of Dependency Injection in Spring?
Spring supports three main styles of injecting dependencies into a bean, and picking the right one affects testability and immutability.
| Type | How it works |
| Constructor injection | Dependencies passed as constructor arguments; recommended default, supports immutable, non-null fields |
| Setter injection | Dependencies assigned via setter methods; useful for optional dependencies |
| Field injection | @Autowired applied directly to a field; concise but harder to test and discouraged for production code |
Spring's own team recommends constructor injection as the default since it makes dependencies explicit and required, allows fields to be marked final, and works cleanly with plain unit tests that don't need a container.
7. What is an ApplicationContext?
An ApplicationContext is Spring's central interface for the IoC container - it extends BeanFactory and adds enterprise features on top of basic bean wiring. It reads bean definitions (from annotations, Java @Configuration classes, or XML), creates and wires the beans, and manages their full lifecycle.
Beyond dependency injection, an ApplicationContext provides event publication (ApplicationEventPublisher), internationalization support via MessageSource, environment and property resolution, and automatic registration of BeanPostProcessors. Common implementations include AnnotationConfigApplicationContext for Java-based configuration, and in a Spring Boot app the context is created and refreshed automatically at startup.
8. What is a BeanFactory in Spring?
BeanFactory is the root interface of Spring's IoC container - it defines the core contract for holding bean definitions and producing bean instances on request, including support for dependency injection, bean scopes, and lifecycle callbacks. It is intentionally minimal and lightweight compared to ApplicationContext.
In practice, almost no application code uses BeanFactory directly anymore. ApplicationContext is a subinterface that adds AOP integration, event handling, and easier configuration, so it's the interface every Spring Boot or Spring MVC application actually works with. BeanFactory still matters conceptually because it's where lazy bean instantiation and the basic getBean() contract are defined.
9. What are Spring beans?
A Spring bean is simply an object whose creation, configuration, and lifecycle are managed by the Spring IoC container instead of being managed manually by application code. Any plain Java object can become a bean once it's registered with the container, whether through a stereotype annotation like @Component, an explicit @Bean method in a @Configuration class, or XML configuration.
Once registered, the container is responsible for instantiating the bean, injecting its dependencies, applying any BeanPostProcessor logic, and eventually destroying it when the context closes. Beans are identified by a unique name or ID within the container, and by default each singleton-scoped bean is created once and shared everywhere it's injected.
10. What are the types of bean scopes in Spring?
Bean scope defines how many instances of a bean the container creates and how long each one lives.
| Scope | Lifetime |
| singleton | One shared instance per container (the default) |
| prototype | A new instance every time the bean is requested |
| request | One instance per HTTP request (web-aware contexts) |
| session | One instance per HTTP session |
| application | One instance per ServletContext |
singleton and prototype are always available; request, session, and application only apply in a web-aware ApplicationContext. Scope is set with @Scope("prototype") or the equivalent XML attribute.
11. What is the purpose of the @Component annotation?
@Component marks a plain Java class as a candidate for auto-detection during component scanning, so Spring registers it as a bean without any explicit @Bean method or XML entry. It's the most generic stereotype annotation in the framework.
@Component public class SlugGenerator { public String slugify(String input) { return input.toLowerCase().replace(" ", "-"); } }
When @ComponentScan (added automatically by @SpringBootApplication) scans the package tree, it finds every class annotated with @Component or one of its specializations - @Service, @Repository, @Controller - and registers each as a singleton bean by default, ready to be injected wherever it's needed.
12. What is the purpose of the @Autowired annotation?
@Autowired tells the Spring container to automatically resolve and inject a matching bean into a constructor, setter, or field. Spring first tries to match by type; if more than one bean of that type exists, it falls back to matching by the parameter or field name, or you can disambiguate with @Qualifier.
@Component public class ReportService { private final EmailSender sender; @Autowired public ReportService(EmailSender sender) { this.sender = sender; } }
On a single-constructor class, @Autowired is actually optional since Spring 4.3 - the container uses that constructor implicitly. It's still commonly written for clarity, and remains required when a class defines multiple constructors.
13. What is the purpose of the @Configuration annotation?
@Configuration marks a class as a source of bean definitions written in plain Java rather than XML. Spring processes the class specially so that any @Bean methods inside it are only ever invoked once per container, even if one @Bean method calls another directly - the container intercepts the call and returns the existing singleton instance.
@Configuration public class AppConfig { @Bean public Clock systemClock() { return Clock.systemUTC(); } }
This behavior relies on CGLIB subclassing the configuration class at startup, which is why @Configuration classes cannot be declared final. It's the modern, type-safe replacement for the XML beans file used in older Spring applications.
14. What is the purpose of the @Bean annotation?
@Bean is applied to a method inside a @Configuration (or @Component) class to tell Spring that the method's return value should be registered and managed as a bean. It's typically used when you need to wire a third-party class you don't own, or when bean creation needs custom logic that a simple @Component can't express.
@Bean public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule()); return mapper; }
By default, the bean's name matches the method name (objectMapper here), though it can be overridden with @Bean(name = "..."). Unlike @Component, @Bean doesn't rely on classpath scanning - it's an explicit, imperative registration.
15. What are stereotype annotations in Spring?
Stereotype annotations are specialized forms of @Component that both register a class as a bean and communicate its architectural role to Spring and to other developers reading the code.
| Annotation | Role |
@Service | Business/service-layer logic |
@Repository | Data-access layer; enables automatic persistence exception translation |
@Controller / @RestController | Web layer handling HTTP requests |
Functionally, all of these behave like @Component for scanning purposes, but @Repository additionally activates Spring's PersistenceExceptionTranslationPostProcessor, converting low-level database exceptions into Spring's consistent DataAccessException hierarchy.
16. What is component scanning in Spring?
Component scanning is the process where Spring walks a specified package (and its sub-packages) at startup, looking for classes annotated with @Component or one of its stereotypes, and automatically registers each one as a bean - no manual @Bean method needed for every class.
@SpringBootApplication // implies @ComponentScan on the current package public class ShopApplication { public static void main(String[] args) { SpringApplication.run(ShopApplication.class, args); } }
It's triggered by @ComponentScan, which @SpringBootApplication already includes by default, scoped to the package the main class lives in and everything beneath it. Classes outside that package tree are simply invisible to the scan unless the base package is widened explicitly.
17. What is the BeanRegistrar contract introduced in Spring Framework 7?
BeanRegistrar is a new programmatic bean-registration contract added in Spring Framework 7 that gives developers a cleaner, code-first alternative to cramming complex registration logic into @Bean methods. Spring's own guidance discourages registering several beans from a single @Bean method or returning a broad supertype, since that limits flexibility - BeanRegistrar exists precisely for the cases those rules get in the way of.
class MetricsRegistrar implements BeanRegistrar { @Override public void register(BeanRegistry registry, Environment env) { registry.registerBean("meterRegistry", MeterRegistry.class, spec -> spec.supplier(ctx -> new SimpleMeterRegistry())); } }
It's especially useful for conditional or dynamic bean registration, such as registering a different set of beans depending on active profiles or discovered configuration.
18. What is JSpecify in Spring Framework 7?
JSpecify is a community-standard set of nullability annotations (like @Nullable and @NonNull) that Spring Framework 7 has adopted in place of its own previous nullability annotations. The goal is a single, tool-agnostic way to declare which parameters, fields, and return types can be null.
import org.jspecify.annotations.Nullable; public interface UserLookup { @Nullable User findByEmail(String email); }
Because JSpecify is shared across the Java ecosystem, IDEs and static analysis tools understand it consistently, and Kotlin interoperates with it more precisely than it did with Spring's older annotations. Migrating brings some nullability behavior changes, since Spring 7 only checks annotations declared locally rather than inherited ones.
19. What is the purpose of the @Value annotation?
@Value injects a single value - typically read from application properties, environment variables, or a PropertySource - directly into a field, constructor parameter, or setter, using ${...} placeholder syntax. It also supports Spring Expression Language (SpEL) for simple computed defaults.
@Component public class MailConfig { @Value("${mail.retry.count:3}") private int retryCount; }
In the example above, if mail.retry.count isn't defined in application.properties, Spring falls back to the default value 3 after the colon. @Value is convenient for individual settings, but when a whole group of related properties needs binding, @ConfigurationProperties on a dedicated class is the more maintainable choice.
20. What are Spring profiles?
Profiles let you group beans and configuration so that only a chosen subset is active for a given environment - typically dev, test, and prod. A bean marked with @Profile("dev") is only registered when the dev profile is active; it's completely invisible to the container otherwise.
@Bean @Profile("dev") public DataSource devDataSource() { return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build(); }
Active profiles are set via the spring.profiles.active property, an environment variable, or a command-line argument, and multiple profiles can be active at once. This is commonly combined with profile-specific property files, such as application-dev.properties, so each environment gets its own configuration without touching code.
21. Define a Spring Boot starter?
A Spring Boot starter is a curated dependency descriptor - just a Maven or Gradle artifact with no code of its own - that pulls in a coherent set of libraries known to work well together for a particular purpose, so you don't have to hand-pick and version-match each one yourself.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
Adding spring-boot-starter-web, for example, brings in Spring MVC, an embedded Tomcat server, and Jackson for JSON, all at compatible versions. Starters exist for data access (spring-boot-starter-data-jpa), security, testing, and dozens of other concerns, and each one usually triggers related auto-configuration once it's on the classpath.
22. What is auto-configuration in Spring Boot 4?
Auto-configuration is Spring Boot's mechanism for guessing and applying sensible default configuration based on what's found on the classpath and in the ApplicationContext, so you don't have to wire common beans by hand. If Boot detects an embedded database driver and no DataSource bean, for instance, it configures one automatically.
@SpringBootApplication public class ShopApplication { } // @SpringBootApplication = @Configuration + @ComponentScan + @EnableAutoConfiguration
Each auto-configuration class is heavily guarded with conditional annotations like @ConditionalOnClass and @ConditionalOnMissingBean, so it backs off the moment you define your own equivalent bean. This "convention over configuration" approach is what lets a Spring Boot 4 project start from almost zero manual setup.
23. What is the DispatcherServlet in Spring MVC?
DispatcherServlet is the single front controller that every incoming HTTP request in a Spring MVC application passes through first. It doesn't contain business logic itself; instead it coordinates the whole request-handling pipeline - consulting handler mappings, invoking interceptors, calling your controller method, and choosing how to render the result.
flowchart LR
A[HTTP Request] --> B[DispatcherServlet]
B --> C[HandlerMapping]
C --> D[Controller method]
D --> E[ViewResolver or Message Converter]
E --> F[HTTP Response]
In a Spring Boot app, DispatcherServlet is registered and configured automatically by auto-configuration, mapped to / by default. For a @RestController, it skips view resolution entirely and hands the return value straight to an HttpMessageConverter to be written as JSON or another format.
24. What is a RestController in Spring MVC?
@RestController is a convenience annotation combining @Controller and @ResponseBody, meaning every handler method's return value is written directly to the HTTP response body - typically serialized to JSON by Jackson - instead of being resolved to a view template.
@RestController @RequestMapping("/api/books") public class BookController { @GetMapping("/{id}") public Book getBook(@PathVariable Long id) { return bookService.findById(id); } }
Without @RestController (using plain @Controller instead), returning a Book object from a method annotated only with @GetMapping would be treated as a view name to resolve, which usually isn't what you want for a REST API. @RestController is the standard choice for building JSON-based backend services.
25. What is API Versioning support in Spring Framework 7?
Spring Framework 7 adds native, declarative API versioning through a new version attribute on @RequestMapping and its shortcuts like @GetMapping, removing the need for the URL-prefix or custom-header hacks teams used before.
@RestController @RequestMapping("/products") public class ProductController { @GetMapping(version = "1") public List<Product> listV1() { /* ... */ } @GetMapping(version = "2") public List<Product> listV2() { /* ... */ } }
Spring supports resolving the requested version from a header, a path segment, a query parameter, or media type, and the same version attribute works on @HttpExchange clients, RestClient, WebClient, and testing utilities like RestTestClient, so client and server stay consistent end to end.
26. What are the types of HTTP message converters in Spring?
HttpMessageConverter implementations translate between Java objects and HTTP request/response bodies, choosing a converter based on content type and target Java type.
| Converter | Handles |
MappingJackson2HttpMessageConverter | JSON via Jackson |
StringHttpMessageConverter | Plain text bodies |
FormHttpMessageConverter | URL-encoded form data |
MultipartHttpMessageConverter | Multipart payloads (dedicated converter as of Spring 7.1) |
ResourceHttpMessageConverter | Raw byte/resource content, such as file downloads |
Spring auto-registers a sensible default list, and you can add or replace converters through WebMvcConfigurer#extendMessageConverters when a project needs a custom format.
27. Describe the RestClient in Spring Framework 7?
RestClient is Spring's modern, fluent HTTP client for synchronous calls, offering a chainable API that's more concise than the older RestTemplate while staying blocking and easy to reason about (unlike the reactive WebClient).
RestClient client = RestClient.create("https://api.example.com"); Product product = client.get() .uri("/products/{id}", 42) .retrieve() .body(Product.class);
As of Spring Framework 7.1, RestTemplate is formally deprecated in favor of RestClient, with actual removal planned for a future Spring 8 release. RestClient also understands the framework's API versioning attribute, so a request can target a specific server-side API version through the same declarative mechanism used on controllers.
28. What is the purpose of HTTP Interface clients in Spring?
HTTP Interface clients let you declare a remote service as a plain Java interface annotated with @HttpExchange (and its @GetExchange, @PostExchange shortcuts), and Spring generates a working proxy implementation at runtime - no boilerplate client code to write by hand.
@HttpExchange("/accounts") public interface AccountClient { @GetExchange("/{id}") Account getAccount(@PathVariable int id); }
Behind the scenes, the generated proxy delegates to an underlying RestClient or WebClient, so it inherits whatever interceptors, error handling, and API-versioning configuration that client has. This declarative style mirrors how @FeignClient works in Spring Cloud, but it's built directly into core Spring, with no extra dependency required.
29. What are the types of Spring AOP advice?
Advice is the action Spring AOP takes at a matched join point. Spring supports five advice types, each firing at a different moment relative to the method call.
| Advice | Fires |
@Before | Before the method executes |
@AfterReturning | After the method returns successfully |
@AfterThrowing | After the method throws an exception |
@After | Regardless of outcome (like finally) |
@Around | Wraps the method; can control if/when it runs |
@Around is the most powerful since it receives a ProceedingJoinPoint and decides whether to call the target method at all, but the other four are simpler to reason about for straightforward logging or validation use cases.
30. Define an Aspect in Spring AOP?
An Aspect is a module that captures a cross-cutting concern - logic like logging, security checks, or transaction handling that would otherwise be scattered across many unrelated classes - and applies it declaratively at defined points in the program, called join points.
@Aspect @Component public class LoggingAspect { @Before("execution(* com.shop.service.*.*(..))") public void logCall(JoinPoint jp) { System.out.println("Calling: " + jp.getSignature()); } }
An aspect is defined by combining a pointcut expression, which selects which join points to match, with advice, which is the code to run at those points. Spring implements aspects using proxies by default, so AOP only intercepts calls that go through a Spring-managed bean reference, not internal method-to-method calls within the same class.
31. What is the purpose of the @Transactional annotation?
@Transactional wraps a method (or every public method in a class) in a database transaction managed by Spring, automatically committing on success and rolling back on an unchecked exception, without you writing any manual begin/commit/rollback calls.
@Service public class TransferService { @Transactional public void transfer(Account from, Account to, BigDecimal amount) { from.debit(amount); to.credit(amount); } }
By default, it only rolls back on unchecked (RuntimeException) exceptions, not checked ones, unless you explicitly configure rollbackFor. Like AOP advice generally, @Transactional relies on proxying, so calling an annotated method from another method in the same class bypasses the proxy and the transaction never actually starts.
32. What are the types of transaction propagation in Spring?
Propagation defines how a @Transactional method behaves when it's called while a transaction is already in progress.
| Propagation | Behavior |
REQUIRED (default) | Joins the existing transaction, or starts a new one if none exists |
REQUIRES_NEW | Always suspends any existing transaction and starts a fresh one |
NESTED | Starts a savepoint within the existing transaction |
SUPPORTS | Joins a transaction if one exists; otherwise runs non-transactionally |
MANDATORY | Requires an existing transaction; throws an exception if none exists |
REQUIRES_NEW is useful when you need an inner operation, like audit logging, to commit independently of whether the outer transaction eventually rolls back.
33. Describe AOT processing in Spring Framework 7?
Ahead-of-Time (AOT) processing shifts work that Spring normally does at runtime - resolving conditions, computing bean definitions, generating proxy classes - to build time instead. During the build, Spring analyzes the application context and generates Java source and bytecode that reproduce that same context far faster, without needing reflection-heavy startup logic.
mvn -Pnative spring-boot:build-image
The immediate payoff is dramatically faster startup and lower memory use, since the container doesn't have to reason things out dynamically every time the JVM boots. AOT processing is also the foundation that makes GraalVM native image compilation possible, because native images can't rely on the reflection and dynamic class loading a normal JVM startup would use.
34. What is GraalVM native image support in Spring Framework 7?
GraalVM native image support lets a Spring Framework 7 application be compiled ahead of time into a standalone native executable, rather than running as bytecode inside a JVM. The result starts in milliseconds and uses a fraction of the memory of a regular JVM process, which is valuable for serverless functions and container-dense deployments.
./mvnw -Pnative native:compile
Because native images can't perform arbitrary reflection or dynamic class loading at runtime, Spring relies on its AOT processing step to precompute everything the native compiler needs to know up front - which beans exist, which proxies to generate, and which classes need reflective access - and feeds that information to the GraalVM compiler during the build.
35. What is virtual thread support in Spring Framework 7?
Virtual threads, a JVM feature from Project Loom, are lightweight threads that the JVM schedules onto a small pool of OS threads, letting an application handle enormous numbers of concurrent blocking calls without the memory overhead of one OS thread per request. Spring Framework 7 lets a traditional Spring MVC application run its request-handling on virtual threads instead of a fixed platform-thread pool.
spring.threads.virtual.enabled=true
Because virtual threads are cheap to create and block, this can dramatically improve throughput for I/O-bound MVC applications - the kind that spend most of their time waiting on a database or a downstream HTTP call - without rewriting the code in a reactive style using WebFlux.
36. What is the purpose of a PropertySource in Spring?
A PropertySource represents a single origin of key-value configuration - a .properties file, a .yml file, environment variables, or command-line arguments - that Spring's Environment abstraction merges together into one searchable set of properties.
@Configuration @PropertySource("classpath:mail.properties") public class MailConfig { @Value("${mail.host}") private String host; }
When several sources define the same key, Spring resolves it using a defined precedence order - command-line arguments and environment variables typically outrank values in application.properties. This layered model is what lets the exact same code read different settings in development, testing, and production without any code changes.
37. List the core modules of Spring Framework 7?
Spring Framework 7 is organized into a set of well-defined modules, and applications typically pull in only the ones they need.
- spring-core / spring-beans - the IoC container and dependency injection fundamentals
- spring-context - ApplicationContext, events, internationalization
- spring-aop - aspect-oriented programming support
- spring-web / spring-webmvc - servlet-based MVC and REST support, including DispatcherServlet
- spring-webflux - reactive, non-blocking web support
- spring-tx - transaction management abstractions
- spring-orm - integration with JPA and Hibernate
- spring-test - testing utilities such as MockMvc and RestTestClient
Spring Boot's starters map closely onto these modules, so choosing spring-boot-starter-webflux instead of spring-boot-starter-web, for example, is really choosing spring-webflux over spring-webmvc underneath.
38. Define a Spring MVC ViewResolver?
A ViewResolver maps the logical view name a controller returns (like "productList") to an actual renderable View object, such as a JSP, Thymeleaf template, or another template engine's output. It's only invoked for traditional server-rendered controllers, not @RestController endpoints.
@Controller public class ProductPageController { @GetMapping("/products") public String list(Model model) { model.addAttribute("products", productService.findAll()); return "productList"; // resolved by a ViewResolver } }
Spring Boot auto-configures a ViewResolver matching whatever templating starter is on the classpath - spring-boot-starter-thymeleaf, for instance, wires up ThymeleafViewResolver automatically, prefixing and suffixing the returned name to locate the actual template file.
39. What is the purpose of ResponseEntity?
ResponseEntity<T> represents a complete HTTP response - status code, headers, and body - giving a controller method full control over what's sent back, rather than just returning a body and letting Spring pick a default 200 OK status.
@GetMapping("/{id}") public ResponseEntity<Product> getProduct(@PathVariable Long id) { Product product = productService.findById(id); if (product == null) { return ResponseEntity.notFound().build(); } return ResponseEntity.ok(product); }
This is especially useful for returning 404 Not Found, 201 Created with a Location header after a POST, or custom headers like caching directives. Returning a plain Product object instead always yields 200 OK, so ResponseEntity is the standard tool whenever the status code itself needs to vary.
40. Describe the Spring Bean lifecycle basics?
Every Spring bean moves through a predictable sequence of stages between creation and destruction, and the container exposes hook points at several of them for custom logic.
flowchart TD
A[Instantiate bean] --> B[Populate properties / inject dependencies]
B --> C[BeanNameAware, BeanFactoryAware callbacks]
C --> D[BeanPostProcessor - before init]
D --> E["@PostConstruct / afterPropertiesSet"]
E --> F[BeanPostProcessor - after init]
F --> G[Bean ready for use]
G --> H["@PreDestroy / destroy on context close"]
Constructor injection happens first, followed by any setter or field injection. Then Spring calls Aware interfaces if implemented, runs BeanPostProcessors before and after any @PostConstruct method, and finally the bean sits ready until the container shuts down and calls @PreDestroy - only for singleton beans, since prototype beans aren't tracked for destruction.
