Spring Annotations: The 2026 Essential Cheat Sheet

Spring 7, the foundation of Spring Boot 4, introduces several useful annotations that reduce boilerplate even further by adding native support for resilience, API versioning, and null-safety. This cheat sheet will guide you through the most important annotations and best practices for 2026.

Core Spring Stereotypes

These annotations remain the foundation of your Spring applications:

  • @Component: Generic bean. Use for internal utilities.
  @Component
  public class MyHelper { ... }
  • @Service: Business logic layer. While @Service itself is a stereotype, Spring 7’s execution model is fully compatible with Virtual Threads, making service-layer code simpler and safer under high concurrency.

Dependency Injection & Configuration

  • @Autowired: Still exists, but Constructor Injection is now the absolute industry standard. Useful for tests. In Spring Boot 4, @Autowired is often omitted entirely on single-constructor classes.
  • @Bean: Registers a method-level bean.
  • @Configuration: Replaces XML-based configuration. Spring Boot 4 uses modular autoconfiguration for faster GraalVM native image startup.

Spring Boot 4 has moved toward a Modular Autoconfiguration model. Many old "starters" have been split into smaller, more focused modules to improve GraalVM native image startup times. For example, web, validation, and JSON support are now more decoupled, allowing smaller native images.

  • @ConfigurationProperties: Preferred over @Value. Works with Java Records for type-safe, immutable configuration.
@ConfigurationProperties(prefix = "app") public record AppConfig(String name, int timeout) { }

New in Spring 7: API Versioning :)

@RestController @RequestMapping("/products") @ApiVersion("v1") public class ProductControllerV1 {
  @GetMapping public List<ProductDto> getProducts() { return List.of(); } }
  ...
}

can coexist with:

@RestController @RequestMapping("/products") @ApiVersion("v2") public class ProductControllerV2 {
@GetMapping public List<ProductV2Dto> getProducts() { return List.of(); } }

You can also use the version at method level:

@GetMapping(path = "/{id}", version = "2.0+") // New version attribute public Product getProductV2(@PathVariable Long id) { return repository.findById(id).orElseThrow(); }

API versioning can be resolved via headers, media types, or URL strategies depending on configuration.

New in Spring 7: Resilience & Concurrency

Spring 7 introduces first-class resilience annotations (either natively or via officially supported modules), reducing the need for third-party libraries in most cases.

  • @Retryable: Automatically retries a failed operation with built-in backoff logic.
@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 2000))
public void callExternalService() { ... }
  • @Recover: Fallback method for exhausted retries:
@Recover public void handleExternalServiceError(Exception e) { ... }
  • @Timeout: Cuts off long-running operations declaratively.
  • @ConcurrencyLimit: Essential for apps using Virtual Threads to prevent saturating external resources (like databases). Remember that with Virtual Threads there is no number of predefined threads.

Combine @Retryable + @ConcurrencyLimit to avoid saturating external services.

@Configuration @EnableResilientMethods // The switch for @Retryable and @ConcurrencyLimit public class ResilienceConfig { // Standard configuration class }

JSpecify - Null safety in Spring 7 and Spring Boot 4

Spring 7 has fully embraced JSpecify for standardized null-safety across the Java ecosystem.

  • @NonNull: Explicitly marks a parameter or return type as never null.
  • @Nullable: Indicates that a null value is expected and must be handled.
  • @NullMarked: Package-level default for non-nullable types.

You can use @NullMarked at the package level to make "Non-Null" the default for all classes in that package.

@NonNull
public String getUsername() { ... }

Data & Persistence

With Spring 7 there is the support for JakartaEE 11 including Jakarta Data 1.0 and JPA 3.2.

With the update, Java Records can be used for immutable projections:

 java public record ProductView( @Id Long id, String name, BigDecimal price ) {}
@Repository public interface ProductRepository {
Optional<ProductView> findById(Long id); }
  • @Transactional: Maintain data integrity; place on the Service layer (class or method, better method-level) not Repository layer.
  • @Entity: Marks a JPA entity. Many developers now use Java Records with Jakarta Data @Id for read-only DTOs.

Quick Reference Table

Annotation Layer / Use Case Notes
@Component Generic bean Utilities / internal classes
@Service Business logic Virtual Thread–friendly execution model
@Repository Data access Works with Jakarta Data
@RestController REST APIs Supports API Versioning
@Retryable Resilience Retry failed operations
@ConcurrencyLimit Resource protection Works with Virtual Threads
@Timeout Resilience Declares max execution time
@Transactional Service layer Ensures business atomicity
@NonNull/@Nullable Null safety Enforce null contracts

Code example

ProductService.java @Service @NullMarked // JSpecify default for the whole class public class ProductService {
private final ExternalApiClient client;
// injection using the constructor public ProductService(ExternalApiClient client) { this.client = client; }
@Transactional @Retryable(retryFor = {RemoteException.class}, maxAttempts = 3) @ConcurrencyLimit(10) // Protects the Virtual Thread pool public void processOrder(@NonNull String orderId) { client.call(orderId); } }