Spring Boot interview questions: auto-configuration, starters, annotations, profiles, Actuator and deployment.
30 questions
Spring Boot auto-configuration inspects the classpath, the beans already registered and the properties available, then configures sensible defaults automatically. For example, if H2 is on the classpath it configures an in-memory DataSource; if spring-boot-starter-web is present it configures DispatcherServlet and EmbeddedTomcat.
Autoconfigured beans are written with conditions (@ConditionalOnClass, @ConditionalOnMissingBean, etc.), so your own bean definitions override the defaults. @SpringBootApplication combines @Configuration, @EnableAutoConfiguration and @ComponentScan.
Starters are convenient dependency descriptors. Instead of adding many jars manually, you add one starter that pulls the correct versions as transitive dependencies. For example spring-boot-starter-web brings Spring MVC, Jackson and embedded Tomcat; spring-boot-starter-data-jpa brings JPA and Hibernate.
Starters also inherit versions from the parent POM, so you never manage library versions by hand.
Configuration lives in application.properties or application.yml. Profile-specific files (application-dev.yml, application-prod.yml) activate with spring.profiles.active=dev or the SPRING_PROFILES_ACTIVE environment variable. The matching profile file is merged over the base file.
Profiles let dev, test and prod set different database URLs, logging levels and feature flags without touching code.
@Controller returns a view name resolved by a view resolver; it typically renders HTML templates.
@RestController combines @Controller and @ResponseBody, so the method return value is serialised directly to the HTTP response (JSON by default via Jackson). REST endpoints almost always use @RestController.
Actuator exposes production-ready endpoints such as /actuator/health, /actuator/metrics, /actuator/beans, /actuator/env and /actuator/mappings. They help with monitoring and diagnosis. Expose only what you need:
management.endpoints.web.exposure.include=health,info,metricsYou can also register custom metrics with Micrometer and feed them to Prometheus, Graphite or CloudWatch.
Run during development with mvn spring-boot:run or a main() class. For production you build an executable JAR (mvn package) and run java -jar app.jar, or a WAR (SpringBootServletInitializer + provided Tomcat) deployed to an external servlet container.
The executable jar embeds Tomcat, so no external server is needed. Environment-specific values are injected via env vars, keeping the same artifact deployable everywhere.
The Spring Framework provides core IoC/DI, AOP, data access and MVC, but requires a lot of manual configuration (XML or Java config, dependency management, and a server to deploy to). Spring Boot builds on Spring and adds auto-configuration, embedded servers, starters and a production-ready toolset so you can create a runnable application with minimal setup.
At startup, @EnableAutoConfiguration triggers loading of META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports files. Each auto-configuration class is evaluated with many conditions (@ConditionalOnClass, @ConditionalOnMissingBean, @ConditionalOnProperty). Only configurations whose conditions pass are registered as beans - and because @ConditionalOnMissingBean is used, your own beans override the defaults.
Use the exclude attribute on @SpringBootApplication or @EnableAutoConfiguration, or the property spring.autoconfigure.exclude in application.properties. For example, to disable DataSource auto-configuration:
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})@ComponentScan tells Spring which packages to scan for @Component/@Service/@Repository/@Controller beans and registers them in the context. @EnableAutoConfiguration activates Spring Boot auto-configuration, which creates sensible default beans based on the classpath - it does not scan your code.
Several ways: @Value("${app.name}") to inject a single property, @ConfigurationProperties(prefix = "app") to bind a whole group of properties into a typed POJO (preferred, type-safe), and Environment.getProperty() for programmatic access.
ConfigurationProperties classes are enabled with @EnableConfigurationProperties or @ConfigurationPropertiesScan.
@Value injects one property at a time into a field and supports SpEL; it is loose and not validated. @ConfigurationProperties binds many related properties into a strongly typed bean with relaxed binding (kebab-case, underscores) and supports validation via @Validated. Prefer ConfigurationProperties for settings, @Value for one-off values.
Add validation annotations from jakarta.validation on the DTO fields (@NotBlank, @Email, @Min, @Size), mark the parameter @Valid in the controller, and handle MethodArgumentNotValidException with @ControllerAdvice to return a clean error response.
The starter spring-boot-starter-validation must be on the classpath (it is no longer bundled with web).
@RequestBody binds the JSON/XML request body to a Java object. @PathVariable reads a value from the URL template: /users/{id}. @RequestParam reads a query parameter: /users?id=5.
Use @ControllerAdvice with @ExceptionHandler methods. A class annotated @RestControllerAdvice (or @ControllerAdvice + @ResponseBody) catches exceptions thrown by controllers across the application and maps them to proper HTTP status codes with a consistent error body:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFound.class)
public ResponseEntity<ErrorBody> handle(ResourceNotFound e) { ... }
}Globally with a WebMvcConfigurer:
@Bean
WebMvcConfigurer cors() {
return new WebMvcConfigurer() {
public void addCorsMappings(CorsRegistry r) {
r.addMapping("/api/**").allowedOrigins("https://site.com");
}
};
}Or per-controller with @CrossOrigin. CORS affects browsers; it is safe by default because same-origin policy blocks reads anyway.
Add @EnableScheduling on a configuration class and annotate methods with @Scheduled, for example @Scheduled(cron = "0 0 * * * *"), @Scheduled(fixedRate = 60000) or @Scheduled(initialDelay = 5000, fixedDelay = 60000). By default tasks run on a single-threaded scheduler; configure a TaskScheduler bean for concurrent execution.
Enable async with @EnableAsync, mark the method @Async, and call it from a different bean so it runs on a separate thread from a configurable executor. The return type can be CompletableFuture. Remember: @Async only takes effect on proxies - calling the method from inside the same class bypasses it.
application.properties is the default configuration embedded in the artifact. Environment variables and command-line arguments provide the external configuration that overrides it, and profile-specific files (application-{profile}.properties) hold per-environment overrides. The precedence (highest first) is roughly: command-line args, Java system properties, OS env vars, profile files, then the base application.properties.
They follow a strict precedence list defined in the docs. Simplest rule: command-line arguments > Java system properties > OS environment variables > application-{profile} files > application.yml/properties > defaults in code. Later/higher sources override earlier ones, so you can run the same artifact in dev and prod just by injecting environment variables.
DevTools provides automatic restart during development (classpath changes trigger a fast app restart), LiveReload to refresh the browser, and automatically disables caching for templates and static resources. It is not part of the production artifact (it is excluded when packaged).
Add spring-boot-starter-security. The framework auto-configures a default login and user, but normally you define a SecurityFilterChain bean describing rules, a UserDetailsService (or JWT filter) and an AuthenticationManager:
@Bean
SecurityFilterChain chain(HttpSecurity http) {
return http.authorizeHttpRequests(a -> a.anyRequest().authenticated())
.formLogin(withDefaults()).build();
}Accept MultipartFile in a controller method, validate its size, and store it (filesystem, DB or object storage). Configure limits with properties:
spring.servlet.multipart.max-file-size=5MB
spring.servlet.multipart.max-request-size=10MBReturn a URL or key so the client can retrieve the file later.
These are JPA constructs: @Id marks a simple primary key. @EmbeddedId embeds a special @Embeddable class containing the key fields as a single object. @IdClass keeps the key fields in the entity and pairs it with a separate ID class matching them. @EmbeddedId is generally more type-safe.
Spring Boot uses Logback by default. Set levels in application.properties:
logging.level.root=INFO
logging.level.com.example.demo=DEBUG
logging.file.name=app.logOr provide a full logback-spring.xml for patterns, rolling policy and appenders. No extra dependencies are needed because spring-boot-starter includes Logback.
The /actuator/health endpoint aggregates HealthIndicator beans: the DB (DataSourceHealthIndicator), disk space, ping and more. Add a custom indicator by implementing the HealthIndicator interface and returning a Health object:
@Component
public class ApiHealth implements HealthIndicator {
public Health health() { return Health.up().build(); }
}For slice tests add @WebMvcTest(MyController.class), wire dependencies with @MockBean, then use MockMvc:
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired MockMvc mvc;
@MockBean UserService service;
@Test void ok() throws Exception {
mvc.perform(get("/users/1")).andExpect(status().isOk());
}
}Full-stack integration tests instead use @SpringBootTest with TestRestTemplate or a real HTTP client.
@SpringBootTest loads the full application context (slowest, integration testing). @WebMvcTest loads only the web layer (controllers, filters, HandlerInterceptors) with the rest mocked. @DataJpaTest loads only JPA/repository beans and usually swaps in an embedded database. Slice tests are fast and isolated; @SpringBootTest verifies everything works together.
Create a Dockerfile based on a JRE image, copy the executable jar and run it with one CMD:
FROM eclipse-temurin:17-jre
COPY target/demo.jar /app/demo.jar
ENTRYPOINT ["java","-jar","/app/demo.jar"]Spring Boot 3.3+ can also generate native images or layered oci images with spring-boot-maven-plugin, producing smaller layers. Pass environment settings as container env vars.
Spring Boot's default is an embedded server (Tomcat, Jetty or Undertow) - the app IS the server, started with java -jar. Deploying a WAR to an external container is only needed when the platform requires it (traditional Tomcat/WebLogic hosting). For WAR, your main class extends SpringBootServletInitializer, Tomcat is provided scope, and the server manages the servlet lifecycle and context.