LearnThatStack Ace your next interview

Spring Boot.
Interview cheat sheet.

Quick reference for Spring Boot - sectioned for fast scanning. Skim the part you're shaky on, walk in confident.

Backend Development 15-section reference ~11 min read

Summary

Spring Boot is an opinionated framework built on top of Spring Framework that simplifies Java application development through auto-configuration, embedded servers, and starter dependencies. Following the principle of "convention over configuration," it enables rapid development of production-ready applications with minimal setup. This cheatsheet covers essential Spring Boot concepts including annotations, dependency injection, REST API development, data access with JPA, security implementation, testing strategies, monitoring with Actuator, and microservices patterns for technical interview preparation.

Spring Boot Basics

What is Spring Boot?

  • Opinionated framework built on Spring Framework
  • Convention over Configuration - minimal config needed
  • Embedded servers (Tomcat, Jetty, Undertow)
  • Auto-configuration based on classpath dependencies
  • Production-ready features (metrics, health checks)

Key Features

  • Starter Dependencies: Pre-configured dependency descriptors
  • Auto-Configuration: Automatically configures beans based on classpath
  • Embedded Server: No need for external application server
  • Actuator: Production monitoring and management
  • CLI: Command-line interface for quick prototyping

Project Structure

src/
├── main/
│   ├── java/
│   │   └── com/example/demo/
│   │       ├── DemoApplication.java      # Main class
│   │       ├── controller/               # REST controllers
│   │       ├── service/                  # Business logic
│   │       ├── repository/               # Data access
│   │       └── model/                    # Entities/DTOs
│   └── resources/
│       ├── application.properties        # Configuration
│       ├── static/                       # Static resources
│       └── templates/                    # View templates
└── test/                                 # Test classes

Core Annotations

Essential Annotations

@SpringBootApplication  // Combines @Configuration + @EnableAutoConfiguration + @ComponentScan
@RestController        // @Controller + @ResponseBody
@RequestMapping       // Map HTTP requests to handler methods
@Component           // Generic Spring-managed component
@Service            // Business logic layer
@Repository         // Data access layer
@Configuration      // Java-based configuration
@Bean              // Method produces a bean

Request Handling Annotations

@GetMapping("/users")           // GET request
@PostMapping("/users")          // POST request
@PutMapping("/users/{id}")      // PUT request
@DeleteMapping("/users/{id}")   // DELETE request
@PatchMapping("/users/{id}")    // PATCH request

@PathVariable Long id           // Extract from URL path
@RequestParam String name       // Extract query parameter
@RequestBody User user          // Extract request body
@RequestHeader String auth      // Extract header value

Validation Annotations

@Valid                  // Trigger validation
@NotNull               // Field cannot be null
@NotEmpty              // Not null and not empty
@NotBlank              // Not null, not empty, not whitespace
@Size(min=2, max=30)   // String/Collection size
@Email                 // Valid email format
@Pattern(regexp="...")  // Regex pattern
@Min(18)               // Minimum numeric value
@Max(100)              // Maximum numeric value

Dependency Injection & IoC

Injection Types

// 1. Constructor Injection (Recommended)
@Service
public class UserService {
    private final UserRepository repository;
    
    public UserService(UserRepository repository) {
        this.repository = repository;
    }
}

// 2. Field Injection (Not recommended)
@Service
public class UserService {
    @Autowired
    private UserRepository repository;
}

// 3. Setter Injection
@Service
public class UserService {
    private UserRepository repository;
    
    @Autowired
    public void setRepository(UserRepository repository) {
        this.repository = repository;
    }
}

Bean Scopes

@Component
@Scope("singleton")    // Default - one instance (shared)
public class SingletonBean {}

@Component
@Scope("prototype")    // New instance each time
public class PrototypeBean {}

@Component
@Scope("request")      // One instance per HTTP request
public class RequestBean {}

@Component
@Scope("session")      // One instance per HTTP session
public class SessionBean {}

Configuration

Application Properties

# application.properties
server.port=8080
spring.application.name=demo-app

# Database
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=secret

# JPA
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

# Logging
logging.level.root=INFO
logging.level.com.example=DEBUG

Configuration Classes

@Configuration
public class AppConfig {
    
    @Bean
    @ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager();
    }
    
    @Profile("dev")
    @Bean
    public DataSource devDataSource() {
        return new H2DataSource();
    }
}

Profiles

// Activate profile: --spring.profiles.active=dev

@Component
@Profile("dev")
public class DevService implements MyService {}

@Component
@Profile("prod")
public class ProdService implements MyService {}

REST APIs

Basic REST Controller

@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @GetMapping
    public List<User> getAllUsers() {
        return userService.findAll();
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        return userService.findById(id)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }
    
    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public User createUser(@Valid @RequestBody User user) {
        return userService.save(user);
    }
    
    @PutMapping("/{id}")
    public User updateUser(@PathVariable Long id, 
                          @Valid @RequestBody User user) {
        user.setId(id);
        return userService.save(user);
    }
    
    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteUser(@PathVariable Long id) {
        userService.deleteById(id);
    }
}

Response Entity

// Custom response with status and headers
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
    User user = userService.findById(id);
    
    return ResponseEntity
        .status(HttpStatus.OK)
        .header("X-Custom-Header", "value")
        .body(user);
}

Data Access (JPA)

Entity Definition

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, unique = true)
    private String email;
    
    @Column(name = "full_name")
    private String fullName;
    
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    private List<Order> orders;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "department_id")
    private Department department;
    
    @CreatedDate
    private LocalDateTime createdAt;
    
    @LastModifiedDate
    private LocalDateTime updatedAt;
}

Repository Layer

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    
    // Derived query methods
    Optional<User> findByEmail(String email);
    List<User> findByAgeGreaterThan(int age);
    List<User> findByNameContainingIgnoreCase(String name);
    
    // Custom JPQL query
    @Query("SELECT u FROM User u WHERE u.email = ?1")
    User findByEmailAddress(String email);
    
    // Native SQL query
    @Query(value = "SELECT * FROM users WHERE age > :age", 
           nativeQuery = true)
    List<User> findUsersOlderThan(@Param("age") int age);
    
    // Modifying queries
    @Modifying
    @Query("UPDATE User u SET u.active = false WHERE u.lastLogin < :date")
    void deactivateInactiveUsers(@Param("date") LocalDate date);
}

Pagination and Sorting

// Controller
@GetMapping
public Page<User> getUsers(Pageable pageable) {
    // GET /users?page=0&size=20&sort=name,asc
    return userRepository.findAll(pageable);
}

// Custom pagination
PageRequest pageRequest = PageRequest.of(0, 10, 
    Sort.by("name").ascending());
Page<User> users = userRepository.findAll(pageRequest);

Exception Handling

Global Exception Handler

@RestControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ErrorResponse handleNotFound(ResourceNotFoundException ex) {
        return new ErrorResponse("NOT_FOUND", ex.getMessage());
    }
    
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ErrorResponse handleValidation(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getFieldErrors().forEach(error ->
            errors.put(error.getField(), error.getDefaultMessage())
        );
        return new ErrorResponse("VALIDATION_FAILED", errors);
    }
    
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ErrorResponse handleGeneral(Exception ex) {
        return new ErrorResponse("INTERNAL_ERROR", "An error occurred");
    }
}

Custom Exceptions

@ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}

Security

Basic Security Configuration

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .httpBasic()
            .and()
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        
        return http.build();
    }
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

JWT Authentication

@Component
public class JwtUtil {
    @Value("${jwt.secret}")
    private String secret;
    
    public String generateToken(String username) {
        return Jwts.builder()
            .setSubject(username)
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + 864000000))
            .signWith(SignatureAlgorithm.HS256, secret)
            .compact();
    }
    
    public String extractUsername(String token) {
        return Jwts.parser()
            .setSigningKey(secret)
            .parseClaimsJws(token)
            .getBody()
            .getSubject();
    }
}

Testing

Unit Testing

@SpringBootTest
class UserServiceTest {
    
    @MockBean
    private UserRepository userRepository;
    
    @Autowired
    private UserService userService;
    
    @Test
    void testFindById() {
        // Given
        User user = new User(1L, "John", "john@example.com");
        when(userRepository.findById(1L)).thenReturn(Optional.of(user));
        
        // When
        User found = userService.findById(1L);
        
        // Then
        assertThat(found.getName()).isEqualTo("John");
    }
}

Integration Testing

@SpringBootTest
@AutoConfigureMockMvc
class UserControllerTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @Test
    void testCreateUser() throws Exception {
        String userJson = "{\"name\":\"John\",\"email\":\"john@example.com\"}";
        
        mockMvc.perform(post("/api/users")
                .contentType(MediaType.APPLICATION_JSON)
                .content(userJson))
                .andExpect(status().isCreated())
                .andExpect(jsonPath("$.name").value("John"));
    }
}

Repository Testing

@DataJpaTest
class UserRepositoryTest {
    
    @Autowired
    private TestEntityManager entityManager;
    
    @Autowired
    private UserRepository userRepository;
    
    @Test
    void testFindByEmail() {
        // Given
        User user = new User("John", "john@example.com");
        entityManager.persistAndFlush(user);
        
        // When
        Optional<User> found = userRepository.findByEmail("john@example.com");
        
        // Then
        assertThat(found).isPresent();
        assertThat(found.get().getName()).isEqualTo("John");
    }
}

Actuator & Monitoring

Enable Actuator

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Actuator Configuration

# Expose endpoints
management.endpoints.web.exposure.include=health,info,metrics,env
management.endpoint.health.show-details=always

# Custom info
info.app.name=Demo Application
info.app.version=1.0.0

Custom Health Indicator

@Component
public class DatabaseHealthIndicator implements HealthIndicator {
    
    @Autowired
    private DataSource dataSource;
    
    @Override
    public Health health() {
        try (Connection conn = dataSource.getConnection()) {
            if (conn.isValid(1000)) {
                return Health.up()
                    .withDetail("database", "Available")
                    .build();
            }
        } catch (Exception e) {
            return Health.down(e).build();
        }
        return Health.down().build();
    }
}

Best Practices

1. Use Constructor Injection

// Good
private final UserService userService;
public UserController(UserService userService) {
    this.userService = userService;
}

2. Follow REST Conventions

  • Use proper HTTP methods (GET, POST, PUT, DELETE)
  • Return appropriate status codes
  • Use plural nouns for resources (/users, not /user)

3. Implement Proper Exception Handling

  • Use @RestControllerAdvice for global handling
  • Return consistent error responses
  • Log exceptions appropriately

4. Use DTOs for API Responses

// Don't expose entities directly
public class UserDTO {
    private Long id;
    private String name;
    private String email;
    // Exclude sensitive fields like password
}

5. Implement Validation

  • Use Bean Validation annotations
  • Validate at controller level with @Valid
  • Create custom validators when needed

6. Use Transactions Properly

@Service
@Transactional
public class UserService {
    @Transactional(readOnly = true)
    public List<User> findAll() { }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void createNewTransaction() { }
}

7. Implement Caching

@Service
public class UserService {
    @Cacheable("users")
    public User findById(Long id) { }
    
    @CacheEvict("users")
    public void deleteUser(Long id) { }
}

8. Use Profiles for Environments

  • dev, test, prod profiles
  • Environment-specific configurations
  • Use @Profile annotation

9. Implement Logging

@Slf4j  // Lombok
@Service
public class UserService {
    public User findById(Long id) {
        log.debug("Finding user by id: {}", id);
        // ...
    }
}

10. Write Tests

  • Unit tests for services
  • Integration tests for controllers
  • Repository tests with @DataJpaTest

Key Concepts & Comparisons

Spring Boot vs Spring Framework

Aspect Spring Framework Spring Boot Benefits
Configuration Manual XML/Java config Auto-configuration 80% less configuration code
Server External server deployment Embedded server Deploy as JAR, no server setup
Dependencies Manual dependency management Starter POMs Simplified dependency management
Production Features Manual setup Built-in (Actuator) Production-ready out of the box
Testing Manual test configuration Test starters Faster test development
Development Speed Slower setup Rapid development Focus on business logic

Bean Scopes Deep Dive

Scope Lifecycle Thread Safety Use Case Memory Impact
Singleton One per container Not guaranteed Stateless services, repositories Low - single instance
Prototype New per request Thread-safe Stateful objects, DTOs High - multiple instances
Request One per HTTP request Thread-safe Web request data Medium - per request
Session One per HTTP session Thread-safe User session data Medium - per session
Application One per ServletContext Not guaranteed Application-wide cache Low - single instance

Dependency Injection Types

Type Implementation Pros Cons Best Practice
Constructor Via constructor Immutable, testable, required deps clear Verbose with many deps ✅ Recommended
Field @Autowired on field Less code Hard to test, hidden dependencies ❌ Avoid
Setter Via setter method Optional dependencies Mutable, unclear requirements ⚠️ Use sparingly

Auto-Configuration Conditions

Annotation Condition Example Use Case
@ConditionalOnClass Class present in classpath Enable if dependency exists
@ConditionalOnMissingBean Bean not already defined Default bean configuration
@ConditionalOnProperty Property has specific value Feature toggles
@ConditionalOnWebApplication Web environment Web-specific beans
@ConditionalOnResource Resource exists Load config if file present

Transaction Propagation Levels

Level Behavior Use Case Transaction Boundary
REQUIRED Join existing or create new Default behavior Participates in outer transaction
REQUIRES_NEW Always create new Independent operations Suspends outer transaction
SUPPORTS Use if exists, else none Read operations Flexible participation
MANDATORY Must have existing Enforce transactional context Throws exception if none
NOT_SUPPORTED Execute without transaction Non-transactional operations Suspends if exists
NEVER Must not have transaction Ensure non-transactional Throws exception if exists

Spring Boot Starters Comparison

Starter Dependencies Included Use Case Auto-Configured
spring-boot-starter-web Spring MVC, Tomcat, Jackson REST APIs, web apps DispatcherServlet, ErrorMvcAutoConfiguration
spring-boot-starter-data-jpa Hibernate, Spring Data JPA Database access DataSource, EntityManagerFactory
spring-boot-starter-security Spring Security Authentication/Authorization SecurityFilterChain, UserDetailsService
spring-boot-starter-test JUnit, Mockito, AssertJ Testing MockMvc, TestRestTemplate
spring-boot-starter-actuator Micrometer, Health indicators Production monitoring Endpoints, metrics

Exception Handling Strategies

Strategy Scope Implementation Use Case
@ExceptionHandler Controller-specific Method in controller Local error handling
@RestControllerAdvice Global Separate class Application-wide handling
ResponseStatusException Throw anywhere Direct exception Simple status codes
Custom exceptions Domain-specific Extend RuntimeException Business logic errors

Caching Providers

Provider Performance Features Configuration
ConcurrentHashMap Very Fast Simple, in-memory Default, no config
Ehcache Fast TTL, disk storage XML or Java config
Redis Fast Distributed, persistent Connection properties
Hazelcast Fast Distributed, clustering Network config
Caffeine Very Fast Advanced features Programmatic

Security Authentication Methods

Method Complexity Stateless Use Case Implementation
Basic Auth Low Yes Development, internal APIs Username/password in header
JWT Medium Yes REST APIs, microservices Token-based authentication
OAuth2 High Yes Third-party integration Authorization server
Form Login Low No Traditional web apps Session-based
API Key Low Yes Service-to-service Custom header/parameter

Testing Annotations

Annotation Test Type Loaded Components Use Case
@SpringBootTest Integration Full context End-to-end testing
@WebMvcTest Unit Web layer only Controller testing
@DataJpaTest Unit JPA components Repository testing
@RestClientTest Unit REST clients External API testing
@JsonTest Unit JSON mapping Serialization testing

Performance Optimization Techniques

Technique Impact Implementation Trade-off
Connection Pooling High HikariCP (default) Memory vs connections
Caching High @Cacheable annotations Memory vs freshness
Lazy Loading Medium JPA fetch strategies N+1 queries risk
Async Processing High @Async methods Complexity
Response Compression Medium Server configuration CPU vs bandwidth

Monitoring with Actuator

Endpoint Purpose Default Exposure Sensitive
/health Application health Yes Configurable
/info Application info Yes No
/metrics Application metrics No Yes
/env Environment properties No Yes
/loggers Logger configuration No Yes
/threaddump Thread information No Yes

Profile-Based Configuration

Profile Use Case Activation Configuration
dev Development --spring.profiles.active=dev Debug logging, H2 database
test Testing @ActiveProfiles("test") Test data, mocks
prod Production Environment variable Real database, security
local Local development IDE configuration Local services

Common Interview Topics Summary

  1. Core Concepts

    • Auto-configuration mechanism using @Conditional annotations
    • Starter dependencies and how they simplify development
    • @SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan
    • Embedded server advantages and configuration
  2. Dependency Injection

    • Constructor injection preferred for required dependencies
    • Bean scopes and their appropriate use cases
    • @Qualifier for multiple beans of same type
    • Circular dependency resolution strategies
  3. Data Access

    • Spring Data JPA repository pattern
    • Transaction management with @Transactional
    • Query methods and @Query annotations
    • Pagination and sorting implementation
  4. REST API Development

    • RESTful design principles
    • Request mapping annotations
    • Response entity and status codes
    • Exception handling strategies
  5. Security

    • Spring Security filter chain
    • Authentication vs Authorization
    • JWT implementation
    • Method-level security
  6. Testing

    • Test slices for targeted testing
    • MockBean vs Mock
    • Integration testing strategies
    • Test containers for database testing
  7. Performance

    • Caching strategies and providers
    • Connection pool configuration
    • Async processing benefits
    • JPA optimization techniques
  8. Microservices

    • Spring Cloud components
    • Service discovery patterns
    • Circuit breaker implementation
    • Configuration management
  9. Production Features

    • Actuator endpoints and monitoring
    • Health indicators
    • Metrics collection
    • Log aggregation
  10. Best Practices

    • Proper exception handling
    • Configuration externalization
    • Profile management
    • Security considerations

Quick Reference

Maven Dependencies

<!-- Core -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Data JPA -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!-- Security -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!-- Validation -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

<!-- Test -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

Application Entry Point

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Common Properties

# Server
server.port=8080
server.servlet.context-path=/api

# Database
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.show-sql=false

# Logging
logging.level.root=INFO
logging.pattern.console=%d{HH:mm:ss} %-5level %logger{36} - %msg%n

# Jackson
spring.jackson.serialization.write-dates-as-timestamps=false
spring.jackson.default-property-inclusion=non_null

Remember for Interviews

  1. Understand the basics thoroughly - IoC, DI, Bean lifecycle
  2. Know the annotations - What they do and when to use them
  3. Practice coding - Be ready to write REST APIs from scratch
  4. Understand the architecture - MVC pattern, layered architecture
  5. Know best practices - SOLID principles, clean code
  6. Be familiar with testing - Unit and integration tests
  7. Understand security basics - Authentication vs Authorization
  8. Know about microservices - Basic concepts and Spring Cloud
  9. Performance considerations - Caching, connection pooling
  10. Stay updated - Spring Boot 3.x features, Java 17+ support

Good luck with your interview! 🚀

Found this useful? Pass it on.
Pro · $10/mo

The sheet is free. Pro goes deeper.

Pro opens the full question library behind every sheet, every refresher and a monthly AI allowance. One subscription, all formats.

Full question library All refreshers Cancel anytime