{"id":1198,"date":"2026-07-16T22:45:45","date_gmt":"2026-07-16T17:15:45","guid":{"rendered":"https:\/\/lastroundai.com\/blog\/?post_type=iq&#038;p=1198"},"modified":"2026-07-19T10:54:07","modified_gmt":"2026-07-19T05:24:07","slug":"spring-boot","status":"publish","type":"iq","link":"https:\/\/lastroundai.com\/interview-questions\/spring-boot","title":{"rendered":"Spring Boot Interview Questions (2026): Most Asked, With Answers"},"content":{"rendered":"<p>A 3-year Java engineer at a Pune fintech got asked one question in June 2026 that decided the whole loop: why does the team&#8217;s style guide ban <code>@Autowired<\/code> on a field when every tutorial online does exactly that. She named the annotation correctly on the first pass. She couldn&#8217;t say why it&#8217;s discouraged, and the interviewer moved on without asking anything else. That&#8217;s usually where Spring Boot interviews actually live, not in whether you&#8217;ve seen an annotation before, in whether you know what it costs you.<\/p>\n<p>Spring Boot is used by 15.6 percent of professional developers according to the <a href=\"https:\/\/survey.stackoverflow.co\/2025\/technology\" target=\"_blank\" rel=\"noopener noreferrer\">2025 Stack Overflow Developer Survey<\/a>, and Java itself sits at 29.6 percent, eighth among languages, well behind JavaScript and Python but still ahead of Kotlin, Go, and Rust combined. That&#8217;s not a shrinking footprint. It&#8217;s an enormous, mostly-invisible one, since almost none of that usage shows up in flashy greenfield demos. Here&#8217;s an opinion that might be wrong: I think most spring boot interview questions still test whether you&#8217;ve memorized an annotation&#8217;s name, when the actual filter in a 2026 loop is whether you can explain what breaks when two of those annotations interact badly, a circular dependency, a self-invoked <code>@Transactional<\/code> method, an autoconfigured bean you never asked for.<\/p>\n<p>This page covers Spring Boot vs. the Spring Framework, autoconfiguration and starters, the IoC container and dependency injection, the annotations everyone lists but can&#8217;t always explain, REST APIs, Spring Data JPA, exception handling, profiles and config, Actuator, security, caching, microservices with Spring Cloud, and testing. It&#8217;s organized by topic, not company, since the same bean-scope question shows up almost verbatim whether you&#8217;re interviewing at a 200-person product company or a Bangalore IT-services shop staffing a banking client.<\/p>\n<div class=\"iq-stats not-prose\"><div class=\"iq-stat\"><span class=\"iq-stat__value\">52<\/span><span class=\"iq-stat__label\">Questions<\/span><\/div><div class=\"iq-stat\"><span class=\"iq-stat__value\">Auto-configuration &amp; DI<\/span><span class=\"iq-stat__label\">Core Topic<\/span><\/div><div class=\"iq-stat\"><span class=\"iq-stat__value\">Easy-Hard<\/span><span class=\"iq-stat__label\">Coding Level<\/span><\/div><div class=\"iq-stat\"><span class=\"iq-stat__value\">Fresher-Senior<\/span><span class=\"iq-stat__label\">Experience Range<\/span><\/div><\/div>\n<h2>Spring vs. Spring Boot: what actually changed<\/h2>\n<p>Almost every loop opens here, and a shaky answer sets a bad tone for everything after it, even at the senior level.<\/p>\n<div class=\"iq-dsec iq-dsec--easy\"><div class=\"iq-dsec__row\"><h2 class=\"iq-dsec__h\" id=\"easy\"><span class=\"iq-dsec__dot\" aria-hidden=\"true\"><\/span>Easy questions<\/h2><span class=\"iq-dsec__n\">19<\/span><\/div><div class=\"iq-dsec__bar\" aria-hidden=\"true\"><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">What&#039;s actually different between the Spring Framework and Spring Boot?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Fundamentals<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>The Spring Framework is the underlying platform: the IoC container, dependency injection, AOP, and modules like Spring MVC and Spring Data that you wire together yourself, usually with a fair amount of XML or Java config. Spring Boot is built on top of that same framework. It doesn&#8217;t replace anything underneath, it adds autoconfiguration, starter dependencies, an embedded server (Tomcat by default), and a set of sane defaults so you can run a working application from a single main method instead of assembling a web.xml and a dispatcher servlet by hand.<\/p>\n<p>Every Spring Boot bean you use is still a plain Spring bean, managed by the same IoC container. Boot&#8217;s job is deciding what to wire for you automatically, not changing how the container itself works.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">Is Spring Boot just &#039;Spring with less XML,&#039; or is that undercutting what it actually does?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Fundamentals<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>It undercuts it. Less XML is a side effect, not the point. The real shift is autoconfiguration deciding, at startup, which beans your classpath actually needs, and an embedded server meaning you ship a runnable JAR instead of a WAR dropped into a separately-managed Tomcat instance.<\/p>\n<p>Plenty of plain-Spring shops had already killed most of their XML with Java-based <code>@Configuration<\/code> classes years before Boot existed. What Boot actually changed was removing the &#8220;assemble it yourself&#8221; step entirely for the 80 percent case, and giving you an escape hatch for the other 20.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">Your main class has one annotation, @SpringBootApplication. What&#039;s actually bundled inside it?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Fundamentals<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>It&#8217;s a meta-annotation stacking three separate ones. <code>@SpringBootConfiguration<\/code> is a specialized <code>@Configuration<\/code>, so the class itself can define <code>@Bean<\/code> methods. <code>@EnableAutoConfiguration<\/code> triggers the whole conditional-bean process covered below. <code>@ComponentScan<\/code> scans the current package and everything underneath it for <code>@Component<\/code>, <code>@Service<\/code>, <code>@Repository<\/code>, and <code>@Controller<\/code> classes.<\/p>\n<p>Drop your main class into a package that&#8217;s a sibling of your feature packages rather than their parent, and <code>@ComponentScan<\/code> quietly stops finding half your beans, since it only scans downward from wherever the annotated class actually lives. That&#8217;s a real gotcha on large multi-module projects, not just an edge case someone made up for an interview.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">What do CommandLineRunner and ApplicationRunner actually do, and why would you pick one over the other?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Fundamentals<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Both let you run code once, right after the application context finishes loading and before Boot considers the app started. Implement either interface as a bean and Spring calls its single method automatically on startup, no manual wiring required. The only real difference is the method signature: <code>CommandLineRunner.run()<\/code> takes a raw <code>String[]<\/code> of command-line arguments, <code>ApplicationRunner.run()<\/code> takes an <code>ApplicationArguments<\/code> object that already parses <code>--key=value<\/code> style options into named and non-named groups for you.<\/p>\n<p>I default to ApplicationRunner unless I&#8217;m specifically parsing positional arguments, since the parsed accessor methods save you from splitting strings by hand. Multiple runner beans in the same app execute in the order <code>@Order<\/code> specifies, or declaration order if nobody bothered to annotate them.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">What is a starter dependency, and what&#039;s actually inside one?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Starters<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>A starter is a curated dependency descriptor, a Maven or Gradle artifact that pulls in a whole cluster of libraries known to work well together, instead of you hand-picking every JAR and hoping the versions don&#8217;t clash.<\/p>\n<p><code>spring-boot-starter-web<\/code> pulls in Spring MVC, Jackson for JSON, an embedded Tomcat, and Bean Validation. <code>spring-boot-starter-data-jpa<\/code> pulls in Hibernate, Spring Data JPA, Spring ORM, and HikariCP (the default connection pool since Boot 2.0). The starter itself has almost no code in it, its real job is a dependency-management pom that pins compatible versions so you don&#8217;t end up with a Hibernate build that silently breaks against a newer Spring release.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">Constructor injection vs. field injection: which do you actually use, and why does it matter?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Dependency Injection<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Constructor injection. Dependencies become <code>final<\/code> and immutable, the class is trivially testable by just calling the constructor with mocks (no Spring context required at all), and a missing dependency fails loudly at application startup instead of surfacing as a <code>NullPointerException<\/code> three requests into production.<\/p>\n<p>Field injection, the <code>@Autowired<\/code>-on-a-field pattern almost every beginner tutorial teaches first, hides the dependency list from anyone reading the class and makes it impossible to construct the object without reflection or a container. IntelliJ&#8217;s own built-in inspection flags it the moment you type it: &#8220;Field injection is not recommended.&#8221; Since Spring 4.3, if a class has exactly one constructor, <code>@Autowired<\/code> on it is optional. Spring wires it implicitly either way.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">@RequestParam, @PathVariable, @RequestBody: what&#039;s each one actually for?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">REST APIs<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>@RequestParam pulls a value off the query string or a form field, <code>\/users?status=active<\/code>. @PathVariable pulls a value out of the URI template itself, <code>\/users\/{id}<\/code>. @RequestBody deserializes the entire HTTP request body, typically JSON, into a Java object using a registered <code>HttpMessageConverter<\/code>, Jackson by default.<\/p>\n<p>Mixing these up is a common fresher mistake: putting @RequestBody on a GET endpoint, for instance, where there usually isn&#8217;t a meaningful body to deserialize in the first place.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">A frontend team says their React app can&#039;t call your API from a different port. How do you actually fix that in Spring Boot?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">REST APIs<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>That&#8217;s a CORS rejection, the browser blocking a cross-origin request before it even reaches your controller, not a server-side error you can catch. Configure it in one place instead of scattering @CrossOrigin annotations across every controller.<\/p>\n<p><div class=\"iq-code not-prose\"><div class=\"iq-code__bar\"><span class=\"iq-code__lang\">java<\/span><button class=\"iq-code__copy\" type=\"button\">Copy<\/button><\/div><pre><code class=\"language-java\">\n\n@Configuration\n\npublic class CorsConfig implements WebMvcConfigurer {\n    @Override\n\n    public void addCorsMappings(CorsRegistry registry) {\n\n        registry.addMapping(\u201c\/api\/**\u201d)\n\n            .allowedOrigins(\u201chttps:\/\/app.example.com\u201d)\n\n            .allowedMethods(\u201cGET\u201d, \u201cPOST\u201d, \u201cPUT\u201d, \u201cDELETE\u201d)\n\n            .allowCredentials(true);\n\n    }\n\n}\n<\/code><\/pre><\/div><\/p>\n<p><code>allowedOrigins(\"*\")<\/code> with <code>allowCredentials(true)<\/code> together will actually throw a startup exception in recent Spring versions, browsers refuse to send credentials to a wildcard origin, so Spring stops you from shipping a config that wouldn&#8217;t have worked anyway.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">How do you accept a file upload in a Spring Boot REST endpoint?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">REST APIs<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>MultipartFile as a @RequestParam, backed by Spring&#8217;s multipart resolver, which Boot autoconfigures the moment spring-boot-starter-web is on the classpath. The file arrives as bytes you can inspect, validate, or stream to disk or object storage yourself.<\/p>\n<p><div class=\"iq-code not-prose\"><div class=\"iq-code__bar\"><span class=\"iq-code__lang\">java<\/span><button class=\"iq-code__copy\" type=\"button\">Copy<\/button><\/div><pre><code class=\"language-java\">\n\n@PostMapping(\u201c\/upload\u201d)\n\npublic ResponseEntity&lt;String&gt; upload(@RequestParam(\u201cfile\u201d) MultipartFile file) {\n\n    if (file.isEmpty()) {\n\n        return ResponseEntity.badRequest().body(\u201cFile is empty\u201d);\n\n    }\n\n    \/\/ save file.getBytes() to disk, S3, wherever\n\n    return ResponseEntity.ok(file.getOriginalFilename());\n\n}\n<\/code><\/pre><\/div><\/p>\n<p><code>spring.servlet.multipart.max-file-size<\/code> defaults to 1MB, which surprises almost everyone the first time a real-sized file gets rejected with a MaxUploadSizeExceededException. Bump it in application.yml before anyone tests with an actual photo instead of a two-line text file.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">How do derived query methods like findByEmailAndStatus actually work?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Spring Data JPA<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Spring Data parses the method name against a fixed keyword grammar, <code>findBy<\/code>, <code>And<\/code>, <code>Or<\/code>, <code>OrderBy<\/code>, comparison keywords like <code>GreaterThan<\/code> or <code>Containing<\/code>, and maps each recognized property name (Email, Status) against your entity&#8217;s actual fields. <code>findByEmailAndStatus(String email, String status)<\/code> becomes something close to <code>WHERE email = ?1 AND status = ?2<\/code> under the hood, generated once at startup, not re-parsed on every call.<\/p>\n<p>The convention is genuinely fragile past a certain complexity. Rename a field on your entity and forget to update the method name, and you get a startup-time <code>PropertyReferenceException<\/code> instead of a silent bug, which is at least the better failure mode.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">What does @ControllerAdvice actually do differently from a try\/catch block in every controller?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Exception Handling<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>@ControllerAdvice is a class-level annotation that scopes @ExceptionHandler methods across every controller in the application (or a subset, if you constrain it with <code>basePackages<\/code> or <code>assignableTypes<\/code>), instead of repeating the same try\/catch logic in every single controller method.<\/p>\n<p>Throw a <code>UserNotFoundException<\/code> anywhere in any controller, and Spring&#8217;s exception-resolution machinery walks up the call stack, finds the matching @ExceptionHandler method in your @ControllerAdvice class, and routes the exception there automatically. Your controller methods stay focused on the happy path.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">Is @RestControllerAdvice just @ControllerAdvice with a different name, or does it actually change behavior?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Exception Handling<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>It bundles @ControllerAdvice with @ResponseBody, the same relationship @RestController has to @Controller. Every @ExceptionHandler method inside gets its return value serialized straight to the response body as JSON, instead of being resolved as a view name the way a plain @ControllerAdvice would try to do by default.<\/p>\n<p>For a JSON API, @RestControllerAdvice is close to the only version worth reaching for. Plain @ControllerAdvice makes sense mainly in an app that&#8217;s also rendering server-side views and needs some handlers to return a template name.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">How do Spring profiles actually work in practice?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Profiles<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>A profile is a named set of beans and properties that only load when that profile is active. <code>application-prod.yml<\/code> overlays (not replaces) the base <code>application.yml<\/code> when the <code>prod<\/code> profile is active, set through <code>spring.profiles.active=prod<\/code> as an environment variable, a JVM flag, or a command-line argument. Beans can be scoped to a profile too, with <code>@Profile(\"prod\")<\/code> on a @Configuration class or @Bean method, so a mock payment gateway bean only registers in <code>dev<\/code> or <code>test<\/code>, never in <code>prod<\/code>.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">application.properties or application.yml, does it actually matter which one you pick?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Externalized Config<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Functionally, no, both bind to the same underlying property source and Boot reads either one identically. YAML reads better once you have nested config, database, mail, and security sections each with several sub-keys, since indentation replaces repeating the same dotted prefix on every line. Properties files are flatter and occasionally easier to grep in a hurry.<\/p>\n<p>The one real gotcha, YAML is whitespace-sensitive and doesn&#8217;t forgive a stray tab character the way most editors default to, mixing tabs and spaces in a YAML file produces a parse error that looks nothing like the actual mistake. I&#8217;ve lost more time to that than to any other config-file issue on this list.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">What happens the moment you add spring-boot-starter-security with zero configuration?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Security<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Every endpoint locks down behind HTTP Basic auth immediately. Boot generates a random UUID password at startup, logs it to the console (&#8220;Using generated security password: &#8230;&#8221;), against a default in-memory user named <code>user<\/code>. No config file needed, adding the dependency alone triggers it.<\/p>\n<p>Nobody ships that default to production. It exists so a bare app isn&#8217;t wide open the instant you add the starter, forcing real security config before deployment.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">How do you test a controller without booting the full Spring context?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Testing<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>MockMvc, usually paired with @WebMvcTest. It simulates an HTTP request against your controller with no real network port and no server starting, and lets you assert on status, headers, and JSON body in one fluent call.<\/p>\n<p>The service layer gets mocked with @MockBean instead of wired for real. You&#8217;re testing that your controller maps requests and responses correctly, not re-testing logic that already has its own unit tests elsewhere.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">Why does Spring Security push you toward BCryptPasswordEncoder instead of just storing passwords in the database directly?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Security<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Storing a plaintext password means a single database leak hands over every user&#8217;s real password, and since people reuse passwords across sites, that leak compounds well past your own app. BCrypt hashes the password with a built-in random salt baked into the output string itself, so two users with the identical password get completely different stored hashes, and it&#8217;s deliberately slow, tunable through a work-factor parameter, specifically to make brute-forcing millions of guesses impractical even with modern hardware.<\/p>\n<p>PasswordEncoder.matches(rawPassword, storedHash) is how you verify a login attempt, you never decrypt the stored hash back into a password, because BCrypt is one-way by design. There&#8217;s no decrypt method to call even if you wanted one.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">How do you cache the result of an expensive method call in Spring Boot without writing your own cache logic?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Caching<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>@EnableCaching on a configuration class turns caching on, then @Cacheable on any method tells Spring to check a cache before running the method body at all, and store the result under a generated key afterward.<\/p>\n<p><div class=\"iq-code not-prose\"><div class=\"iq-code__bar\"><span class=\"iq-code__lang\">java<\/span><button class=\"iq-code__copy\" type=\"button\">Copy<\/button><\/div><pre><code class=\"language-java\">\n\n@Cacheable(value = \u201cproducts\u201d, key = \u201c#id\u201d)\n\npublic Product findProduct(Long id) {\n\n    return productRepository.findById(id)\n\n        .orElseThrow(() -&gt; new ProductNotFoundException(id));\n\n}\n<\/code><\/pre><\/div><\/p>\n<p>Boot defaults to a simple ConcurrentHashMap-based cache if nothing else is configured, fine for a demo, not for anything you&#8217;d actually run in production since it&#8217;s per-instance and vanishes on restart. A real deployment reaches for Redis or Caffeine, wired in as the CacheManager bean, so the cache survives restarts (Redis) or at least gets proper eviction policies (Caffeine) instead of growing unbounded in memory.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">Once Eureka knows where a service lives, how do you actually call it from Java code without hand-writing a RestTemplate call for every endpoint?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Microservices<\/span><span class=\"iq-badge iq-badge--easy\">Easy<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>A Feign client, an interface where you declare the HTTP calls you want to make and Spring Cloud OpenFeign generates the implementation at runtime, wiring in Eureka-based load balancing automatically if it&#8217;s on the classpath.<\/p>\n<p><div class=\"iq-code not-prose\"><div class=\"iq-code__bar\"><span class=\"iq-code__lang\">java<\/span><button class=\"iq-code__copy\" type=\"button\">Copy<\/button><\/div><pre><code class=\"language-java\">\n\n@FeignClient(name = \u201cinventory-service\u201d)\n\npublic interface InventoryClient {\n    @GetMapping(\u201c\/api\/inventory\/{sku}\u201d)\n\n    InventoryStatus checkStock(@PathVariable String sku);\n\n}\n<\/code><\/pre><\/div><\/p>\n<p>Calling <code>inventoryClient.checkStock(\"SKU-123\")<\/code> from another service reads exactly like a local method call, no manual URL building, no manual JSON parsing, the load balancer picks a healthy instance from Eureka&#8217;s registry behind the scenes. RestTemplate still works fine for a one-off call, Feign earns its keep once you&#8217;re calling the same downstream service from more than one place in the codebase.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-dsec iq-dsec--medium\"><div class=\"iq-dsec__row\"><h2 class=\"iq-dsec__h\" id=\"medium\"><span class=\"iq-dsec__dot\" aria-hidden=\"true\"><\/span>Medium questions<\/h2><span class=\"iq-dsec__n\">21<\/span><\/div><div class=\"iq-dsec__bar\" aria-hidden=\"true\"><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">You add spring-boot-starter-data-jpa and suddenly there&#039;s a DataSource bean you never wrote a line of code for. Walk through why.<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Autoconfiguration<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>The starter puts HikariCP, an embedded H2 driver (if it&#8217;s on the classpath), and Spring&#8217;s JPA autoconfiguration classes onto the classpath. <code>DataSourceAutoConfiguration<\/code>, one of those classes, is gated by <code>@ConditionalOnClass(DataSource.class)<\/code> and <code>@ConditionalOnMissingBean<\/code>. Both conditions pass, since you added the starter and haven&#8217;t declared your own <code>DataSource<\/code> bean, so Boot wires one automatically, pointed at whatever connection properties you&#8217;ve set in <code>application.yml<\/code>, or an in-memory H2 instance if you haven&#8217;t set any at all.<\/p>\n<p>The moment you declare your own <code>@Bean DataSource<\/code>, that same conditional fails and Boot&#8217;s version quietly steps aside. This is the exact mechanism behind almost every &#8220;how does X get configured automatically&#8221; question you&#8217;ll get asked about Boot.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">A teammate insists autoconfiguration is &#039;basically magic.&#039; How would you actually go check what it did?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Autoconfiguration<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Start the app with the <code>--debug<\/code> flag and read the conditions report Boot prints: a positive-matches list (what fired, and why) and a negative-matches list (what got rejected, and by which condition). Once Actuator&#8217;s on the classpath, <code>\/actuator\/conditions<\/code> gives you the same report over HTTP instead of scrolling logs, which is the version I&#8217;d reach for once the app is running anywhere other than my own laptop. There&#8217;s no magic in either report, just a long list of conditions somebody already evaluated for you.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">What are Spring&#039;s bean scopes, and when do you actually reach for something other than singleton?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Bean Scopes<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Singleton is the default and covers the overwhelming majority of beans: one shared instance per container. Prototype creates a brand-new instance every time the bean is requested, useful for stateful, non-thread-safe objects you don&#8217;t want shared across requests. The remaining four (request, session, application, websocket) only exist in a web-aware context, scoped to the lifetime of an HTTP request, an HTTP session, the ServletContext, or a WebSocket session respectively.<\/p>\n<p>I&#8217;d say prototype scope is rarer in real Spring Boot codebases than interview prep material suggests. Most &#8220;I need a fresh instance per use&#8221; problems get solved with a factory method or an <code>ObjectFactory&lt;T&gt;<\/code> injected into a singleton, rather than the bean itself being prototype-scoped.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">Two classes implement the same interface, and Spring refuses to start because it can&#039;t pick one to inject. What are your actual options?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Dependency Injection<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Three real options. Mark one implementation <code>@Primary<\/code> and Spring injects it by default whenever the interface is requested without further hints, only useful when one implementation is genuinely the &#8220;normal&#8221; choice. Tag each implementation with a distinct name in <code>@Qualifier<\/code> and reference that same name at the injection point, which works even when neither implementation is clearly the default. Or rename the constructor parameter to match one bean&#8217;s name exactly, since Spring falls back to matching by variable name before giving up, though I wouldn&#8217;t rely on that one for anything a teammate has to maintain later.<\/p>\n<p><code>@Primary<\/code> and <code>@Qualifier<\/code> on the same interface together is a common bug. <code>@Qualifier<\/code> at the injection point always wins over <code>@Primary<\/code>, so a leftover <code>@Primary<\/code> annotation on the wrong implementation can sit there silently doing nothing while everyone assumes it&#8217;s still in charge.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">@Component, @Service, and @Repository all register a bean the same way. Why do all three exist?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Annotations<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>They&#8217;re all meta-annotated with @Component, so Spring&#8217;s component scan registers them identically as far as bean creation goes. The difference is what rides along with each one. @Repository adds automatic exception translation, Spring wraps a raw <code>SQLException<\/code> or similar persistence-specific exception into its own unchecked <code>DataAccessException<\/code> hierarchy, so a service calling a repository never needs to know which database driver actually threw what.<\/p>\n<p>@Service and @Controller carry no extra framework behavior by default, they&#8217;re semantic markers, mainly useful for readability and for AOP pointcuts (transaction advice is commonly configured to target @Service-annotated classes by convention, not because the framework enforces it). @RestController is @Controller plus @ResponseBody bundled together, added in Spring 4.0 specifically so REST APIs didn&#8217;t need to annotate every single handler method.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">@Aspect, @Before, @After, @Around show up on plenty of resumes. What do they actually do underneath?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Annotations<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Aspect-Oriented Programming lets you attach behavior to method calls without touching the method itself, logging, timing, auditing, retried calls, cross-cutting concerns that would otherwise get copy-pasted into every service method. <code>@Aspect<\/code> marks a class as holding that behavior, and a pointcut expression, <code>execution(* com.example.service.*.*(..))<\/code>, tells Spring which methods to intercept. <code>@Before<\/code> runs code ahead of the matched method, <code>@After<\/code> runs regardless of outcome, and <code>@Around<\/code> wraps the whole call, letting you skip the method entirely, change its arguments, or swap its return value.<\/p>\n<p>Spring AOP is proxy-based, the same mechanism behind @Transactional, so it inherits the identical self-invocation limitation. Call an @Around-advised method from another method in the same class and the aspect never fires, for the same reason a self-invoked @Transactional method never opens a transaction. If you&#8217;ve already explained the @Transactional self-invocation trap earlier in the interview, saying this one out loud usually lands well.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">What does wrapping a return value in ResponseEntity buy you that a plain object doesn&#039;t?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">REST APIs<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Control. Return a plain object from a @RestController method and Spring defaults to a 200 OK, with no way to signal &#8220;this was actually created&#8221; (201) or &#8220;this wasn&#8217;t found&#8221; (404) from the return type alone, short of throwing an exception or slapping @ResponseStatus on the method.<\/p>\n<p>ResponseEntity lets you set the status code, custom headers, and the body all from the same return statement, <code>ResponseEntity.status(HttpStatus.CREATED).body(savedUser)<\/code>. For simple GET endpoints that always succeed with the same status, a plain object is fine and arguably reads cleaner. For anything conditional, use ResponseEntity.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">What does @Transactional actually guarantee, and what&#039;s the mistake that silently breaks it?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Spring Data JPA<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>It wraps the method in a database transaction, commit on normal return, rollback on an unchecked exception (checked exceptions don&#8217;t roll back by default, which surprises people). Mechanically it&#8217;s proxy-based AOP, Spring wraps your bean in a proxy at startup, and that proxy is what actually opens and closes the transaction.<\/p>\n<p>The mistake: calling a @Transactional method from another method in the same class. That&#8217;s a plain internal call, <code>this.someMethod()<\/code>, never routed through the proxy, so none of the transactional advice fires. The method still runs, it just quietly isn&#8217;t transactional anymore, and nothing throws an error to say so. Restructure so the call comes from a different bean, or, less cleanly, inject a self-reference through <code>ApplicationContext<\/code>.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">A findAll() endpoint returns 40,000 rows and the frontend times out. What&#039;s the Spring Data fix?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Spring Data JPA<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Extend PagingAndSortingRepository (or just use JpaRepository, which already includes it) and accept a Pageable parameter instead of returning a full List. Spring Data injects page number, size, and sort order straight from query parameters like <code>?page=0&size=20&sort=createdAt,desc<\/code>, no manual parsing required.<\/p>\n<p><div class=\"iq-code not-prose\"><div class=\"iq-code__bar\"><span class=\"iq-code__lang\">java<\/span><button class=\"iq-code__copy\" type=\"button\">Copy<\/button><\/div><pre><code class=\"language-java\">\n\npublic interface OrderRepository extends JpaRepository&lt;Order, Long&gt; {\n\n    Page&lt;Order&gt; findByStatus(String status, Pageable pageable);\n\n}\n<\/code><\/pre><\/div><\/p>\n<p>The returned Page object carries the content plus totalElements, totalPages, and whether there&#8217;s a next page, everything a frontend needs to render pagination controls without a second count query written by hand. Watch the count query itself on a large table though, Page runs a separate SELECT COUNT(*) for every request unless you switch to Slice, which skips the count and only tells you whether more results exist.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">You could annotate a custom exception class with @ResponseStatus instead of writing an @ExceptionHandler for it. When would you actually choose that?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Exception Handling<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>@ResponseStatus(HttpStatus.NOT_FOUND) directly on a custom exception class is simpler for exceptions that always map to exactly one status code and never need a custom response body, Spring reads the annotation and sets the status automatically the moment the exception propagates uncaught. No @ControllerAdvice class involved at all.<\/p>\n<p>The moment you need a structured error body, a field-level validation map, a trace ID, anything beyond a bare status code, that annotation stops being enough and you&#8217;re back to an @ExceptionHandler. Most production APIs end up using @ExceptionHandler for nearly everything within a few months, since &#8220;just a status code, no body&#8221; rarely survives contact with a real frontend team asking for error details to display.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">The same property is set in three places. What order actually wins?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Externalized Config<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Command-line arguments beat almost everything. OS environment variables come next in most real deployments, which is why containerized apps set config through env vars instead of baking values into the JAR. A profile-specific file beats the base <code>application.yml<\/code> when that profile is active, and a hardcoded <code>@Value(\"${some.prop:default}\")<\/code> fallback only applies once nothing else in the chain set the property. Most config incidents I&#8217;ve seen aren&#8217;t &#8220;Spring picked the wrong value,&#8221; they&#8217;re a team forgetting an env var set in the deploy pipeline had already overridden the file they were staring at.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">What&#039;s Spring Boot Actuator, and which endpoint would you actually check first during an incident?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Actuator<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Actuator is a starter that exposes production-readiness endpoints over HTTP and JMX: health, metrics, environment properties, thread dumps, and more. Only <code>\/actuator\/health<\/code> and <code>\/actuator\/info<\/code> are exposed by default, everything else needs an explicit <code>management.endpoints.web.exposure.include<\/code> setting.<\/p>\n<p><code>\/actuator\/health<\/code> first, for a fast pass-fail signal, then <code>\/actuator\/metrics<\/code> for anything specific: JVM memory, request latency, pool usage. One underused endpoint: <code>\/actuator\/loggers<\/code> flips a package&#8217;s log level from INFO to DEBUG at runtime via a POST request, no restart, no redeploy, no waiting for the next deploy window while something&#8217;s actively on fire.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">@Value(&quot;${some.setting}&quot;) works fine for one property. Why do teams switch to @ConfigurationProperties once they have more than a few?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Externalized Config<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>@Value pulls one property per annotation, scattered across however many classes need it, with no compile-time check that the property even exists until the app actually starts and that specific line runs. @ConfigurationProperties binds an entire prefixed block of config to a single strongly-typed class in one place, nested objects, lists, and Maps included, and Spring Boot&#8217;s own annotation processor can generate IDE autocomplete metadata for it.<\/p>\n<p><div class=\"iq-code not-prose\"><div class=\"iq-code__bar\"><span class=\"iq-code__lang\">java<\/span><button class=\"iq-code__copy\" type=\"button\">Copy<\/button><\/div><pre><code class=\"language-java\">\n\n@ConfigurationProperties(prefix = \u201capp.mail\u201d)\n\npublic class MailProperties {\n\n    private String host;\n\n    private int port;\n\n    private boolean sslEnabled;\n\n    \/\/ getters and setters\n\n}\n<\/code><\/pre><\/div><\/p>\n<p>Add @Validated alongside @ConfigurationProperties and Bean Validation annotations on the fields (@NotBlank, @Min) actually get enforced at startup, so a missing required property fails the app immediately with a clear message instead of surfacing as a null three services downstream.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">The default \/actuator\/health endpoint says UP, but your app actually depends on a third-party payment API that&#039;s down right now. How do you make health reflect that?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Actuator<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Implement HealthIndicator (or extend AbstractHealthIndicator) as a bean, and Boot&#8217;s health aggregator automatically includes it in the \/actuator\/health response alongside the built-in database and disk-space checks.<\/p>\n<p><div class=\"iq-code not-prose\"><div class=\"iq-code__bar\"><span class=\"iq-code__lang\">java<\/span><button class=\"iq-code__copy\" type=\"button\">Copy<\/button><\/div><pre><code class=\"language-java\">\n\n@Component\n\npublic class PaymentGatewayHealthIndicator implements HealthIndicator {\n    private final PaymentGatewayClient client;\n    public PaymentGatewayHealthIndicator(PaymentGatewayClient client) {\n\n        this.client = client;\n\n    }\n    @Override\n\n    public Health health() {\n\n        try {\n\n            client.ping();\n\n            return Health.up().build();\n\n        } catch (Exception e) {\n\n            return Health.down(e).withDetail(\u201cgateway\u201d, \u201cunreachable\u201d).build();\n\n        }\n\n    }\n\n}\n<\/code><\/pre><\/div><\/p>\n<p>One down indicator flips the whole aggregate status to DOWN by default, which is exactly what you want feeding a load balancer or Kubernetes readiness probe, a pod that can&#8217;t reach a critical dependency shouldn&#8217;t keep receiving traffic just because its own JVM is technically alive.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">How would you configure a custom SecurityFilterChain for a stateless REST API?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Security<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Disable CSRF (it guards against a browser-session attack that doesn&#8217;t apply to a token-authenticated API with no cookies), set session creation to stateless so Spring never touches an HttpSession, and permit public endpoints explicitly before requiring authentication on everything else.<\/p>\n<p><div class=\"iq-code not-prose\"><div class=\"iq-code__bar\"><span class=\"iq-code__lang\">java<\/span><button class=\"iq-code__copy\" type=\"button\">Copy<\/button><\/div><pre><code class=\"language-java\">\n\n@Configuration\n\n@EnableWebSecurity\n\npublic class SecurityConfig {\n    @Bean\n\n    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {\n\n        http\n\n            .csrf(csrf -&gt; csrf.disable())\n\n            .sessionManagement(session -&gt;\n\n                session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))\n\n            .authorizeHttpRequests(auth -&gt; auth\n\n                .requestMatchers(\u201c\/api\/auth\/**\u201d).permitAll()\n\n                .anyRequest().authenticated()\n\n            )\n\n            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);\n        return http.build();\n\n    }\n\n}\n<\/code><\/pre><\/div><\/p>\n<p>The JWT filter itself is the part interviewers usually gloss over verbally but expect you to have actually built once: pulling the token off the Authorization header, validating it, and populating the SecurityContext before the request reaches your controller.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">@SpringBootTest, @WebMvcTest, @DataJpaTest: when do you actually reach for each one?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Testing<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>@SpringBootTest boots the entire application context, real beans, real wiring, the closest thing to a genuine integration test, and the slowest of the three. @WebMvcTest loads only the web layer, controllers, converters, MockMvc, with service beans mocked through @MockBean, so you&#8217;re testing routing and serialization, not business logic.<\/p>\n<p>@DataJpaTest loads only JPA config against an embedded test database, rolling back each test&#8217;s transaction afterward so nothing leaks into the next one. Reach for @WebMvcTest or @DataJpaTest whenever you can, they&#8217;re faster and narrower. Save @SpringBootTest for the handful of tests that genuinely need the whole wiring.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">How do you restrict a single method to admin users only, without writing an if-check against the current user&#039;s role inside the method body?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Security<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>@PreAuthorize with a SpEL expression, evaluated before the method runs. Enable it with @EnableMethodSecurity on a configuration class, then annotate any bean method Spring manages.<\/p>\n<p><div class=\"iq-code not-prose\"><div class=\"iq-code__bar\"><span class=\"iq-code__lang\">java<\/span><button class=\"iq-code__copy\" type=\"button\">Copy<\/button><\/div><pre><code class=\"language-java\">\n\n@PreAuthorize(\u201chasRole(\u2018ADMIN\u2019)\u201d)\n\npublic void deleteUser(Long userId) {\n\n    userRepository.deleteById(userId);\n\n}\n<\/code><\/pre><\/div><\/p>\n<p>It works because Spring Security wraps the bean in a proxy, the same AOP mechanism behind @Transactional, so it has the identical self-invocation blind spot: call this method from another method in the same class and the check never fires. That pattern keeps showing up across the framework once you notice it once.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">What&#039;s actually different between @Mock and @MockBean when you&#039;re writing a test?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Testing<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>@Mock is plain Mockito, it creates a mock object with no Spring context involved at all, meant for fast unit tests where you construct the class under test directly and hand it mocked dependencies yourself. @MockBean is Spring Boot&#8217;s own annotation, it replaces a real bean inside the Spring application context with a Mockito mock, for tests like @WebMvcTest or @SpringBootTest that actually boot some slice of the container.<\/p>\n<p>Reach for @Mock whenever you&#8217;re not loading a Spring context at all, it&#8217;s faster since there&#8217;s no context to start. @MockBean only earns its cost in tests that need the container anyway, using it just to avoid writing a plain constructor call is paying for a slower test for no real benefit.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">A product&#039;s price changes, but \/products\/{id} keeps returning the old cached value. What went wrong?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Caching<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Nothing evicted the stale entry. @Cacheable only ever populates a cache, it never invalidates one, so an update method needs its own @CacheEvict (or @CachePut, if you want to refresh the entry rather than just clear it) pointed at the same cache name and key.<\/p>\n<p><div class=\"iq-code not-prose\"><div class=\"iq-code__bar\"><span class=\"iq-code__lang\">java<\/span><button class=\"iq-code__copy\" type=\"button\">Copy<\/button><\/div><pre><code class=\"language-java\">\n\n@CacheEvict(value = \u201cproducts\u201d, key = \u201c#product.id\u201d)\n\npublic Product updateProduct(Product product) {\n\n    return productRepository.save(product);\n\n}\n<\/code><\/pre><\/div><\/p>\n<p>The key expression on the evict has to actually resolve to the same value the original @Cacheable used, key = &#8220;#id&#8221; on one method and key = &#8220;#product.id&#8221; on another look similar but generate different cache keys if the parameter shapes don&#8217;t line up, and Spring won&#8217;t warn you, it just quietly evicts nothing and the stale value sits there until it expires on its own.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">In a system with a dozen microservices, how does one service actually find another one&#039;s network address without a hardcoded URL?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Microservices<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Service discovery, and Netflix Eureka (through Spring Cloud Netflix) is the version most Spring Boot shops still reach for even with Netflix itself long past actively developing it. Each service registers itself with a Eureka server on startup, its own instance ID, host, and port, and periodically sends a heartbeat to prove it&#8217;s still alive. Any service that needs to call another one asks Eureka for the current list of healthy instances instead of reading a URL out of a config file.<\/p>\n<p>@EnableDiscoveryClient on a service&#8217;s main class is what registers it. The real payoff shows up during a rolling deploy, old instances heartbeat out and get removed from the registry, new instances register themselves, and callers never touch a hardcoded IP that changed underneath them mid-deploy.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">Your app connects fine locally but under load in production you start seeing connections time out. What HikariCP settings do you actually check, and what breaks if maximum-pool-size is set too high?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">HikariCP tuning<\/span><span class=\"iq-badge iq-badge--medium\">Medium<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Start with the properties that actually matter: maximum-pool-size (default 10), minimum-idle, connection-timeout (30 seconds by default, how long a thread waits to borrow a connection before it gives up), idle-timeout, and max-lifetime. Max-lifetime should be set a few seconds shorter than whatever timeout your database or the network in front of it enforces, otherwise you get connections that look healthy in the pool but get killed mid-query by a firewall or the DB&#8217;s own wait_timeout, and you see intermittent &#8220;connection reset&#8221; errors that are hard to reproduce. Leak-detection-threshold is worth turning on in staging too, it logs a stack trace for any connection held longer than the threshold, which is how you actually find the code path that opens a connection and forgets to close it.<\/p>\n<p>Setting maximum-pool-size too high is the more common mistake than setting it too low, and it doesn&#8217;t help the way people expect. HikariCP&#8217;s own guidance is roughly (core_count * 2) + effective_spindle_count as a starting point, not a number in the hundreds. If you run five app instances each with a pool of 50 against a Postgres box with max_connections set to 100, you&#8217;ll blow through the database&#8217;s connection limit before you even hit real traffic, and you&#8217;ll get &#8220;FATAL: sorry, too many clients already&#8221; errors that have nothing to do with your app code. Even below that hard limit, more connections than the database has cores to serve them just means more context switching and lock contention on the DB side, so throughput actually drops as you raise the pool size past a certain point.<\/p>\n<p>The opposite failure, pool too small, shows up as threads blocking on HikariPool.getConnection() and eventually throwing SQLTransientConnectionException with &#8220;Connection is not available, request timed out.&#8221; A thread dump during an incident will show a pile of threads parked in the same place, which is the tell that you&#8217;re pool-starved rather than database-starved, and the fix there is either raising minimum-idle\/maximum-pool-size a bit or finding the query that&#8217;s holding connections too long instead of just cranking the numbers up.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-dsec iq-dsec--hard\"><div class=\"iq-dsec__row\"><h2 class=\"iq-dsec__h\" id=\"hard\"><span class=\"iq-dsec__dot\" aria-hidden=\"true\"><\/span>Hard questions<\/h2><span class=\"iq-dsec__n\">12<\/span><\/div><div class=\"iq-dsec__bar\" aria-hidden=\"true\"><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">How does Spring Boot&#039;s autoconfiguration actually decide which beans to create?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Autoconfiguration<\/span><span class=\"iq-badge iq-badge--hard\">Hard<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Spring Boot&#8217;s own reference docs describe it plainly: autoconfiguration &#8220;attempts to automatically configure your Spring application based on the jar dependencies that you have added&#8221; (<a href=\"https:\/\/docs.spring.io\/spring-boot\/reference\/using\/auto-configuration.html\" target=\"_blank\" rel=\"noopener noreferrer\">Spring Boot reference docs, Auto-configuration<\/a>). <code>@EnableAutoConfiguration<\/code>, pulled in automatically through <code>@SpringBootApplication<\/code>, tells Boot to read a list of candidate autoconfiguration classes. As of Spring Boot 2.7, that list lives in a flat file at <code>META-INF\/spring\/org.springframework.boot.autoconfigure.AutoConfiguration.imports<\/code>, one fully qualified class name per line, replacing the older <code>spring.factories<\/code> registration.<\/p>\n<p>Each candidate class is gated behind conditional annotations, most often <code>@ConditionalOnClass<\/code> (only apply if a specific class is on the classpath) and <code>@ConditionalOnMissingBean<\/code> (only apply if you haven&#8217;t already defined your own bean of that type). Boot evaluates every condition and only registers the beans that pass. It&#8217;s non-invasive by design: define your own <code>DataSource<\/code> bean, and the auto-configured one silently backs off instead of fighting you for the slot.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">Your company has three internal services that all need the same Kafka producer setup. How would you package that as a Spring Boot autoconfiguration instead of copy-pasting config into each one?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Autoconfiguration<\/span><span class=\"iq-badge iq-badge--hard\">Hard<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Build a small library module with a plain <code>@Configuration<\/code> class holding the shared producer&#8217;s <code>@Bean<\/code> methods, gated behind <code>@ConditionalOnClass(KafkaTemplate.class)<\/code> so it only activates when Kafka is actually on the consuming project&#8217;s classpath, and <code>@ConditionalOnMissingBean<\/code> so any service that wants to override the default still can. Register that class&#8217;s fully qualified name in a <code>META-INF\/spring\/org.springframework.boot.autoconfigure.AutoConfiguration.imports<\/code> file inside the library jar, the same mechanism Boot&#8217;s own starters use.<\/p>\n<p>Ship it as two artifacts if you&#8217;re doing this properly, an -autoconfigure module with the actual <code>@Configuration<\/code> classes and a thin -starter module that just depends on it plus whatever client libraries it needs, mirroring how <code>spring-boot-starter-data-jpa<\/code> is really a dependency wrapper around <code>spring-boot-autoconfigure<\/code>&#8216;s JPA classes. Most teams skip the two-module split for internal-only libraries and just ship one jar. Nobody outside your org will ever notice.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">Walk through a bean&#039;s lifecycle, from the container instantiating it to destroying it.<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Bean Lifecycle<\/span><span class=\"iq-badge iq-badge--hard\">Hard<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>The container instantiates the bean, populates its dependencies, then fires any Aware callbacks it asked for (<code>BeanNameAware<\/code>, <code>ApplicationContextAware<\/code>, and similar), giving it access to container internals. <code>BeanPostProcessor.postProcessBeforeInitialization<\/code> runs next, then the actual init step, <code>@PostConstruct<\/code> or <code>InitializingBean.afterPropertiesSet()<\/code>, then <code>postProcessAfterInitialization<\/code>, and the bean is ready.<\/p>\n<p>On shutdown, <code>@PreDestroy<\/code> or <code>DisposableBean.destroy()<\/code> fires, but only for singletons, the container manages their full lifecycle. A prototype bean gets handed off after creation and Spring stops tracking it entirely, so its destroy callback never runs on its own. That&#8217;s the detail candidates most often miss.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">Two beans depend on each other through constructor injection. What actually happens, and how do you fix it?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Bean Lifecycle<\/span><span class=\"iq-badge iq-badge--hard\">Hard<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>It throws <code>BeanCurrentlyInCreationException<\/code> at startup. Spring resolves circular dependencies between singletons using a three-level cache of early object references, but that trick only works for setter or field injection, where a partially-built reference can be handed out and filled in later. Constructor injection needs the full object graph before the constructor runs at all, so there&#8217;s no partial reference available.<\/p>\n<p>Three real fixes: extract the shared responsibility into a third bean both depend on, switch one side to setter injection so the early-reference trick applies, or add <code>@Lazy<\/code> to one constructor parameter so Spring injects a proxy that resolves on first use. I&#8217;d reach for the refactor first. Most circular dependencies are design smells wearing a wiring-error costume, and @Lazy just delays the conversation the team needs to have anyway.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">@Configuration and @Bean vs. just @Component: when do you actually need the former?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Annotations<\/span><span class=\"iq-badge iq-badge--hard\">Hard<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Use a stereotype annotation (@Component, @Service) when Spring itself can construct the object from its own constructor, your own class, wired by the container directly. Reach for a @Configuration class with @Bean methods when you&#8217;re wiring something you don&#8217;t own the source of, a third-party client, a library&#8217;s builder object, anything that needs custom construction logic Spring can&#8217;t infer from annotations alone.<\/p>\n<p>Here&#8217;s the part most candidates miss: @Configuration classes get CGLIB-proxied by default (&#8220;full&#8221; mode). Call one @Bean method from inside another @Bean method in the same class, and the proxy intercepts that call and returns the already-registered singleton instead of running the method body again. Drop @Configuration down to a plain @Component with @Bean methods (Spring&#8217;s &#8220;lite&#8221; mode) and that guarantee disappears entirely, each call becomes an ordinary Java method invocation and hands back a fresh object every time. That distinction has bitten more than a few teams who assumed @Bean always meant singleton, regardless of where it was declared.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">Write a small REST controller with a GET and a POST endpoint.<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Coding<\/span><span class=\"iq-badge iq-badge--hard\">Hard<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Constructor injection for the service dependency, @PathVariable for the single-resource GET, @RequestBody for the POST payload, and ResponseEntity on the POST so the 201 status is explicit rather than assumed.<\/p>\n<p><div class=\"iq-code not-prose\"><div class=\"iq-code__bar\"><span class=\"iq-code__lang\">java<\/span><button class=\"iq-code__copy\" type=\"button\">Copy<\/button><\/div><pre><code class=\"language-java\">\n\n@RestController\n\n@RequestMapping(\u201c\/api\/users\u201d)\n\npublic class UserController {\n    private final UserService userService;\n    public UserController(UserService userService) {\n\n        this.userService = userService;\n\n    }\n    @GetMapping(\u201c\/{id}\u201d)\n\n    public ResponseEntity&lt;User&gt; getUser(@PathVariable Long id) {\n\n        return userService.findById(id)\n\n            .map(ResponseEntity::ok)\n\n            .orElse(ResponseEntity.notFound().build());\n\n    }\n    @PostMapping\n\n    public ResponseEntity&lt;User&gt; createUser(@RequestBody @Valid UserRequest request) {\n\n        User saved = userService.create(request);\n\n        return ResponseEntity.status(HttpStatus.CREATED).body(saved);\n\n    }\n\n}\n<\/code><\/pre><\/div><\/p>\n<p>The <code>@Valid<\/code> annotation on the POST parameter is worth calling out unprompted, it triggers Bean Validation against annotations on <code>UserRequest<\/code> (like <code>@NotBlank<\/code> or <code>@Email<\/code>) and returns a 400 automatically if they fail, before your service method ever runs.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">A JpaRepository interface has no implementation anywhere in your codebase. How does calling save() actually do anything?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Spring Data JPA<\/span><span class=\"iq-badge iq-badge--hard\">Hard<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>At startup, Spring Data&#8217;s <code>RepositoryFactoryBean<\/code> creates a JDK dynamic proxy for your interface, there&#8217;s no generated source file you can go read. Calls to the standard CRUD methods, <code>save()<\/code>, <code>findById()<\/code>, <code>delete()<\/code>, get routed to <code>SimpleJpaRepository<\/code>, the one concrete class backing nearly every Spring Data JPA repository regardless of what entity it&#8217;s parameterized over.<\/p>\n<p>Calls that don&#8217;t exist on SimpleJpaRepository, your own custom method names, get handled differently. The proxy&#8217;s method interceptor parses the method name at proxy-creation time and builds the corresponding JPQL query, before you ever call it at runtime.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">What&#039;s the N+1 query problem, and how does it show up in a real Spring Data JPA app?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Spring Data JPA<\/span><span class=\"iq-badge iq-badge--hard\">Hard<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>You fetch N parent entities with one query, and each has a lazily-loaded <code>@OneToMany<\/code> collection. The moment your code, or your JSON serializer, touches that collection on each parent, Hibernate fires a separate query per parent. One query becomes N+1, and it&#8217;s easy to miss with a handful of test rows in dev, then show up as real latency once the table has a few thousand real ones.<\/p>\n<p><div class=\"iq-code not-prose\"><div class=\"iq-code__bar\"><span class=\"iq-code__lang\">java<\/span><button class=\"iq-code__copy\" type=\"button\">Copy<\/button><\/div><pre><code class=\"language-java\">\n\n\/\/ N+1 trap: each order.getItems() call fires its own query\n\nList&lt;Order&gt; orders = orderRepository.findAll();\n\nfor (Order order : orders) {\n\n    order.getItems().size(); \/\/ lazy load fires here, once per order\n\n}\n\/\/ fixed with a JOIN FETCH, one query total\n\n@Query(\u201cSELECT o FROM Order o JOIN FETCH o.items\u201d)\n\nList&lt;Order&gt; findAllWithItems();\n<\/code><\/pre><\/div><\/p>\n<p><code>@EntityGraph<\/code> is the other common fix if you&#8217;d rather not hand-write JPQL for every case. Either way, load the association eagerly in that one query, don&#8217;t switch the mapping to eager globally, that just shifts the same N+1 cost onto every other query against the entity.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">Two users load the same order to edit it, and both hit save seconds apart. How do you keep the second save from silently overwriting the first user&#039;s changes?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Spring Data JPA<\/span><span class=\"iq-badge iq-badge--hard\">Hard<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Add a @Version field to the entity, a Long or int Hibernate manages for you. Every update includes that version in its WHERE clause, and increments it on success. If User B&#8217;s save fires with a stale version number because User A already committed a change in between, the WHERE clause matches zero rows, and Hibernate throws OptimisticLockException instead of silently overwriting data neither user saw the other change.<\/p>\n<p><div class=\"iq-code not-prose\"><div class=\"iq-code__bar\"><span class=\"iq-code__lang\">java<\/span><button class=\"iq-code__copy\" type=\"button\">Copy<\/button><\/div><pre><code class=\"language-java\">\n\n@Entity\n\npublic class Order {\n\n    @Id\n\n    private Long id;\n    @Version\n\n    private Long version;\n    \/\/ other fields\n\n}\n<\/code><\/pre><\/div><\/p>\n<p>This is optimistic locking, no database lock held while the user has the record open, which is the only version that scales to a real web app with people leaving tabs open for an hour. Pessimistic locking, an actual row-level SELECT &#8230; FOR UPDATE, exists too, but I&#8217;d only reach for it on genuinely short-lived, high-contention operations like a seat reservation, not general CRUD editing.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">A service method calls another @Transactional method on a different bean. Does it join the same transaction, or start a new one?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Spring Data JPA<\/span><span class=\"iq-badge iq-badge--hard\">Hard<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Joins the same one, by default. REQUIRED, Spring&#8217;s default propagation, means &#8220;use the current transaction if one exists, start a new one if it doesn&#8217;t.&#8221; Both methods commit or roll back together as a single unit.<\/p>\n<p><div class=\"iq-code not-prose\"><div class=\"iq-code__bar\"><span class=\"iq-code__lang\">java<\/span><button class=\"iq-code__copy\" type=\"button\">Copy<\/button><\/div><pre><code class=\"language-java\">\n\n@Transactional(propagation = Propagation.REQUIRES_NEW)\n\npublic void logAuditEvent(String message) {\n\n    auditRepository.save(new AuditEntry(message));\n\n}\n<\/code><\/pre><\/div><\/p>\n<p>REQUIRES_NEW suspends whatever transaction is already running and opens a completely separate one, its own commit, its own rollback, independent of the caller. That&#8217;s the actual use case for the audit-log example above: you want the audit entry to survive even if the outer business transaction rolls back afterward. Get REQUIRED and REQUIRES_NEW confused and you&#8217;ll either lose audit records you needed, or accidentally commit a partial write the outer transaction meant to undo.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">Two @ExceptionHandler methods could both technically match a thrown exception. How does Spring decide which one to run?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Exception Handling<\/span><span class=\"iq-badge iq-badge--hard\">Hard<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>Spring picks the handler mapped to the closest matching type in the exception&#8217;s own class hierarchy, not the order the methods are declared in the file. A handler for the exact thrown class wins over one written for a superclass.<\/p>\n<p><div class=\"iq-code not-prose\"><div class=\"iq-code__bar\"><span class=\"iq-code__lang\">java<\/span><button class=\"iq-code__copy\" type=\"button\">Copy<\/button><\/div><pre><code class=\"language-java\">\n\n@ControllerAdvice\n\npublic class GlobalExceptionHandler {\n    @ExceptionHandler(UserNotFoundException.class)\n\n    public ResponseEntity&lt;ErrorResponse&gt; handleNotFound(UserNotFoundException ex) {\n\n        return ResponseEntity.status(HttpStatus.NOT_FOUND)\n\n            .body(new ErrorResponse(ex.getMessage()));\n\n    }\n    @ExceptionHandler(Exception.class)\n\n    public ResponseEntity&lt;ErrorResponse&gt; handleGeneric(Exception ex) {\n\n        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)\n\n            .body(new ErrorResponse(\u201cSomething went wrong\u201d));\n\n    }\n\n}\n<\/code><\/pre><\/div><\/p>\n<p>Throw a <code>UserNotFoundException<\/code> against the class above and the specific handler runs, not the generic one, even though <code>Exception.class<\/code> technically matches too. Candidates who only ever write one catch-all handler rarely get asked this follow-up, since there&#8217;s nothing to disambiguate between. Write two, and it comes up almost every time.<\/p>\n<p><\/div><\/div><\/div>\n<div class=\"iq-qa\"><button class=\"iq-qa__q\" type=\"button\" aria-expanded=\"false\"><span class=\"iq-qa__qtext\">You mark a service method @Async, wire up @EnableAsync, and now when it throws an exception nothing shows up anywhere, no log line, no error to the caller. Where did it go?<\/span><span class=\"iq-qa__meta\"><span class=\"iq-qa__tag\">Async exceptions<\/span><span class=\"iq-badge iq-badge--hard\">Hard<\/span><span class=\"iq-qa__chev\" aria-hidden=\"true\"><\/span><\/span><\/button><div class=\"iq-qa__a\"><div class=\"iq-qa__a-inner\"><\/p>\n<p>For a void-returning @Async method, the calling thread has already moved on before the async method even starts executing on the task executor&#8217;s thread, so there&#8217;s no call stack left for the exception to propagate back into. Spring&#8217;s proxy catches it on the worker thread and, unless you&#8217;ve told it otherwise, just drops it. No stack trace in your logs, no 500 to the client, nothing. This is one of the more common surprises people hit the first time they slap @Async on something that used to be synchronous and expect it to fail the same way.<\/p>\n<p>The fix for void methods is implementing AsyncConfigurer and overriding getAsyncUncaughtExceptionHandler to return a handler that actually logs the method, its arguments, and the throwable:<\/p>\n<p><div class=\"iq-code not-prose\"><div class=\"iq-code__bar\"><span class=\"iq-code__lang\">java<\/span><button class=\"iq-code__copy\" type=\"button\">Copy<\/button><\/div><pre><code class=\"language-java\">\n\n@Configuration\n\n@EnableAsync\n\npublic class AsyncConfig implements AsyncConfigurer {\n    @Override\n\n    public Executor getAsyncExecutor() {\n\n        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\n\n        executor.setCorePoolSize(4);\n\n        executor.setMaxPoolSize(8);\n\n        executor.setQueueCapacity(100);\n\n        executor.initialize();\n\n        return executor;\n\n    }\n    @Override\n\n    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n\n        return (throwable, method, params) -&gt;\n\n            log.error(\u201cAsync method {} failed with params {}\u201d, method.getName(), params, throwable);\n\n    }\n\n}\n<\/code><\/pre><\/div><\/p>\n<p>If the method returns CompletableFuture instead of void, the exception is captured on the future rather than swallowed, but it still only surfaces if the caller actually inspects it with .get(), .join(), or .exceptionally(). A lot of code calls an async method and ignores the returned future entirely, which puts you right back in silent-failure territory. Before chasing the exception handler, also check that the method isn&#8217;t being called from within the same class (this.method()) instead of through the injected bean or a self-reference proxy, because Spring&#8217;s @Async support is proxy-based and a same-class call bypasses the proxy entirely, meaning the method actually just runs synchronously and any exception behaves like a normal thrown exception, not an async one. That mismatch between what you expect to be async and what&#8217;s actually running synchronously is usually the first thing to rule out.<\/p>\n<p><\/div><\/div><\/div>\n<h2>How to prepare for a Spring Boot interview in 2026<\/h2>\n<p>Skip the annotation flashcards. Knowing that @Transactional &#8220;wraps a method in a transaction&#8221; doesn&#8217;t help when an interviewer hands you a service class calling one of its own @Transactional methods and asks why the rollback isn&#8217;t happening. Build one small app end to end instead: a REST controller, a Spring Data JPA repository, a @ControllerAdvice with at least two exception types, and one deliberately broken thing, a self-invoked transactional call, an N+1 query against a few thousand seeded rows, a circular constructor dependency you untangle by hand. Fixing your own mistakes teaches the mechanism faster than reading about it does.<\/p>\n<p>Across Spring Boot-tagged mock interviews run through LastRoundAI, the stumble that shows up most isn&#8217;t a missing annotation. It&#8217;s candidates who name every bean scope correctly and then go quiet the moment a follow-up connects two of them, why a prototype bean injected into a singleton only gets created once, say, instead of fresh every time the way its name implies. I don&#8217;t have a clean percentage for how often that specific follow-up catches people, only that it comes up enough in review to flag here.<\/p>\n<p>Fresher and campus-hire loops (TCS, Infosys, Wipro, Cognizant) weight heavily toward annotations, REST APIs, and Spring Data JPA, plus one security question about the zero-config starter. Product-company and 3+ year loops lean harder into bean lifecycle, the self-invocation transaction trap, and N+1, since those separate someone who&#8217;s used Spring Boot from someone who&#8217;s actually debugged it under load.<\/p>\n<h2>Get the reps in before the real thing<\/h2>\n<p>Reading an answer to the self-invocation @Transactional question isn&#8217;t the same as defending it live once an interviewer changes one detail on you mid-conversation. <a href=\"\/products\/mock-interviews\">LastRoundAI&#8217;s mock interview mode<\/a> runs Java and Spring Boot rounds with real-time follow-ups instead of a static question bank, and the free plan includes 15 credits a month that reset monthly rather than stockpiling. Starter is $19\/mo if you need more sessions than that covers.<\/p>\n<p>If the slower part of your job search is finding enough Spring Boot and Java backend openings rather than passing the interview once you land one, <a href=\"\/products\/auto-apply\">Auto-Apply<\/a> matches and applies to roles for you, 10 a month free, up to 400 a month on Ultimate, with every application held in a review queue until you approve it. Nothing goes out without you seeing it first.<\/p>\n<p>Questions about either product go to contact@lastroundai.com. That&#8217;s the only inbox we check.<\/p>\n<div class=\"iq-sources not-prose\"><div class=\"iq-sources__title\">Sources &amp; further reading<\/div><ul class=\"iq-sources__list\"><li><a href=\"https:\/\/survey.stackoverflow.co\/2025\/technology\" target=\"_blank\" rel=\"nofollow noopener\">Stack Overflow Developer Survey 2025<\/a><\/li><li><a href=\"https:\/\/docs.spring.io\/spring-boot\/reference\/using\/auto-configuration.html\" target=\"_blank\" rel=\"nofollow noopener\">Spring Boot Reference Docs: Auto-configuration<\/a><\/li><li><a href=\"https:\/\/www.bls.gov\/ooh\/computer-and-information-technology\/software-developers.htm\" target=\"_blank\" rel=\"nofollow noopener\">BLS Occupational Outlook Handbook: Software Developers, QA Analysts, and Testers<\/a><\/li><\/ul><\/div>\n","protected":false},"excerpt":{"rendered":"<p>A 3-year Java engineer at a Pune fintech got asked one question in June 2026 that decided the whole loop: why does the team&#8217;s style guide ban @Autowired on a field when every tutorial online does exactly that. She named the annotation correctly on the first pass. She couldn&#8217;t say why it&#8217;s discouraged, and the&#8230;<\/p>\n","protected":false},"author":4,"featured_media":1693,"comment_status":"open","ping_status":"closed","template":"","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"tags":[],"class_list":["post-1198","iq","type-iq","status-publish","has-post-thumbnail","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Spring Boot Interview Questions (2026): Q&amp;A | LastRoundAI<\/title>\n<meta name=\"description\" content=\"Spring Boot interview questions for 2026 with answers and code: auto-configuration, starters, DI and beans, REST APIs, Spring Data JPA, profiles, and Actuator.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/lastroundai.com\/interview-questions\/spring-boot\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring Boot Interview Questions (2026): Q&amp;A | LastRoundAI\" \/>\n<meta property=\"og:description\" content=\"Spring Boot interview questions for 2026 with answers and code: auto-configuration, starters, DI and beans, REST APIs, Spring Data JPA, profiles, and Actuator.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/lastroundai.com\/interview-questions\/spring-boot\" \/>\n<meta property=\"og:site_name\" content=\"LastRound AI\" \/>\n<meta property=\"article:modified_time\" content=\"2026-07-19T05:24:07+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/lastroundai.com\/blog\/wp-content\/uploads\/2026\/07\/iq-spring-boot-og.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"20 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/lastroundai.com\\\/interview-questions\\\/spring-boot\",\"url\":\"https:\\\/\\\/lastroundai.com\\\/interview-questions\\\/spring-boot\",\"name\":\"Spring Boot Interview Questions (2026): Q&A | LastRoundAI\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/lastroundai.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/lastroundai.com\\\/interview-questions\\\/spring-boot#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/lastroundai.com\\\/interview-questions\\\/spring-boot#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/lastroundai.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/iq-spring-boot-og.png\",\"datePublished\":\"2026-07-16T17:15:45+00:00\",\"dateModified\":\"2026-07-19T05:24:07+00:00\",\"description\":\"Spring Boot interview questions for 2026 with answers and code: auto-configuration, starters, DI and beans, REST APIs, Spring Data JPA, profiles, and Actuator.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/lastroundai.com\\\/interview-questions\\\/spring-boot#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/lastroundai.com\\\/interview-questions\\\/spring-boot\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/lastroundai.com\\\/interview-questions\\\/spring-boot#primaryimage\",\"url\":\"https:\\\/\\\/lastroundai.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/iq-spring-boot-og.png\",\"contentUrl\":\"https:\\\/\\\/lastroundai.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/iq-spring-boot-og.png\",\"width\":1200,\"height\":630,\"caption\":\"Spring Boot interview questions \u2014 LastRoundAI\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/lastroundai.com\\\/interview-questions\\\/spring-boot#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/lastroundai.com\\\/blog\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Interview Questions\",\"item\":\"https:\\\/\\\/lastroundai.com\\\/interview-questions\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Spring Boot Interview Questions (2026): Most Asked, With Answers\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/lastroundai.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/lastroundai.com\\\/blog\\\/\",\"name\":\"LastRound AI\",\"description\":\"Interview Assistant prep, tech careers and AI tools\",\"publisher\":{\"@id\":\"https:\\\/\\\/lastroundai.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/lastroundai.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/lastroundai.com\\\/blog\\\/#organization\",\"name\":\"LastRound AI\",\"url\":\"https:\\\/\\\/lastroundai.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/lastroundai.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/lastroundai.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/06\\\/lastroundai-transprant-logo-optimized-BxEo2Wtq.png\",\"contentUrl\":\"https:\\\/\\\/lastroundai.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/06\\\/lastroundai-transprant-logo-optimized-BxEo2Wtq.png\",\"width\":400,\"height\":400,\"caption\":\"LastRound AI\"},\"image\":{\"@id\":\"https:\\\/\\\/lastroundai.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Spring Boot Interview Questions (2026): Q&A | LastRoundAI","description":"Spring Boot interview questions for 2026 with answers and code: auto-configuration, starters, DI and beans, REST APIs, Spring Data JPA, profiles, and Actuator.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/lastroundai.com\/interview-questions\/spring-boot","og_locale":"en_US","og_type":"article","og_title":"Spring Boot Interview Questions (2026): Q&A | LastRoundAI","og_description":"Spring Boot interview questions for 2026 with answers and code: auto-configuration, starters, DI and beans, REST APIs, Spring Data JPA, profiles, and Actuator.","og_url":"https:\/\/lastroundai.com\/interview-questions\/spring-boot","og_site_name":"LastRound AI","article_modified_time":"2026-07-19T05:24:07+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/lastroundai.com\/blog\/wp-content\/uploads\/2026\/07\/iq-spring-boot-og.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"20 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/lastroundai.com\/interview-questions\/spring-boot","url":"https:\/\/lastroundai.com\/interview-questions\/spring-boot","name":"Spring Boot Interview Questions (2026): Q&A | LastRoundAI","isPartOf":{"@id":"https:\/\/lastroundai.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/lastroundai.com\/interview-questions\/spring-boot#primaryimage"},"image":{"@id":"https:\/\/lastroundai.com\/interview-questions\/spring-boot#primaryimage"},"thumbnailUrl":"https:\/\/lastroundai.com\/blog\/wp-content\/uploads\/2026\/07\/iq-spring-boot-og.png","datePublished":"2026-07-16T17:15:45+00:00","dateModified":"2026-07-19T05:24:07+00:00","description":"Spring Boot interview questions for 2026 with answers and code: auto-configuration, starters, DI and beans, REST APIs, Spring Data JPA, profiles, and Actuator.","breadcrumb":{"@id":"https:\/\/lastroundai.com\/interview-questions\/spring-boot#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/lastroundai.com\/interview-questions\/spring-boot"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/lastroundai.com\/interview-questions\/spring-boot#primaryimage","url":"https:\/\/lastroundai.com\/blog\/wp-content\/uploads\/2026\/07\/iq-spring-boot-og.png","contentUrl":"https:\/\/lastroundai.com\/blog\/wp-content\/uploads\/2026\/07\/iq-spring-boot-og.png","width":1200,"height":630,"caption":"Spring Boot interview questions \u2014 LastRoundAI"},{"@type":"BreadcrumbList","@id":"https:\/\/lastroundai.com\/interview-questions\/spring-boot#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/lastroundai.com\/blog"},{"@type":"ListItem","position":2,"name":"Interview Questions","item":"https:\/\/lastroundai.com\/interview-questions"},{"@type":"ListItem","position":3,"name":"Spring Boot Interview Questions (2026): Most Asked, With Answers"}]},{"@type":"WebSite","@id":"https:\/\/lastroundai.com\/blog\/#website","url":"https:\/\/lastroundai.com\/blog\/","name":"LastRound AI","description":"Interview Assistant prep, tech careers and AI tools","publisher":{"@id":"https:\/\/lastroundai.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/lastroundai.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/lastroundai.com\/blog\/#organization","name":"LastRound AI","url":"https:\/\/lastroundai.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/lastroundai.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/lastroundai.com\/blog\/wp-content\/uploads\/2026\/06\/lastroundai-transprant-logo-optimized-BxEo2Wtq.png","contentUrl":"https:\/\/lastroundai.com\/blog\/wp-content\/uploads\/2026\/06\/lastroundai-transprant-logo-optimized-BxEo2Wtq.png","width":400,"height":400,"caption":"LastRound AI"},"image":{"@id":"https:\/\/lastroundai.com\/blog\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/lastroundai.com\/blog\/wp-json\/wp\/v2\/iq\/1198","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lastroundai.com\/blog\/wp-json\/wp\/v2\/iq"}],"about":[{"href":"https:\/\/lastroundai.com\/blog\/wp-json\/wp\/v2\/types\/iq"}],"author":[{"embeddable":true,"href":"https:\/\/lastroundai.com\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/lastroundai.com\/blog\/wp-json\/wp\/v2\/comments?post=1198"}],"version-history":[{"count":4,"href":"https:\/\/lastroundai.com\/blog\/wp-json\/wp\/v2\/iq\/1198\/revisions"}],"predecessor-version":[{"id":1764,"href":"https:\/\/lastroundai.com\/blog\/wp-json\/wp\/v2\/iq\/1198\/revisions\/1764"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/lastroundai.com\/blog\/wp-json\/wp\/v2\/media\/1693"}],"wp:attachment":[{"href":"https:\/\/lastroundai.com\/blog\/wp-json\/wp\/v2\/media?parent=1198"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lastroundai.com\/blog\/wp-json\/wp\/v2\/tags?post=1198"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}