Master Spring interview answers for Boot 3 and Spring 6, covering Java 17, Jakarta migrations, autoconfiguration, and production tradeoffs.
Most candidates preparing for a Spring backend interview study the same thing: a definition list. IoC means inversion of control. DI means dependency injection. ApplicationContext is a BeanFactory with extra features. If you can framework spring interview questions at that level, you'll pass a 2018 screen. You won't pass a modern one.
The gap isn't vocabulary. It's that Spring Boot 3 and Spring 6 changed the baseline assumptions — Jakarta namespaces, Java 17 as the minimum, revised autoconfiguration mechanics, and a hiring bar that now expects candidates to connect framework knowledge to what actually breaks in production. Interviewers at companies shipping real backend services aren't looking for someone who can recite the container lifecycle. They're looking for someone who has debugged a transaction boundary, reasoned about proxy limits, or migrated a javax import. That's a different kind of preparation.
This article is organized around the questions that actually come up, what a good answer looks like now versus what it looked like before Boot 3, and where the follow-ups live. Work through it before your next backend interview.
Why Spring interview answers changed with Boot 3 and Spring 6
The old definition-only answer is now a red flag
There's a specific kind of Spring interview answer that used to be acceptable and now signals that you haven't touched the framework recently. It sounds like this: "Spring provides inversion of control through dependency injection, which decouples components and improves testability." That sentence is true. It's also the answer that approximately every candidate gives, and it tells the interviewer nothing about whether you can ship code.
The shift happened because Spring Boot 3 interview questions are increasingly about behavior, not vocabulary. What does autoconfiguration actually do when two beans conflict? How does a transactional method behave when called from the same class? What breaks when you upgrade from javax to Jakarta? These questions don't have definition-shaped answers. They have "I've seen this fail" answers.
What changed when Jakarta and Java 17 became the floor
Spring Boot 3.0 requires Java 17 and migrated entirely from the `javax.` namespace to `jakarta.`. This isn't a cosmetic change. Any application importing `javax.persistence`, `javax.servlet`, or `javax.validation` needs a full package rename. The Spring 6 interview reality is that interviewers at companies running modern stacks will ask whether you've done this migration or at least understand what it involves. Candidates who answer Spring questions using pre-Boot 3 assumptions — referencing the old namespace, assuming Java 8 compatibility, or describing deprecated configuration patterns — immediately signal that their experience is dated.
Java 17 as the baseline also matters because it changes what's idiomatic. Records, sealed classes, and text blocks are now fair game in Spring component design, and interviewers at senior levels may ask how you'd use them.
What this looks like in practice
A common interview question: "How does Spring manage beans?" The legacy answer describes XML configuration, maybe mentions component scanning, and stops at the container. The Boot 3 answer covers conditional autoconfiguration, starter-driven defaults, the shift to `@SpringBootApplication`, and the fact that most beans in a modern app are wired without explicit `@Bean` declarations. One answer sounds like a textbook. The other sounds like someone who has opened a Boot 3 project recently.
A candidate I know lost a senior backend role by confidently explaining Spring Security configuration using `WebSecurityConfigurerAdapter` — which was deprecated in Spring 5.7 and removed in Spring 6. The interviewer asked a follow-up about the current approach. Silence. That one answer cost the offer.
Answer Spring Core interview questions like someone who has used the container
BeanFactory vs ApplicationContext is not just a trivia question
The textbook answer is that `ApplicationContext` extends `BeanFactory` and adds more features. That's true and nearly useless. What interviewers want to hear is what those features actually mean in a running application.
`BeanFactory` is lazy by default — beans are created when first requested. `ApplicationContext` eagerly instantiates singleton beans at startup, which means startup failures surface immediately rather than at first call. In production, that's almost always what you want. `ApplicationContext` also provides event publishing, internationalization support, and integration with Spring's AOP infrastructure. In practice, you will never use a raw `BeanFactory` in a Spring Boot application. Knowing why — not just that — is what separates a real answer from a memorized one. Reference the Spring container documentation for the full context hierarchy.
Scopes, lifecycle, and why singleton does not mean one object everywhere
Singleton scope means one instance per Spring container, not one instance per JVM. If you have two application contexts — which happens in test environments — you have two singleton instances of the same bean. Candidates who treat singleton as a global guarantee get caught by this in test isolation questions.
The thread-safety trap is the more common interview pitfall. A singleton bean is shared across all threads. If it holds mutable state — a counter, a cached result, a user-specific value — you have a race condition. The correct answer is that singleton beans should be stateless, and any state that varies per request belongs in a request-scoped bean or a local variable.
Lifecycle callbacks are worth knowing at the level of `@PostConstruct` and `@PreDestroy`. These are the hooks that run after dependency injection completes and before the bean is destroyed, respectively. Interviewers sometimes ask how you'd initialize a connection pool or close a resource cleanly — these are the answers.
What this looks like in practice
A stateless `UserService` is the canonical singleton: it holds a reference to a repository, does work, returns results. No state leaks between requests. A shopping cart bean that holds items for the current user is the canonical request-scoped bean — you'd annotate it `@RequestScope` and let Spring create a fresh instance per HTTP request. The bug that appears when someone makes a cart singleton is exactly the kind of real example interviewers are probing for. I've seen this exact mistake in a production app where cart items from one user bled into another user's session during load testing — the scope annotation was missing, and the singleton held mutable list state.
Treat dependency injection as a design choice, not a checkbox
Constructor injection is the default for a reason
Field injection with `@Autowired` is convenient. You skip the constructor, the class looks cleaner, and Spring handles the wiring. The problem is that the object can now be instantiated without its dependencies — which means your unit tests require a Spring context to work, or you have to use reflection to inject mocks. Setter injection is better: it at least allows injection without a container. But constructor injection is the answer that holds up because it makes dependencies explicit, enforces required collaborators at compile time, and works naturally with Lombok's `@RequiredArgsConstructor`.
Steelmanning field injection: in a prototype or a quick integration test, it's fine. The argument against it isn't moral — it's that it makes objects harder to test and easier to instantiate incorrectly. Spring's own documentation recommends constructor injection for required dependencies.
The follow-up question is really about testability and immutability
When an interviewer pushes on injection style, they're not testing syntax knowledge. They're asking: do you think about object design? Can you instantiate this class in a unit test without a container? Can this bean be in an invalid state after construction? Constructor injection answers all three questions correctly by default. A bean with all required dependencies in its constructor cannot be partially initialized. That's the immutability argument, and it's the answer that lands well.
What this looks like in practice
A `PaymentService` that requires a `PaymentGateway` and optionally accepts a `FraudCheckService` is the right example. The gateway is constructor-injected — it's required, and the service can't function without it. The fraud checker is setter-injected or `@Autowired(required = false)` — it's optional, and the service degrades gracefully without it. In a unit test, you pass a mock gateway directly to the constructor. No Spring context needed. When I refactored a service from field injection to constructor injection in a real project, three missing dependency bugs surfaced at compile time that had previously only appeared at runtime. That's the concrete payoff.
Know the proxy limits before you talk about circular dependencies
Why self-invocation keeps biting Spring apps
Spring AOP works by wrapping your bean in a proxy. When external code calls a method on your bean, it goes through the proxy, which applies the advice — `@Transactional`, `@Cacheable`, whatever you've declared. When a method inside the same bean calls another method on the same bean, it bypasses the proxy entirely. The advice never fires.
This is the self-invocation problem, and it's one of the most common sources of silent transaction failures in Spring apps. A developer adds `@Transactional` to a private helper method, calls it from a public method in the same class, and wonders why the transaction boundary isn't working. The answer is that `@Transactional` on a private method does nothing useful, and even on a public method, it only applies when called through the proxy. The Spring AOP documentation covers this explicitly.
Circular dependencies are a design smell, not a container party trick
Spring Boot 3 disabled circular dependency injection by default. If bean A depends on bean B and bean B depends on bean A, Boot 3 will fail at startup rather than silently resolving the cycle. This is the right behavior. Circular dependencies almost always indicate that responsibilities are mixed — the solution is a redesign, not a `@Lazy` annotation to paper over it.
Interviewers who ask about circular dependencies are checking whether you recognize the smell. The strong answer acknowledges that Spring can sometimes resolve cycles, explains why Boot 3 now rejects them by default, and proposes the refactor rather than the workaround.
What this looks like in practice
A `NotificationService` with a `@Transactional` method that calls a private `sendEmail()` method on the same class: the transaction works on the outer method because it's called through the proxy. The inner call is direct. If `sendEmail()` also needs transactional behavior, the correct fix is to extract it into a separate Spring-managed bean so the proxy chain is preserved. I've debugged exactly this scenario — a caching annotation on a method that was only ever called internally, and the cache was never populated. The fix was a three-minute extraction refactor. The debugging took two hours.
Explain Boot 3 autoconfiguration without hand-waving
Starters are packaging, autoconfiguration is behavior
A starter is a convenience dependency that pulls in a curated set of libraries. `spring-boot-starter-web` brings Tomcat, Spring MVC, and Jackson. That's packaging. Autoconfiguration is what happens after: Spring Boot reads the classpath, finds those libraries, and conditionally wires beans based on what's present and what you haven't overridden.
The mechanism is `@ConditionalOnClass`, `@ConditionalOnMissingBean`, and similar annotations on autoconfiguration classes. If Jackson is on the classpath and you haven't defined a custom `ObjectMapper`, Boot creates one for you. If you define your own, Boot backs off. This conditionality is the core of how Spring Boot auto-configuration works, and explaining it at this level is what separates a real answer from "Spring Boot configures things automatically."
Exclusions matter when defaults get in the way
Sometimes the default autoconfiguration creates a conflict. A common case: you're using Spring Boot with a test database for local development, but you want to disable the datasource autoconfiguration entirely in a specific profile. The mechanism is `@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})` or the `spring.autoconfigure.exclude` property. Knowing this exists — and more importantly, knowing why you'd reach for it — signals that you've worked with real Boot 3 projects.
What this looks like in practice
A project that includes `spring-boot-starter-data-jpa` will get a datasource autoconfigured from `application.properties`. If the database credentials aren't present, startup fails. A developer who wants to run the app without a database for a lightweight smoke test can exclude `DataSourceAutoConfiguration` and avoid the failure. In a real project I worked on, a starter was pulling in Flyway autoconfiguration that conflicted with a manual migration setup. Excluding `FlywayAutoConfiguration` and managing migrations explicitly resolved the startup conflict in under ten minutes once we understood what was happening.
Read DispatcherServlet and MVC annotations as a request flow, not a cheat sheet
DispatcherServlet is the traffic cop interviewers actually care about
Every HTTP request to a Spring MVC application hits `DispatcherServlet` first. It consults `HandlerMapping` to find the right controller method, delegates to `HandlerAdapter` to invoke it, and then passes the result to `ViewResolver` or writes directly to the response for REST endpoints. Understanding this pipeline means you can answer questions about request routing, exception handling, and response rendering without treating them as separate unrelated topics.
The interviewer asking "how does Spring MVC handle a request?" wants to hear this flow, not a list of annotations. The Spring MVC reference documentation describes the full dispatch sequence.
@RequestMapping, @RequestParam, and @PathVariable each answer a different question
`@RequestMapping` (and its shortcuts `@GetMapping`, `@PostMapping`, etc.) defines which URL pattern and HTTP method this controller method handles — it's the routing declaration. `@PathVariable` extracts a segment from the URL path itself: `/users/{id}` with `@PathVariable Long id` captures the ID as part of the resource identity. `@RequestParam` reads a query parameter from the URL: `/users?active=true` with `@RequestParam boolean active` reads the filter. These are not interchangeable, and treating them as syntax variants rather than conceptually distinct inputs is a common shallow answer.
What this looks like in practice
A REST endpoint `GET /orders/{orderId}/items?status=PENDING` uses both: `@PathVariable Long orderId` identifies which order, `@RequestParam String status` filters the results. The request hits `DispatcherServlet`, which matches the path to the handler via `RequestMappingHandlerMapping`, invokes the method via `RequestMappingHandlerAdapter`, and returns a `ResponseEntity` that Jackson serializes to JSON. Tracing this flow in a debugger — stepping through the dispatch chain — is how you build the mental model that makes interview answers feel lived-in rather than memorized.
Talk about transactions and AOP like you have debugged a real outage
AOP is not the point — the advice is the point
An aspect is a module that encapsulates cross-cutting behavior. A pointcut defines where it applies. Advice is what it does — `@Before`, `@After`, `@Around`. A join point is the specific execution point. Weaving is how the aspect gets applied. You need these terms, but only to the extent that they connect to observable behavior. Interviewers don't want a glossary recitation. They want to know what happens when advice fires, when it doesn't, and why.
Propagation and rollback are where the real Spring transaction interview starts
`@Transactional` with no arguments gives you `REQUIRED` propagation: join an existing transaction if one exists, start a new one if not. `REQUIRES_NEW` always starts a new transaction, suspending the outer one. This matters when you have an audit log write that should commit even if the main operation rolls back — you'd use `REQUIRES_NEW` for the audit method.
Rollback rules: by default, Spring rolls back on unchecked exceptions (`RuntimeException` and its subclasses) and does not roll back on checked exceptions. If your service throws a checked exception and you expect a rollback, you need `@Transactional(rollbackFor = MyCheckedException.class)`. Missing this is a real production bug that has caused partial writes in more than a few systems.
What this looks like in practice
A service method writes an order to one table and a payment record to another. If the payment write fails with a `RuntimeException`, the order write rolls back — correct. If the payment service throws a checked `PaymentException`, the order commits and the payment doesn't — silent partial write, data inconsistency. Adding `rollbackFor = PaymentException.class` fixes it. I've seen this exact pattern cause a production incident where orders appeared in the system with no associated payment record. The fix was a one-line annotation change. The discovery took a full incident review.
Use JPA, JdbcTemplate, and testing answers to signal backend depth
JpaRepository answers are easy to memorize and easy to expose
Derived query methods like `findByEmailAndActive` are convenient, but the follow-up question is always about what happens under the hood. Spring Data JPA translates the method name into JPQL, which the JPA provider (Hibernate, typically) translates to SQL. The N+1 problem surfaces when you load a list of entities and each entity triggers a separate query for its lazy-loaded associations. The fix is `@EntityGraph` or a JPQL join fetch. Candidates who can describe this — and explain why `FetchType.EAGER` is not the answer — signal real Spring Data JPA experience. Spring Data JPA documentation covers fetch strategies and repository behavior in detail.
JdbcTemplate still matters when you need control
`JpaRepository` is the right default for standard CRUD. `JdbcTemplate` is the right tool when you need a bulk insert, a complex native query, or explicit control over result mapping without the overhead of entity lifecycle management. Interviewers respect candidates who can articulate this tradeoff rather than treating JPA as the universal answer.
What this looks like in practice
A repository method `findAllByStatus(String status)` triggers a JPQL query and returns managed entities with lazy-loaded associations — convenient, but watch the N+1. A `JdbcTemplate` query with a `RowMapper` returns a plain list of DTOs with no entity lifecycle, no lazy loading, and predictable SQL. For a reporting query that aggregates across three tables, `JdbcTemplate` is almost always the cleaner choice. For testing, `@DataJpaTest` gives you a slice context with an in-memory database and only JPA infrastructure — no full application context needed, fast feedback, and clear scope.
Mention the Spring topics that make a hiring manager trust you faster
The candidate who can connect Spring to production wins
Knowing the framework is table stakes. What separates a strong backend candidate is the ability to connect Spring concepts to what actually happens in a running system — under load, during an upgrade, in a failing test. Interviewers are pattern-matching for this signal throughout the conversation. The candidates who get offers at mid-senior levels are the ones who volunteer production context without being asked.
Security, testing, and migration are the depth signals
Spring Security, slice testing, Jakarta migration, and Boot 3 defaults are the topics that consistently separate surface answers from strong backend signals. A candidate who can explain the Security filter chain, distinguish `@WebMvcTest` from `@SpringBootTest`, describe what a javax-to-jakarta migration involves, and explain why Boot 3 changed the default for circular dependencies — that candidate sounds like someone who has maintained a real application.
What this looks like in practice
When an interviewer asks "what Spring topics should we dig into next?" the strong answer is not "whatever you want." It's: "I'm comfortable with the container lifecycle, transaction management, and MVC request flow. If you want to go deeper, I'd suggest Spring Security filter chain configuration, test slice strategies, or Boot 3 migration patterns — those tend to surface the most interesting production tradeoffs." That answer signals range, confidence, and awareness of what actually matters in a backend role.
Frequently Asked Questions
Q: What Spring concepts are most likely to come up in a backend interview, and how should I answer them crisply?
The highest-frequency topics are IoC and DI mechanics, bean scopes and lifecycle, `@Transactional` behavior (especially propagation and rollback), autoconfiguration, and MVC request flow. Answer each by naming the mechanism, then immediately connecting it to a real behavior or failure mode — not just a definition. The follow-up is always "what goes wrong when this is misused?" so build that into your first answer.
Q: How do BeanFactory and ApplicationContext differ in practice, not just in definition?
`BeanFactory` creates beans lazily on first request; `ApplicationContext` eagerly instantiates singletons at startup, which surfaces wiring errors immediately. `ApplicationContext` also provides event publishing, AOP integration, and resource loading. In any Spring Boot application you will use `ApplicationContext` — the question is really asking whether you understand why eager initialization is the production-safe default.
Q: When should I prefer constructor injection over setter or field injection, and what follow-up questions do interviewers ask?
Constructor injection for required dependencies, setter injection for optional ones. The follow-up is almost always about testability: with constructor injection, you can instantiate the class in a unit test by passing mocks directly, no Spring context needed. Interviewers also ask about immutability — a constructor-injected bean's required dependencies are set once and cannot be null after construction.
Q: What bean-scope and thread-safety pitfalls should a backend candidate be ready to explain?
Singleton beans are shared across all threads, so mutable instance state causes race conditions. The fix is stateless design — push any request-specific state into method-local variables or a request-scoped bean. Also know that singleton means one instance per container, not per JVM — test contexts with multiple application contexts will have multiple singleton instances of the same bean.
Q: How does DispatcherServlet route requests, and what is the difference between @RequestMapping, @RequestParam, and @PathVariable?
`DispatcherServlet` receives every request, uses `HandlerMapping` to find the matching controller method, and delegates to `HandlerAdapter` to invoke it. `@RequestMapping` declares which URL pattern and HTTP method the method handles. `@PathVariable` extracts a segment from the URL path (resource identity). `@RequestParam` reads a query string parameter (filter or option). They answer different questions about the incoming request and are not interchangeable.
Q: What should I say about Spring Boot auto-configuration, starters, and embedded servers in a live interview?
Starters are dependency bundles; autoconfiguration is the conditional bean wiring that happens because of what's on the classpath. Spring Boot reads autoconfiguration classes annotated with `@ConditionalOnClass` and `@ConditionalOnMissingBean` to decide what to wire. If you've defined your own bean, Boot backs off. Embedded servers (Tomcat by default) are included via the web starter and configured via `application.properties` — no external server deployment needed.
Q: What AOP and transaction questions separate a junior answer from a mid-senior answer?
A junior answer covers `@Transactional` basics and maybe ACID. A mid-senior answer covers propagation modes (`REQUIRED` vs `REQUIRES_NEW`), rollback rules for checked exceptions, self-invocation proxy failures, and isolation levels and when to change them. The strongest answers include a concrete failure mode: "I've seen a partial write caused by a checked exception not triggering rollback — here's how I fixed it."
Q: Which Spring topics signal strong backend-engineering depth to a hiring manager?
Spring Security filter chain configuration, test slicing (`@WebMvcTest`, `@DataJpaTest`), Jakarta namespace migration, Boot 3 circular dependency behavior, and JPA fetch strategy tradeoffs. Volunteering these topics — especially with production context — signals that you've maintained a real application rather than just completed tutorials.
How Verve AI Can Help You Prepare for Your Interview With Spring Framework
The structural problem with Spring interview prep is that you can read every section of the documentation and still blank on the follow-up. The follow-up is where the interview actually happens — and it only works if you've rehearsed answering live, not just reading. That requires a tool that can respond to what you actually said, not a canned prompt.
Verve AI Interview Copilot is built for exactly that. It listens in real-time to your answers and responds to the specific thing you said — so when you explain `@Transactional` propagation and the follow-up asks about a partial write scenario, Verve AI Interview Copilot is already working from your answer, not a generic Spring question bank. You can run through the proxy self-invocation trap, the Jakarta migration angle, or the autoconfiguration exclusion case and get feedback that's specific to how you explained it, not just whether you mentioned the right keywords. Verve AI Interview Copilot stays invisible during practice so the session feels like the real thing, and it covers the full range of Spring topics — from bean lifecycle to transaction debugging to test slice strategy — so you're not rehearsing a subset of what might come up.
Conclusion
The goal was never to memorize more Spring words. It was to sound like someone who has shipped and debugged a Boot 3 application — someone who knows why constructor injection matters, what breaks when a proxy call stays inside the bean, and what propagation mode to reach for when an audit write needs to survive a rollback.
Before your next interview, pick one answer from each section and say it out loud. Not to yourself silently — out loud, as if the interviewer just asked. The gap between knowing the concept and being able to explain it under pressure is where most Spring interviews are actually won or lost.
James Miller
Career Coach

