Mastering Spring Boot: 10 Advanced Techniques to Design, Optimize, and Operate Your Apps

This guide explores ten advanced Spring Boot features—including conditional auto‑configuration, configuration‑property precedence, asynchronous execution, task scheduling, startup and JVM tuning, test context caching, Actuator monitoring, security setup, multi‑datasource configuration, custom starter creation, and cloud‑native deployment—to help developers move from users to masters of the framework.

Senior Xiao Ying
Senior Xiao Ying
Senior Xiao Ying
Mastering Spring Boot: 10 Advanced Techniques to Design, Optimize, and Operate Your Apps

1. Auto‑configuration mechanism

Spring Boot’s auto‑configuration is driven by conditional annotations. At startup it scans

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

and activates configuration classes whose @Conditional annotations match. Core annotations include @ConditionalOnClass (active when a class is on the classpath), @ConditionalOnMissingBean (active when a bean type is absent), and @ConditionalOnProperty (active when a property is defined).

Example of a simplified DataSource auto‑configuration:

@Configuration
// When DataSource class is present
@ConditionalOnClass(DataSource.class)
// When no DataSource bean exists
@ConditionalOnMissingBean(DataSource.class)
// When spring.datasource.url property is set
@ConditionalOnProperty(prefix = "spring.datasource", name = "url")
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
    @Bean
    public DataSource dataSource(DataSourceProperties properties) {
        return DataSourceBuilder.create()
                .url(properties.getUrl())
                .username(properties.getUsername())
                .password(properties.getPassword())
                .build();
    }
}

2. Configuration‑loading precedence

When the same property appears in multiple locations, Spring Boot applies a defined order, higher‑priority sources overriding lower ones. The order (high → low) is:

Command‑line arguments (e.g., java -jar app.jar --server.port=8081)

JVM system properties (e.g., -Dspring.profiles.active=prod)

OS environment variables (e.g., SPRING_DATASOURCE_URL) /config directory inside the project /config directory on the classpath

Root‑level application.properties or application.yml In production, sensitive values such as database passwords can be supplied via the highest‑priority environment variables while generic settings remain in application‑prod.yml, achieving both security and configuration separation.

3. Asynchronous execution and scheduling

Enabling @Async and @Scheduled can dramatically increase throughput and simplify periodic tasks. To activate them, add @EnableAsync and @EnableScheduling to the main application class:

@SpringBootApplication
@EnableAsync          // enable async execution
@EnableScheduling    // enable scheduled tasks
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Typical async mail service:

@Service
public class EmailService {
    @Async
    public CompletableFuture<String> sendEmail(String content) {
        try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
        return CompletableFuture.completedFuture("Sent: " + content);
    }
}

Scheduled task examples:

@Component
public class ScheduledTasks {
    // Run daily at 02:00
    @Scheduled(cron = "0 0 2 * * ?")
    public void cleanTempFiles() {
        System.out.println("Cleaning temporary files...");
    }
    // Fixed‑rate every 5 seconds
    @Scheduled(fixedRate = 5000)
    public void performHealthCheck() {
        // health‑check logic
    }
}

Configuring a dedicated thread pool for async work is recommended to avoid resource exhaustion:

@Configuration
public class AsyncConfig {
    @Bean("taskExecutor")
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("Async-");
        executor.initialize();
        return executor;
    }
}

4. Performance tuning

Performance concerns include startup time and runtime memory. Enabling lazy initialization in application.properties ( spring.main.lazy-initialization=true) speeds up boot but may delay the first request. JVM memory settings differ between development ( -Xms512m -Xmx1024m) and production micro‑services ( -Xms1g -Xmx2g -XX:MetaspaceSize=256m).

5. Integration‑test optimization

Large projects suffer slow @SpringBootTest execution due to repeated context creation. Spring Test caches contexts based on the MergedContextConfiguration; identical configurations reuse the same context. Overusing @DirtiesContext forces a reset and should be avoided. Design test configurations to maximize cache reuse.

6. Actuator and observability

Spring Boot Actuator adds production‑grade monitoring endpoints. After adding the spring-boot-starter-actuator dependency, expose endpoints via

management.endpoints.web.exposure.include=health,info,metrics,env

. Access health at http://host:port/actuator/health and metrics at /actuator/metrics to view JVM memory, threads, etc.

7. Security basics

Using Spring Security, a minimal configuration can protect all routes except those explicitly permitted:

@Configuration
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(authz -> authz
                .requestMatchers("/public/**").permitAll()
                .anyRequest().authenticated())
            .formLogin(withDefaults());
        return http.build();
    }
}

8. Advanced data access

Multiple data sources require disabling the default auto‑configuration and defining each source and its EntityManager. Example for a primary datasource:

@Configuration
@EnableJpaRepositories(
    basePackages = "com.example.repository.primary",
    entityManagerFactoryRef = "primaryEntityManagerFactory")
public class PrimaryDataSourceConfig {
    @Bean @Primary @ConfigurationProperties("spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }
    @Bean @Primary
    public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(
            EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(primaryDataSource())
                .packages("com.example.model.primary")
                .build();
    }
}

A similar configuration can be created for a secondary datasource.

9. Custom starter creation

Packaging reusable functionality as a custom starter involves an auto‑configuration class and a properties holder. Example:

@Configuration
@ConditionalOnClass(MyService.class)
@EnableConfigurationProperties(MyServiceProperties.class)
public class MyServiceAutoConfiguration {
    @Bean @ConditionalOnMissingBean
    public MyService myService(MyServiceProperties properties) {
        return new MyService(properties.getPrefix(), properties.getSuffix());
    }
}
@ConfigurationProperties("my.service")
public class MyServiceProperties {
    private String prefix = "DefaultPrefix";
    private String suffix = "DefaultSuffix";
    // getters and setters omitted
}

10. Cloud‑native integration

Spring Boot naturally fits cloud‑native environments. Configuration can be externalized via ConfigMaps in Kubernetes, injected through environment variables or volume mounts. Actuator’s /actuator/health endpoint serves as a readiness and liveness probe for Kubernetes.

Spring Boot diagram
Spring Boot diagram
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

SchedulingSpring BootsecurityasyncAuto-ConfigurationMulti-DataSourceactuatorCustom Starter
Senior Xiao Ying
Written by

Senior Xiao Ying

Dedicated to sharing Java backend technical experience and original tutorials, offering career transition advice and resume editing. Recognized as a rising star in CSDN's Java backend community and ranked Top 3 in the 2022 New Star Program for Java backend.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.