Skip to main content

Spring Boot Annotations List: Every Annotation You Need, with Real Examples

A grouped list of the Spring Boot annotations you will actually use, plus the pairs people confuse (@Component vs @Bean, @Controller vs @RestController, @Primary vs @Qualifier) with real output.

A Spring Boot annotation is metadata on a class, method or parameter that tells Spring what to create, wire, expose or intercept, so you write behaviour and not boilerplate. This page lists the annotations you will meet in a real Boot 4 project, grouped by job, then spends its length on the pairs people confuse. The comparisons below were run, not remembered.

Tested on Spring Boot 4.1.1 (Spring Framework 7.0.9, Tomcat 11.0.24) with OpenJDK 21.0.12. The demo app is four files: DemoApplication.java, Components.java, More.java and Report.java. Each output block below comes from running it.

Three facts explain half of the list. First, almost every annotation is a meta-annotation built from smaller ones. The demo prints this at startup:

REPORT meta-annotations of @SpringBootApplication:
REPORT   SpringBootConfiguration
REPORT   EnableAutoConfiguration
REPORT   ComponentScan
REPORT meta-annotations of @RestController:
REPORT   Controller
REPORT   ResponseBody
REPORT @Service is a @Component: true
REPORT @Repository is a @Component: true
REPORT @RestController is a @Component: true

So @SpringBootApplication is three annotations, @RestController is two, and @Service, @Repository and @RestController are all @Components. Source: Report.java.

The annotation list, by job

Core and stereotypes

AnnotationWhat it does
@ComponentMarks a class as a Spring-managed bean found by component scanning.
@ServiceA @Component for business logic. No extra behaviour, only intent.
@RepositoryA @Component for data access; enables persistence exception translation.
@ControllerA web @Component whose methods return view names.
@RestController@Controller + @ResponseBody: return values are written to the response body.
@ConfigurationA class that declares beans with @Bean methods.
@BeanA method whose return value becomes a bean. Use it for classes you do not own.
@ImportPulls other configuration classes into this one.
@ComponentScanTells Spring which packages to scan for stereotypes.

Dependency injection and bean control

AnnotationWhat it does
@AutowiredInject a dependency by type. Optional on a single constructor.
@QualifierPick one bean by name when several match.
@PrimaryMake one bean the default when several match.
@ValueInject a single property or SpEL expression.
@ScopeSet the bean scope: singleton (default), prototype, request, session.
@LazyCreate the bean on first use instead of at startup.
@ProfileRegister the bean only when a profile is active.
@ConditionalRegister the bean only if a custom condition holds.
@PostConstructRun a method after injection (jakarta.annotation).
@PreDestroyRun a method before the bean is destroyed (jakarta.annotation).

Spring Boot

AnnotationWhat it does
@SpringBootApplication@SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan (shown in the output below).
@EnableAutoConfigurationTurns on Boot’s classpath-driven auto-configuration.
@ConfigurationPropertiesBind a group of properties (a prefix) to a typed class or record.
@EnableConfigurationPropertiesRegister a @ConfigurationProperties class as a bean.
@ConfigurationPropertiesScanScan for @ConfigurationProperties classes instead of listing them.
@ConditionalOnPropertyRegister the bean only if a property has a given value.
@ConditionalOnClassRegister the bean only if a class is on the classpath.
@ConditionalOnMissingBeanRegister the bean only if you have not defined your own.

Web

AnnotationWhat it does
@RequestMappingMap a URL (and method) to a handler; also usable on a class for a prefix.
@GetMappingShortcut for @RequestMapping(method = GET). Likewise @PostMapping, @PutMapping, @PatchMapping, @DeleteMapping.
@PathVariableBind a part of the URL path: /items/{id}.
@RequestParamBind a query parameter or form field: ?style=bold.
@RequestBodyConvert the request body (usually JSON) to an object.
@RequestHeaderBind a request header.
@CookieValueBind a cookie.
@ResponseBodyWrite the return value to the response instead of resolving a view.
@ResponseStatusSet the HTTP status of a handler or exception.
@ExceptionHandlerHandle an exception thrown by a controller.
@RestControllerAdviceGlobal @ExceptionHandlers for all controllers (@ControllerAdvice + @ResponseBody).
@CrossOriginAllow cross-origin requests to a handler or controller.
@ValidTrigger Bean Validation on an argument (jakarta.validation).
@ValidatedSpring’s variant: validation groups, and validation of @ConfigurationProperties and method parameters.

Data and transactions

AnnotationWhat it does
@TransactionalRun a method in a transaction through a proxy.
@EntityMarks a JPA entity (jakarta.persistence).
@IdThe primary key of an entity. Pair with @GeneratedValue.
@ColumnCustomise a column mapping.
@OneToMany / @ManyToOneRelationship mappings between entities.
@QueryWrite the query for a Spring Data repository method.

Scheduling, async, caching, events, resilience

AnnotationWhat it does
@EnableScheduling / @ScheduledRun a method on a fixed rate, delay or cron.
@EnableAsync / @AsyncRun a method on another thread.
@EnableCaching / @CacheableCache a method’s result. @CacheEvict removes entries, @CachePut refreshes them.
@EventListenerReceive an application event. @TransactionalEventListener waits for the transaction phase.
@Retryable / @ConcurrencyLimitRetry and concurrency limits built into Spring Framework 7.

Security and testing

AnnotationWhat it does
@EnableMethodSecurityTurns on @PreAuthorize and @PostAuthorize checks on methods.
@SpringBootTestStart the full application context in a test.
@WebMvcTestStart only the web layer for controller tests.
@DataJpaTestStart only the JPA layer for repository tests.
@MockitoBeanReplace a bean with a Mockito mock in the test context (replaces @MockBean in Boot 4).
@ActiveProfilesChoose the profiles for a test.

The next sections are for the annotations that look the same and are not. Every example is in the demo files linked above.

Commonly confused pairs, with real output

@Component vs @Bean

@Component goes on your class and component scanning finds it. @Bean goes on a method inside a @Configuration class and registers whatever the method returns, which is how you register a class you cannot edit. The demo has both: EmailNotifier is a @Component, and AppConfig.appName() is a @Bean. The beans from the demo package:

REPORT beans from package demo:
REPORT   app-demo.AppProps -> AppProps
REPORT   appConfig -> AppConfig$$SpringCGLIB$$0
REPORT   demoApplication -> DemoApplication
REPORT   emailNotifier -> EmailNotifier
REPORT   itemController -> ItemController
REPORT   itemRepository -> ItemRepository
REPORT   itemService -> ItemService
REPORT   propsConfig -> PropsConfig$$SpringCGLIB$$0
REPORT   report -> Report
REPORT   sms -> SmsNotifier
REPORT   validController -> ValidController
REPORT   viewController -> ViewController

Note appConfig is a $$SpringCGLIB$$ subclass: Spring proxies @Configuration classes so @Bean methods return the same singleton on repeated calls. Source: Components.java.

@Controller vs @RestController

A @Controller method returns a view name. A @RestController method returns the body. Returning a String from @Controller in an app with no view technology gives a 404, which is the usual confusion:

$ curl localhost:8080/view   (@Controller returning a String)
{"timestamp":"2026-10-21T16:04:04.735Z","status":404,"error":"Not Found","path":"/view"}
HTTP 404

The method returned "items", Spring looked for a view called items, found none, and answered Not Found. Add @ResponseBody or switch to @RestController. Source: More.java.

@Primary vs @Qualifier

Two beans implement Notifier. @Primary on EmailNotifier makes it the default; @Qualifier("sms") on a parameter overrides that for one injection point. Same controller, both used:

$ curl localhost:8080/api/notify?msg=hi
{"qualified":"sms:hi","primary":"email:hi"}

Without either, startup fails. This is the real failure when two Greeter beans exist and nothing says which to use:

Parameter 0 of constructor in demo.NeedsGreeter required a single bean, but 2 were found:
	- enGreeter: defined in URL [<jar>/demo/EnGreeter.class]
	- frGreeter: defined in URL [<jar>/demo/FrGreeter.class]
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

The error names both candidates and the three ways out. Source: More.java. More on resolution: @Autowired Explained: By-Type Resolution, @Qualifier, @Primary, ObjectProvider and List Injection.

@Value vs @ConfigurationProperties

@Value("${app.greeting}") injects one property. @ConfigurationProperties(prefix = "app") binds the whole app.* group to a record and validates it (here @NotBlank and @Size(max = 40)). Both read the same file:

$ curl localhost:8080/api/config
{"props.maxItems":5,"value":"Hello from properties","props.greeting":"Hello from properties"}

Use @Value for a one-off; use @ConfigurationProperties when properties belong together or need validation. One surprise from the bean listing above: the properties record is registered under the name app-demo.AppProps, prefix first. Source: Components.java. Deeper: @ConfigurationProperties vs @Value in Spring Boot 4: Binding, Validation and Relaxed Rules.

@PathVariable vs @RequestParam

@PathVariable reads from the path template, @RequestParam from the query string. One handler uses both:

$ curl localhost:8080/api/items/1?style=bold
bold:book
$ curl localhost:8080/api/items/abc
{"timestamp":"2026-10-21T16:04:04.715Z","status":400,"error":"Bad Request","path":"/api/items/abc"}
HTTP 400

A non-numeric path variable is a 400, not a 500: the conversion failure is mapped for you. Source: Components.java.

@Valid and what the client sees

@Valid @RequestBody NewItem triggers the constraints on the record (@NotBlank name, @Min(1) qty). A bad body is rejected before your method runs:

$ curl -XPOST -H "Content-Type: application/json" -d {"name":"","qty":0} localhost:8080/api/new
{"timestamp":"2026-10-21T16:04:04.682Z","status":400,"error":"Bad Request","path":"/api/new"}
HTTP 400
$ curl -XPOST -H "Content-Type: application/json" -d {"name":"cup","qty":2} localhost:8080/api/new
{"created":"cup","qty":2}
HTTP 200

Boot’s default 400 body says nothing about which field failed. If clients need that, return a ProblemDetail: Global Exception Handling with ProblemDetail (RFC 9457) in Spring Boot 4. Source: More.java.

@Profile

DevOnly is annotated @Profile("dev"). With no active profile it is not created:

REPORT DevOnly (@Profile("dev")) present: false

Profiles in depth: Spring Boot Profiles Done Right: Config Import, Config Trees and Kubernetes ConfigMaps.

Where to go next

This list is a map. For the order to learn it in, use the Spring Boot tutorial for beginners; for what each version of Boot changed, Spring Boot versions; and for how Boot differs from the framework underneath, Spring vs Spring Boot vs Spring MVC.

Common interview questions

What is the difference between @Component, @Service and @Repository?

All three register a bean. @Service and @Controller add only meaning; @Repository also enables exception translation for data-access errors.

What does @SpringBootApplication do?

It combines @SpringBootConfiguration, @EnableAutoConfiguration and @ComponentScan.

What is the difference between @Controller and @RestController?

@RestController is @Controller plus @ResponseBody, so return values become the response body.

@Bean or @Component?

@Component for your own classes, @Bean for third-party classes or when construction needs logic.

How do you resolve two beans of the same type?

Mark one @Primary, qualify the injection point with @Qualifier, or inject a List of all of them.

Common mistakes

FAQ

What are the most important Spring Boot annotations?

@SpringBootApplication, @RestController, @Service, @Repository, @Autowired, @GetMapping/@PostMapping, @RequestBody, @Transactional, @ConfigurationProperties and @Bean.

Is @Autowired required on a constructor?

No. With one constructor, Spring injects it without the annotation.

What changed for annotations in Spring Boot 4?

@MockBean and @SpyBean are replaced by @MockitoBean and @MockitoSpyBean; see the versions page and the Boot 3 to 4 migration guide.

Further reading

No Comments yet!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.