Cheat SheetsSpring BootCore & Setup

Core & Setup — Cheat Sheet

Spring Boot · 14 topics. Download the PDF or the Instagram carousel and share it.

Cheat Sheet · AiCanCode.org
Core & Setup
Spring Boot14 topicsQuick revision reference
1

Spring Boot Introduction

Spring Boot is an opinionated framework that eliminates boilerplate Spring configuration through auto-configuration, embedded servers, and production-ready defaults.

  • @SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan.
  • Auto-configuration is conditional — it backs off when you define your own beans.
  • Embedded Tomcat/Jetty means the app runs as a plain JAR with java -jar.
  • application.properties/yml is the central config; profile files override per environment.
  • Property override order: command-line args > env vars > profile files > application.properties.
  • Use --debug or /actuator/conditions to inspect which auto-configurations are active.
Java + Properties — minimal Spring Boot app
@SpringBootApplication          // = @Configuration + @EnableAutoConfiguration + @ComponentScan
public class AiCanCodeApplication {

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

// application.properties — key defaults you often override
server.port=8080
spring.application.name=toolhub
spring.profiles.active=dev

// Fat JAR build + run
// mvn package → target/toolhub-1.0.0.jar
// java -jar target/toolhub-1.0.0.jar --server.port=9090
2

Spring Boot Starters

Starters are curated dependency descriptors (e.g. spring-boot-starter-web) that bundle all required libraries for a feature, removing version-conflict headaches.

  • Starters are curated dependency bundles — one starter replaces many individual dependencies.
  • spring-boot-dependencies BOM manages all library versions; override via Maven properties.
  • Naming convention: spring-boot-starter-{feature} (official) or {name}-spring-boot-starter (third-party).
  • Exclude an auto-included transitive dep (e.g. Tomcat) by adding <exclusions> on the starter.
  • spring-boot-starter-web = Tomcat; swap to spring-boot-starter-undertow or spring-boot-starter-webflux.
  • spring-boot-starter-test brings JUnit 5, Mockito, AssertJ, MockMvc, and Testcontainers.
XML — common Spring Boot starters
<!-- pom.xml — common starters -->
<dependencies>
  <!-- Web: Spring MVC, Tomcat, Jackson, Hibernate Validator -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <!-- JPA: Hibernate, Spring Data JPA, HikariCP -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>

  <!-- Security: Spring Security core + web -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
  </dependency>

  <!-- Actuator: health, metrics, info endpoints -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
  </dependency>

  <!-- Test: JUnit 5, Mockito, AssertJ, MockMvc, Testcontainers -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>
3

Auto-Configuration

Spring Boot scans the classpath and conditionally creates beans on your behalf; understanding @EnableAutoConfiguration and spring.factories unlocks deep customisation.

  • @SpringBootApplication includes @EnableAutoConfiguration which triggers the entire auto-configuration loading mechanism.
  • Auto-configuration classes are loaded from META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports (Boot 3) or META-INF/spring.factories (Boot 2).
  • @ConditionalOnMissingBean is the primary escape hatch — declare your own @Bean of the same type to override any auto-configured bean.
  • User-defined beans are always registered before auto-configured ones, so explicit definitions always win.
  • Use the --debug flag to print the ConditionEvaluationReport and understand exactly why each auto-config fired or was skipped.
  • Write your own Spring Boot starter by creating a @Configuration class with @Conditional annotations and registering it in the AutoConfiguration.imports file.
Java — Spring Boot
// Spring Boot 3 imports file:
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration

// Simplified example of DataSourceAutoConfiguration
@AutoConfiguration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {

    @Configuration(proxyBeanMethods = false)
    @Conditional(PooledDataSourceCondition.class)
    @ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
    @Import({ DataSourceConfiguration.Hikari.class })
    protected static class PooledDataSourceConfiguration { }
}
4

@SpringBootApplication

A convenience annotation combining @Configuration, @EnableAutoConfiguration, and @ComponentScan that bootstraps the entire application context.

  • @SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan
  • Auto-configuration is conditional — @ConditionalOnMissingBean means your own beans take priority
  • Use exclude or spring.autoconfigure.exclude to disable unwanted auto-configs
  • scanBasePackages restricts component scanning to a specific root (improves startup)
  • Only one @SpringBootApplication is needed per application; typically on the main class
  • spring.main.lazy-initialization=true delays bean creation to first use, cutting startup time
Java — @SpringBootApplication customisation
@SpringBootApplication(
    scanBasePackages = "com.example",
    exclude = { DataSourceAutoConfiguration.class }
)
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

// Equivalent explicit form:
// @Configuration
// @EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)
// @ComponentScan("com.example")
5

application.properties / YAML

Externalise configuration via key-value properties or structured YAML; Spring Boot resolves values from multiple sources following a strict precedence order.

  • Property source precedence (highest first): CLI args → env vars → profile properties → base properties.
  • @ConfigurationProperties binds a prefix to a typed bean — prefer over scattered @Value for grouped config.
  • @Validated on @ConfigurationProperties enables JSR-303 constraint checking at startup.
  • Never commit secrets to application.properties — inject via environment variables or a secrets manager.
  • spring.profiles.active selects environment-specific files; profile groups (Spring Boot 2.4+) activate multiple at once.
  • Environment variables override properties: SPRING_DATASOURCE_URL overrides spring.datasource.url.
Properties + YAML — property sources and precedence
# application.properties (lowest priority in the set)
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=app

# Overridden by application-prod.properties (active profile)
# application-prod.properties
server.port=80
spring.datasource.url=jdbc:mysql://prod-db:3306/mydb

# Overridden by environment variable (higher priority)
# SPRING_DATASOURCE_URL=jdbc:mysql://rds-host:3306/mydb

# Overridden by command-line arg (highest priority)
# java -jar app.jar --spring.datasource.url=jdbc:mysql://override:3306/mydb

# Activate profile
spring.profiles.active=prod
# Or: SPRING_PROFILES_ACTIVE=prod  (env var)
# Or: java -jar app.jar --spring.profiles.active=prod  (CLI)

# YAML equivalent (application.yml)
server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: app
  profiles:
    active: dev
6

@ConfigurationProperties

Binds a whole hierarchy of properties to a strongly-typed POJO, supporting relaxed binding, JSR-303 validation, and IDE auto-completion.

  • @ConfigurationProperties binds a whole group of related properties to one POJO — much cleaner than multiple @Value annotations.
  • Add @Validated to the properties class and JSR-303 annotations on fields — Spring Boot fails fast on startup if config is invalid.
  • Relaxed binding maps kebab-case YAML, camelCase Java, and UPPERCASE_ENV_VARS to the same field automatically.
  • Use a Java record (Boot 3+) for immutable, concise configuration properties without boilerplate getters/setters.
  • Add spring-boot-configuration-processor (optional, annotationProcessor scope) to unlock IDE auto-completion for your custom properties.
  • Nested objects are supported — group sub-settings in inner classes or nested records for clean hierarchies.
YAML + Java — @ConfigurationProperties
// application.yml
payment:
  gateway-url: https://api.stripe.com/v1
  api-key: sk_live_xxxx
  timeout-seconds: 30
  retry:
    max-attempts: 3
    back-off-ms: 500

// 1. Define the POJO
@ConfigurationProperties(prefix = "payment")
@Validated   // enables JSR-303 validation on fields
public class PaymentProperties {

    @NotBlank
    private String gatewayUrl;

    @NotBlank
    private String apiKey;

    @Min(1) @Max(120)
    private int timeoutSeconds;

    private Retry retry = new Retry();  // nested object

    // getters + setters (or use a record in Boot 3.x)

    public static class Retry {
        private int maxAttempts = 3;
        private long backOffMs = 500;
        // getters + setters
    }
}

// 2. Register (choose one approach)
@SpringBootApplication
@ConfigurationPropertiesScan   // scans for all @ConfigurationProperties in package
public class App { }

// 3. Inject anywhere
@Service
@RequiredArgsConstructor
public class PaymentService {
    private final PaymentProperties props;
    // props.getGatewayUrl(), props.getRetry().getMaxAttempts(), etc.
}
7

Spring Profiles

Profiles separate configuration per environment (dev, test, prod); beans annotated with @Profile or properties suffixed -dev.yml are activated selectively.

  • Profile-specific files follow the naming convention `application-{profile}.yml`; they override keys in the base `application.yml`.
  • Set `SPRING_PROFILES_ACTIVE` env var for production/K8s deployments — never hardcode the active profile in application.yml for prod.
  • Multiple profiles can be active simultaneously: `SPRING_PROFILES_ACTIVE=prod,datadog`.
  • @Profile on a @Bean or @Component registers it only when the profile matches; use `!prod` for "active in all non-prod environments".
  • @ActiveProfiles("test") in test classes activates a profile just for that test class without changing JVM arguments.
  • Profiles do not need to match environment names — you can create profiles for features: `spring.profiles.active=billing-v2`.
YAML — Profile Files
# application.yml — shared defaults
spring:
  application:
    name: order-service
  jpa:
    show-sql: false

logging:
  level:
    root: INFO

---
# application-dev.yml — local dev overrides
spring:
  datasource:
    url: jdbc:h2:mem:devdb
    driver-class-name: org.h2.Driver
  jpa:
    show-sql: true    # override: show SQL locally

logging:
  level:
    com.example: DEBUG  # verbose logging in dev

---
# application-prod.yml — production
spring:
  datasource:
    url: ${DB_URL}      # injected from env var / Kubernetes Secret
    username: ${DB_USER}
    password: ${DB_PASS}
8

Spring Boot DevTools

Provides automatic application restart on classpath changes, live reload for static resources, and relaxed property defaults during development.

  • DevTools uses two classloaders: base (libs) + restart (app code) — only restart classloader reloads on change
  • Declare as optional/developmentOnly so it never ends up in the production fat-jar
  • LiveReload server starts on port 35729 and integrates with the LiveReload browser extension
  • Template caches (Thymeleaf, FreeMarker) are disabled automatically — no need to configure
  • Trigger-file mode prevents spurious restarts in IDEs that save files aggressively
  • Remote DevTools allows restarting a remote app via a secure tunnel — use only in controlled staging environments
Maven / Gradle — DevTools dependency
<!-- Maven -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

// Gradle
dependencies {
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
}
9

Embedded Servers

Spring Boot embeds Tomcat, Jetty, or Undertow directly in the fat JAR, removing the need to deploy WARs to external containers.

  • Embedded servers (Tomcat/Jetty/Undertow/Netty) are packaged in the JAR — no WAR deployment needed.
  • java -jar app.jar is all that's required to start — simplifies cloud/container deployment.
  • server.port, server.ssl.*, and server.tomcat.* cover most tuning needs via properties.
  • WebServerFactoryCustomizer<T> allows programmatic server configuration beyond properties.
  • server.shutdown=graceful lets in-flight requests complete before shutdown.
  • HTTP/2 is supported but requires SSL — enable with server.http2.enabled=true.
Properties — embedded server configuration
# application.properties — embedded server config

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

# SSL (enable HTTPS)
server.ssl.enabled=true
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-type=PKCS12
server.ssl.key-store-password=${SSL_KEYSTORE_PASSWORD}

# Tomcat-specific tuning
server.tomcat.max-threads=200          # max worker threads
server.tomcat.min-spare-threads=20     # min idle threads
server.tomcat.accept-count=100         # queue length when all threads busy
server.tomcat.connection-timeout=20000 # ms before idle connection dropped

# Undertow-specific
server.undertow.threads.io=4           # IO threads (= CPU cores typically)
server.undertow.threads.worker=32      # worker threads

# HTTP/2 support (requires SSL)
server.http2.enabled=true

# Compression
server.compression.enabled=true
server.compression.mime-types=text/html,text/plain,application/json
server.compression.min-response-size=1024
10

Conditional Beans (@ConditionalOn*)

@ConditionalOnClass, @ConditionalOnProperty, and friends let you register beans only when specific conditions on the classpath or environment hold true.

  • @ConditionalOnClass guards auto-configuration beans on classpath presence
  • @ConditionalOnMissingBean is the override hook — user-defined beans take precedence
  • @ConditionalOnProperty enables/disables features via application.properties flags
  • @ConditionalOnExpression evaluates SpEL for multi-property conditions
  • All @ConditionalOn* annotations are built on @Conditional(SomeCondition.class)
  • matchIfMissing=true on @ConditionalOnProperty enables the bean when the property is absent
Spring Boot — @ConditionalOnClass / MissingBean / Property
@Configuration
@ConditionalOnClass(DataSource.class)            // only if JDBC is on classpath
public class DataSourceAutoConfig {

    @Bean
    @ConditionalOnMissingBean(DataSource.class)  // default — user can override
    public DataSource defaultDataSource(DataSourceProperties props) {
        return DataSourceBuilder.create()
                .url(props.getUrl())
                .username(props.getUsername())
                .password(props.getPassword())
                .build();
    }
}

@Bean
@ConditionalOnProperty(
    name         = "feature.cache.enabled",
    havingValue  = "true",
    matchIfMissing = false      // don't create bean if property absent
)
public CacheManager cacheManager() {
    return new ConcurrentMapCacheManager("users");
}
11

Spring Framework & IoC

The Spring Framework is built on Inversion of Control (IoC) — you declare what you need, the container creates and wires it. Understanding the IoC container is the foundation of everything else in Spring.

  • IoC container creates and wires objects — you declare dependencies, Spring fulfills them.
  • ApplicationContext is the full-featured IoC container used in Spring Boot apps.
  • Constructor injection is preferred: makes dependencies explicit, enables final fields, fails fast.
  • Field injection (@Autowired on fields) hides dependencies and breaks unit testing without Spring.
  • Beans are singletons by default — one instance shared across the entire application.
  • @PostConstruct and @PreDestroy handle bean lifecycle hooks.
Java — ApplicationContext bean lifecycle
// The container reads @Component, @Service, @Repository, @Controller, @Bean
// and builds a map of name → bean instance

// Conceptually what the container does:
// 1. Scan classpath for annotated classes (@ComponentScan)
// 2. Instantiate each bean (constructor or no-arg + setters)
// 3. Inject dependencies (constructor injection preferred)
// 4. Call @PostConstruct lifecycle methods
// 5. Register the bean, ready to serve

// Accessing the container directly (rarely needed):
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(App.class, args);

        // Look up a bean by type
        UserService userService = ctx.getBean(UserService.class);

        // Inspect registered bean names
        String[] names = ctx.getBeanDefinitionNames();
    }
}
12

Spring Boot Setup

Spring Boot eliminates boilerplate setup through auto-configuration and starter dependencies. A production-ready app can be running in under 5 minutes with the right project structure.

  • spring-boot-starter-parent manages all dependency versions — never specify library versions manually.
  • Starters bundle related libraries with compatible versions; you pick the feature, Spring picks the versions.
  • @SpringBootApplication must be in the root package for @ComponentScan to find all sub-packages.
  • Auto-configuration is conditional — it backs off when you declare your own beans.
  • spring-boot-maven-plugin produces a fat executable JAR runnable with java -jar.
  • Use application-{profile}.yml for environment-specific overrides (dev, prod, test).
XML — pom.xml with common starters
<!-- pom.xml — minimal Spring Boot web app -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.3.0</version>
</parent>

<dependencies>
    <!-- Web: Tomcat + Spring MVC + Jackson -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

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

    <!-- PostgreSQL driver -->
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- Test: JUnit 5, Mockito, MockMvc -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <!-- Builds executable fat JAR with java -jar -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
13

Dependency Injection

Spring's DI container wires your application together. Understanding @Component stereotypes, @Bean factory methods, @Qualifier disambiguation, and scope is essential for every Spring developer.

  • @Service, @Repository, @Controller are specializations of @Component — use them to communicate layer intent.
  • @Repository adds persistence exception translation: vendor SQLExceptions → Spring DataAccessException.
  • Use @Bean methods in @Configuration classes for third-party objects or beans needing complex setup.
  • @Primary sets a default when multiple beans satisfy a type; @Qualifier picks a specific named bean.
  • Singleton scope (default) means one shared instance — never store mutable request state in a singleton.
  • Prototype scope creates a new instance per injection; request scope creates one per HTTP request.
Java — @Service, @Repository, @Component
// @Service — business logic, no extra framework magic
@Service
public class UserService {
    private final UserRepository userRepository;
    private final EmailService emailService;

    public UserService(UserRepository userRepository, EmailService emailService) {
        this.userRepository = userRepository;
        this.emailService = emailService;
    }

    public User register(RegisterRequest req) {
        if (userRepository.existsByEmail(req.email())) {
            throw new EmailAlreadyExistsException(req.email());
        }
        User user = new User(req.email(), passwordEncoder.encode(req.password()));
        User saved = userRepository.save(user);
        emailService.sendWelcome(saved); // fire and forget
        return saved;
    }
}

// @Repository — data access layer
// Also translates SQLExceptions to DataAccessException
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByEmail(String email);
    boolean existsByEmail(String email);
}

// Plain @Component — doesn't fit other stereotypes
@Component
public class SlugGenerator {
    public String generate(String title) {
        return title.toLowerCase().replaceAll("\s+", "-");
    }
}
14

Application Configuration

application.yml is the central config file. @ConfigurationProperties binds whole config sections to typed classes — the recommended approach for anything beyond a single value. @Value injects individual properties.

  • @ConfigurationProperties is preferred for multi-property sections — type-safe, validatable, IDE-autocompletable.
  • @Value("${prop:default}") injects a single property with an optional fallback default.
  • Command-line args > env vars > application-{profile}.yml > application.yml — env vars always win.
  • Never hardcode secrets in YAML — use ${ENV_VAR} references and set them in the runtime environment.
  • @ConfigurationPropertiesScan on @SpringBootApplication auto-registers all @ConfigurationProperties.
  • Use profile-specific files (application-prod.yml) for environment differences, not if/else in code.
YAML + Java — @ConfigurationProperties with validation
// application.yml
app:
  jwt:
    secret: ${JWT_SECRET}          # from env var
    expiry-minutes: 60
  email:
    provider: resend
    api-key: ${EMAIL_API_KEY}
    from: noreply@aicancode.org
  rate-limit:
    requests-per-minute: 100
    burst-capacity: 200

// --- Java config class (Java record — Spring Boot 3+) ---
@ConfigurationProperties(prefix = "app.jwt")
public record JwtProperties(
    @NotBlank String secret,
    @Min(5) @Max(1440) int expiryMinutes
) {}

@ConfigurationProperties(prefix = "app.email")
public record EmailProperties(
    @NotBlank String provider,
    @NotBlank String apiKey,
    @Email String from
) {}

// Register in main class
@SpringBootApplication
@ConfigurationPropertiesScan // picks up all @ConfigurationProperties in package
public class App { ... }

// Inject and use
@Service
public class JwtService {
    private final JwtProperties jwt;

    public JwtService(JwtProperties jwt) { this.jwt = jwt; }

    public String generateToken(String userId) {
        return Jwts.builder()
            .subject(userId)
            .expiration(Date.from(Instant.now()
                .plusSeconds(jwt.expiryMinutes() * 60L)))
            .signWith(Keys.hmacShaKeyFor(jwt.secret().getBytes()))
            .compact();
    }
}
Learn this free with Aria, your AI tutor → AiCanCode.org/learn/spring-boot