Spring Boot 3.4: Tüm yenilikler detaylı anlatım

Spring Boot 3.4, yerel yapılandırılmış loglama, genişletilmiş virtual thread desteği, varsayılan graceful shutdown ve MockMvcTester getiriyor. Yeni özelliklerin eksiksiz rehberi.

Spring Boot 3.4 yeni özellikler ve iyileştirmeler

Spring Boot 3.4, Kasım 2024'te yayınlandı ve geliştirici üretkenliği ile uygulama performansında önemli iyileştirmeler sunuyor. Bu sürüm yerel yapılandırılmış loglamayı tanıtıyor, graceful shutdown'ı varsayılan olarak etkinleştiriyor ve virtual thread desteğini framework genelinde genişletiyor.

Ön Koşullar

Spring Boot 3.4, minimum Java 17 gerektirir ve virtual threads için Java 21'i destekler. Bu sürüm Spring Framework 6.2 kullanır.

Yerel yapılandırılmış loglama

Yapılandırılmış loglama, uygulama gözlemlenebilirliği için önemli bir ilerleme temsil eder. Analiz edilmesi zor metin tabanlı loglar yerine, Spring Boot 3.4 Elasticsearch, Grafana Loki veya Datadog gibi araçlar tarafından tüketilebilen JSON formatında loglar üretir.

Üç format yerel olarak desteklenir: Elastic Common Schema (ECS), Logstash ve Graylog Extended Log Format (GELF).

properties
# application.properties
# Enable structured logging in console
logging.structured.format.console=ecs

# Or for log files
logging.structured.format.file=logstash

Bu basit yapılandırma otomatik olarak formatlanmış yapılandırılmış JSON logları üretir.

LoggingController.javajava
@RestController
@RequestMapping("/api/demo")
public class LoggingController {

    // Logger injection via SLF4J
    private static final Logger logger = LoggerFactory.getLogger(LoggingController.class);

    @GetMapping("/action")
    public ResponseEntity<String> performAction(@RequestParam String userId) {
        // Log will be automatically formatted as structured JSON
        logger.info("Action performed by user: {}", userId);
        return ResponseEntity.ok("Action completed");
    }
}

ECS formatı etkinleştirildiğinde, bu log timestamp, seviye, mesaj, sınıf adı, thread ve uygulama metaverisi içeren bir JSON nesnesine dönüşür. Bu yapı, izleme platformlarında arama ve toplamayı kolaylaştırır.

Varsayılan olarak etkin Graceful Shutdown

Önemli değişiklik: graceful shutdown artık varsayılan olarak etkin. Devam eden HTTP istekleri sunucu kapatılmadan önce işlenir, bu da dağıtımlar sırasında 502 hatalarını önler.

properties
# application.properties
# Graceful shutdown is now ON by default
# To restore previous behavior (immediate shutdown):
server.shutdown=immediate

# Configure maximum wait timeout (30s default)
spring.lifecycle.timeout-per-shutdown-phase=45s

Bu davranış tüm gömülü sunucular için geçerlidir: Tomcat, Jetty, Undertow ve Reactor Netty.

LifecycleConfig.javajava
@Configuration
public class LifecycleConfig {

    private static final Logger logger = LoggerFactory.getLogger(LifecycleConfig.class);

    @Bean
    public ApplicationListener<ContextClosedEvent> gracefulShutdownListener() {
        // This listener executes at shutdown start
        return event -> {
            logger.info("Graceful shutdown initiated - completing in-flight requests");
            // Custom logic: close connections, save state, etc.
        };
    }
}

Bu iyileştirme, çoğu durumda ek yapılandırma gerektirmeden sıfır kesinti süreli dağıtımların uygulanmasını kolaylaştırır.

Genişletilmiş Virtual Thread desteği

Spring Boot 3.4, virtual thread desteğini (Java 21+) daha fazla bileşene genişletir. OtlpMeterRegistry ve Undertow sunucusu artık etkinleştirildiğinde virtual thread kullanır.

properties
# application.properties
# Enable virtual threads globally
spring.threads.virtual.enabled=true

Bu tek özellik, uygulamanın thread modelini dönüştürür. Her HTTP isteği kendi virtual thread'ini alır ve thread havuzunu tüketmeden binlerce eşzamanlı bağlantıya olanak tanır.

AsyncService.javajava
@Service
public class AsyncService {

    private static final Logger logger = LoggerFactory.getLogger(AsyncService.class);

    // With virtual threads enabled, each blocking call
    // no longer consumes an OS thread
    public String fetchExternalData() {
        logger.info("Executing on thread: {}", Thread.currentThread());

        // Blocking HTTP call - with virtual threads,
        // the OS thread is released during I/O wait
        return restClient.get()
            .uri("https://api.external.com/data")
            .retrieve()
            .body(String.class);
    }
}

Virtual thread'ler I/O yoğun uygulamalarda parlıyor: HTTP çağrıları, veritabanı sorguları, dosya işlemleri. İşletim sistemi thread'i bekleme süresinde serbest bırakılır ve devam ettiğinde yeniden atanır.

Uyumluluk

Virtual thread'ler minimum Java 21 gerektirir. Java 17'de bu özellik yoksayılır ve klasik davranış uygulanır.

Geliştirilmiş RestClient ve RestTemplate

Spring Boot 3.4, HTTP istemci yapılandırmasını normalleştirir. HttpRequestFactory seçimi artık classpath'e dayalı net bir öncelik sırasını takip eder.

HttpClientConfig.javajava
@Configuration
public class HttpClientConfig {

    @Bean
    public RestClient restClient(RestClient.Builder builder) {
        // Spring Boot automatically chooses implementation:
        // 1. Apache HTTP Components (if present)
        // 2. Jetty Client
        // 3. Reactor Netty
        // 4. JDK HttpClient (Java 11+)
        // 5. SimpleClientHttpRequestFactory (fallback)
        return builder
            .baseUrl("https://api.example.com")
            .defaultHeader("Accept", "application/json")
            .build();
    }
}

Yönlendirme davranışı yapılandırması da basitleştirilmiştir.

properties
# application.properties
# Force specific implementation
spring.http.client.factory=jdk

# Configure redirect behavior
spring.http.client.redirects=dont-follow

Daha ayrıntılı kontrol için yeni ClientHttpRequestFactoryBuilder tam programatik yapılandırmaya olanak tanır.

CustomHttpClientConfig.javajava
@Configuration
public class CustomHttpClientConfig {

    @Bean
    public RestClient customRestClient(ClientHttpRequestFactoryBuilder factoryBuilder) {
        // Advanced factory configuration
        ClientHttpRequestFactory factory = factoryBuilder
            .httpComponents()
            .connectTimeout(Duration.ofSeconds(5))
            .readTimeout(Duration.ofSeconds(30))
            .build();

        return RestClient.builder()
            .requestFactory(factory)
            .baseUrl("https://api.example.com")
            .build();
    }
}

Bu yaklaşım, temel HTTP uygulamasından bağımsız olarak tutarlı bir API ile maksimum esneklik sunar.

Spring Boot mülakatlarında başarılı olmaya hazır mısın?

İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.

Akıcı test için MockMvcTester

Spring Boot 3.4, MockMvc'ye AssertJ tabanlı bir alternatif olan MockMvcTester'ı tanıtır. Bu yeni yaklaşım testleri daha okunabilir ve ifade edici kılar.

UserControllerTest.javajava
@WebMvcTest(UserController.class)
class UserControllerTest {

    @Autowired
    private MockMvcTester mockMvc; // New class!

    @Test
    void shouldReturnUserById() {
        // Fluent API with AssertJ
        mockMvc.get().uri("/api/users/{id}", 1)
            .assertThat()
            .hasStatusOk()
            .hasContentType(MediaType.APPLICATION_JSON)
            .bodyJson()
            .extractingPath("$.name")
            .isEqualTo("John Doe");
    }

    @Test
    void shouldReturn404ForUnknownUser() {
        mockMvc.get().uri("/api/users/{id}", 999)
            .assertThat()
            .hasStatus(HttpStatus.NOT_FOUND)
            .bodyJson()
            .extractingPath("$.error")
            .isEqualTo("User not found");
    }
}

MockMvc kullanan eski yaklaşımla karşılaştırıldığında, doğrulamalar daha özlü ve zincirleme daha doğal hissettiriyor.

ComparisonTest.javajava
@WebMvcTest(UserController.class)
class ComparisonTest {

    @Autowired
    private MockMvcTester mockMvcTester;

    @Autowired
    private MockMvc mockMvc;

    @Test
    void withMockMvcTester() {
        // New approach: fluent and concise
        mockMvcTester.post().uri("/api/users")
            .contentType(MediaType.APPLICATION_JSON)
            .content("{\"name\": \"Jane\"}")
            .assertThat()
            .hasStatus(HttpStatus.CREATED)
            .hasHeader("Location", "/api/users/2");
    }

    @Test
    void withClassicMockMvc() throws Exception {
        // Old approach: more verbose
        mockMvc.perform(post("/api/users")
                .contentType(MediaType.APPLICATION_JSON)
                .content("{\"name\": \"Jane\"}"))
            .andExpect(status().isCreated())
            .andExpect(header().string("Location", "/api/users/2"));
    }
}

MockMvcTester, classpath'te AssertJ mevcut olduğunda otomatik olarak yapılandırılır (spring-boot-starter-test ile varsayılan olarak dahildir).

Geliştirilmiş Docker Compose ve Testcontainers

Docker Compose desteği, birden fazla yapılandırma dosyası ve özel argümanlarla esneklik kazanır.

properties
# application.properties
# Use multiple Docker Compose files
spring.docker.compose.file=compose.yaml,compose-dev.yaml

# Pass arguments at startup
spring.docker.compose.start.arguments=--scale redis=2

# Arguments at shutdown
spring.docker.compose.stop.arguments=--timeout 60

Yeni servisler otomatik olarak algılanır ve yapılandırılır.

yaml
# compose.yaml
services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    ports:
      - "5432:5432"

  redis-stack:
    image: redis/redis-stack:latest
    ports:
      - "6379:6379"
      - "8001:8001" # RedisInsight UI

  grafana-lgtm:
    image: grafana/otel-lgtm:latest
    ports:
      - "3000:3000"  # Grafana
      - "4317:4317"  # OTLP gRPC

Spring Boot 3.4 bu servisleri otomatik olarak algılar ve ilgili bağlantı özelliklerini yapılandırır.

Testcontainers ile test için yeni konteynerler desteklenir.

IntegrationTestConfig.javajava
@TestConfiguration(proxyBeanMethods = false)
public class IntegrationTestConfig {

    @Bean
    @ServiceConnection
    public PostgreSQLContainer<?> postgresContainer() {
        return new PostgreSQLContainer<>("postgres:16");
    }

    @Bean
    @ServiceConnection
    public RedisStackContainer redisStackContainer() {
        // New Redis Stack support
        return new RedisStackContainer("redis/redis-stack:latest");
    }

    @Bean
    @ServiceConnection
    public LgtmStackContainer observabilityContainer() {
        // New Grafana LGTM support (Loki, Grafana, Tempo, Mimir)
        return new LgtmStackContainer("grafana/otel-lgtm:latest");
    }
}

@ServiceConnection anotasyonu bağlantı özelliklerini otomatik olarak yapılandırır ve çoğu durumda @DynamicPropertySource gereksinimini ortadan kaldırır.

Actuator SSL ve gözlemlenebilirlik

Yeni /actuator/info endpoint'i artık yapılandırılmış SSL sertifikaları hakkında bilgi sunar: geçerlilik tarihleri, veren ve konu.

properties
# application.properties
# Enable SSL information in actuator
management.info.ssl.enabled=true

# Configure warning threshold for expiring certificates
management.health.ssl.certificate-validity-warning-threshold=30d

Bu özellik, sertifika sona ermesinin doğrudan actuator üzerinden izlenmesini sağlayarak yenileme otomasyonunu kolaylaştırır.

SslMonitoringConfig.javajava
@Configuration
public class SslMonitoringConfig {

    @Bean
    public HealthIndicator sslCertificateHealth(SslInfo sslInfo) {
        return () -> {
            // Custom certificate validity check
            boolean allValid = sslInfo.getBundles().values().stream()
                .flatMap(bundle -> bundle.getCertificates().stream())
                .allMatch(cert -> cert.getValidityEnds().isAfter(Instant.now()));

            return allValid
                ? Health.up().build()
                : Health.down().withDetail("reason", "Certificate expiring soon").build();
        };
    }
}

Gözlemlenebilirlik için OTLP taşıması artık HTTP'ye ek olarak gRPC'yi destekler.

properties
# application.properties
# Use gRPC for OTLP (traces and metrics)
management.otlp.tracing.transport=grpc
management.otlp.tracing.endpoint=http://localhost:4317

# New: group applications together
spring.application.group=payment-services

Uygulama grubu (spring.application.group) gözlemlenebilirlik panolarında birden fazla servisin mantıksal olarak gruplandırılmasını sağlar.

Daha hafif OCI imajları

Varsayılan OCI imaj oluşturucusu paketobuildpacks/builder-jammy-base'den paketobuildpacks/builder-jammy-java-tiny'ye değişir ve önemli ölçüde daha küçük imajlar üretir.

build.gradlegroovy
tasks.named("bootBuildImage") {
    // Native ARM support (new)
    imagePlatform = "linux/arm64"

    // New security flag
    trustBuilder = false

    // Image configuration
    imageName = "myregistry.com/myapp:${version}"
}

Yeni imagePlatform parametresi ARM ve x64 için platformlar arası derlemeyi kolaylaştırır.

xml
<!-- pom.xml -->
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <image>
            <!-- Native ARM support -->
            <platform>linux/arm64</platform>
            <!-- Builder optimized for minimal images -->
            <builder>paketobuildpacks/builder-jammy-java-tiny</builder>
        </image>
    </configuration>
</plugin>

Bu optimize edilmiş imajlar daha hızlı başlar ve daha az kaynak tüketir, özellikle Kubernetes dağıtımları için avantajlıdır.

Geçiş Notu

Oluşturucu değişikliği, belirli sistem araçlarına bağımlı uygulamaları etkileyebilir. Yeni imajlar üretime dağıtılmadan önce test edilmelidir.

Bean Validation değişiklikleri

Spring Boot 3.4, doğrulama davranışını Bean Validation spesifikasyonuyla uyumlu hale getirir. Doğrulama artık iç içe özelliklere otomatik olarak yayılmaz.

ConfigProperties.javajava
@ConfigurationProperties(prefix = "app")
@Validated
public class AppConfig {

    @NotBlank
    private String name;

    // IMPORTANT: @Valid required to cascade validation
    @Valid
    private DatabaseConfig database;

    // Without @Valid, ServerConfig constraints will NOT be checked
    private ServerConfig server;

    // Getters and setters
}

public class DatabaseConfig {
    @NotBlank
    private String url;

    @Min(1)
    private int poolSize;

    // Getters and setters
}

public class ServerConfig {
    @NotNull // This constraint will NOT be checked without @Valid on parent
    private Integer port;

    // Getters and setters
}

Bu değişiklik mevcut uygulamaları etkileyebilir. @ConfigurationProperties sınıfları kontrol edilmeli ve doğrulamanın yayılması gereken yerlere @Valid eklenmelidir.

@MockBean ve @SpyBean kullanımdan kaldırma

Spring Boot'un @MockBean ve @SpyBean anotasyonları, yeni Mockito anotasyonları lehine kullanımdan kaldırıldı.

UserServiceTest.java (new approach)java
@SpringBootTest
class UserServiceTest {

    // New: native Mockito annotations
    @MockitoBean
    private UserRepository userRepository;

    @MockitoSpyBean
    private EmailService emailService;

    @Autowired
    private UserService userService;

    @Test
    void shouldCreateUser() {
        // Mock configuration
        when(userRepository.save(any())).thenReturn(new User(1L, "test@example.com"));

        userService.createUser("test@example.com");

        // Spy verification
        verify(emailService).sendWelcomeEmail("test@example.com");
    }
}

Eski anotasyonlar hala çalışıyor ancak kullanımdan kaldırma uyarıları gösteriyor. @MockitoBean ve @MockitoSpyBean'e geçiş planlanmalıdır.

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

Sonuç

Spring Boot 3.4, üretkenlik ve gözlemlenebilirlikte önemli iyileştirmeler sunar:

Geçiş kontrol listesi:

  • Daha iyi gözlemlenebilirlik için yapılandırılmış loglamayı etkinleştirin
  • Graceful shutdown davranışını doğrulayın (artık varsayılan olarak etkin)
  • I/O yoğun uygulamalar için virtual thread'leri değerlendirin (Java 21+)
  • Daha okunabilir testler için MockMvcTester'a geçiş yapın
  • İç içe @ConfigurationProperties özelliklerine @Valid ekleyin
  • @MockBean/@SpyBean'i @MockitoBean/@MockitoSpyBean ile değiştirin
  • Yeni OCI imajlarını üretime dağıtımdan önce test edin

Spring Boot 3.4, gözlemlenebilirlik standartları ve performansa özel ilgi göstererek modern Java geliştirme için referans framework olarak konumunu güçlendirir.

Kaynaklar:

Etiketler

#spring boot
#java
#spring boot 3.4
#spring framework
#backend

Paylaş

İlgili makaleler