# Annotations in Java Spring Boot

In 
Published 2024-01-14

This tutorial explains some annotations used in Java Spring Boot.

Here are some well known annotations used in Java:

# @ActiveProfiles (tests)

@ActiveProfiles is a class-level annotation that is used to declare which bean definition profiles should be active when loading an ApplicationContext for an integration test.

Profiles used for that particular test.

# @Async

@Async annotation in Spring Boot is used for telling Spring to run that method on another thread, so in parallel with the parent thread. We need also to add @EnableAsync at the main application class.

# @Autowired

@Autowired is used to inject a dependency automatically into an object (when using SpringExtension.class).

# @Bean

@Bean defines a Bean (or more) which could be used later by the Spring container. This annotation is usually used in the "Configuration" classes.

# @BeforeTransaction & @AfterTransaction (tests)

@BeforeTransaction & @AfterTransaction mark methods which run after/before a transaction when doing tests.

# @CookieValue

@CookieValue bind the value of an HTTP cookie to a method parameter (in a Controller class).

# @ComponentScan

@ComponentScan : without arguments tells Spring to scan the current package and all of its sub-packages. You can add/exclude directories/classes you want to scan/use. The scan is done for looking for Beans and for creating them.

# @ConfigurationProperties

@ConfigurationProperties (Spring Boot) : maps the values from .properties or .yml files to directly to object variables. For custom .properties files (not application.properties), we need to use @PropertySource (in this case we need to use an Environment variable).

# @Configuration

@Configuration : indicates that a class declares one or more @Bean methods and may be processed by the Spring container. @Configuration contains @Component annotation.

# @ConditionalOnClass & @ConditionalOnMissingClass

@ConditionalOnClass and @ConditionalOnMissingClass annotations let @Configuration classes be included based on the presence or absence of specific classes.

# @ConditionalOnBean & @ConditionalOnMissingBean

@ConditionalOnBean and @ConditionalOnMissingBean annotations let @Configuration classes be included based on the presence or absence of specific Beans. The name of the Beans must be specified.

# @ConditionalOnJava

@ConditionalOnJava : allows you to conditionally enable or disable a bean or configuration class based on the version of the Java Runtime Environment (JRE) being used.

# @ConditionalOnProperty

@ConditionalOnProperty annotation lets configuration be included based on a Spring Environment property.

Example
@Bean
@ConditionalOnProperty(name = "oracle", environment = "local")
DataSource dataSource() {
     // ...
}

# @ConditionalOnExpression

@ConditionalOnExpression has the same utility as @ConditionalOnProperty, but the condition is based on an expression.

# @ConditionalOnResource

@ConditionalOnResource annotation lets configuration be included only when a specific resource (a file, etc) is present.

# @Conditional

@Conditional annotation allows you to conditionally enable or disable a bean or configuration class based on some conditions kept in a custom class (this class must implement Condition interface:).

# @ContextConfiguration (tests)

@ContextConfiguration loads an ApplicationContext for Spring integration test. It is recommended to use @SpringBootTest.

# @Component

@Component marks a class as a Component class. Spring Container will automatically create a Spring bean for that class. Controller, Repository, Service are types of Components.

# @Controller

@Controller marks a class as a Controller (a kind of Component). Spring Container will automatically create a Spring bean for that class.

# @ControllerAdvice

@ControllerAdvice is used to create a global exception handler that can catch and handle exceptions that occur in any controller in your application. @RestControllerAdvice do the same thing, but returns a JSON or XML response.

# @ConstructorBinding

@ConstructorBinding it is used together with @ConfigurationProperties. The constructor will use the properties from the file. As of Boot 3.0 @ConstructorBinding is no longer needed at the type level on @ConfigurationProperties classes and should be removed (valid if we have only 1 constructor when this is done automatically).

Before Spring 3.0
@ConfigurationProperties("custom")
@ConstructorBinding
public class CustomProperties {

    private final String song;
 
    public CustomProperties(String song) {
        this.song = song;
    }
 
    public String getSong() {
        return song;
    }
}
After Spring 3.0
@ConfigurationProperties("custom")
// @ConstructorBinding --> not needed
public class CustomProperties {

    private final String song;
 
    public CustomProperties(String song) {
        this.song = song;
    }
 
    public String getSong() {
        return song;
    }
}
After Spring 3.0
@ConfigurationProperties("custom")
public class CustomProperties {

    private final String song;
 
    // Could be useful when we have more constructors
    @ConstructorBinding 
    public CustomProperties(String song) {
        this.song = song;
    }
    
    public CustomProperties(String song, String song2)
        this.song = song + song2;
    }
 
    public String getSong() {
        return song;
    }
}

# @CrossOrigin

@CrossOrigin enable cross-origin calls.

// You can specify also which cross-origin are allowed.
@CrossOrigin(origins = {"http://localhost:8080", "http://localhost:8081"})

# @DependsOn

@DependsOn specify the Beans the current Bean depends on.

# @Deprecated

@Deprecated : It is read by the compiler and during the compilation you will see a warning if the method marked as @Deprecated is used.

# @Documented

@Documented : the class will be added to Java Docs.

# @EnableAsync

@EnableAsync used in the main class to enable the async calls in the service/application.

# @EnableAutoConfiguration

@EnableAutoConfiguration : automatically configure some Beans for you, based on the presence of certain classes on the classpath (like a DataSource bean). You can also exclude some classes from automatic configuration.

# @EnableConfigurationProperties

Example:

@EnableConfigurationProperties(value = MyCustomProperties.class)
public class MyConfiguration{
   ...
}

When MyCustomProperties class is defined could be defined as Bean or not. If the class is not define as a Bean, @EnableConfigurationProperties force the creation of a Bean for MyCustomProperties. This is for being sure that MyConfiguration class could inject MyCustomProperties Bean.

# @EnableConfigurationPropertiesScan

EnableConfigurationPropertiesScan : scans the packages based on the parameter value passed into it and discovers all classes annotated with @ConfiguratonProperties under the package.

# @EnableScheduling

@EnableScheduling enable scheduling in the application. This annotation is set in the configuration or main class level.

# @EnableJpaRepositories

@EnableJpaRepositories used with the Configuration classes to tell Spring were to find @Repository definitions.

# @Entity

@Entity (in JPA) each instance of an entity represents a row in the table.

# @EntityScan

@EntityScan (in JPA) it is looking for Entities in particular locations.

# @ExceptionHandler

@ExceptionHandler handle the specific exceptions and send the custom responses to the client. This is used at method level in ControllerAdvice classes.

# @ExtendWith

@ExtendWith is a repeatable annotation that is used to register extensions for the annotated test class, test interface, test method, parameter, or field. The extensions will make available @Mock, @MockBean, @InjectMocks annotations (but that depends on extensions Mockito, etc).

@ExtendWith(MockitoExtension.class)
OR
@ExtendWith({org.springframework.test.context.junit.jupiter.SpringExtension.class})

# @FunctionalInterface

@FunctionalInterface is used in Spring for testing if we have only one abstract method in the interface and for documentation.

# @GetMapping

@GetMapping acts as a shortcut for @RequestMapping(method = RequestMethod.GET). The same thing is valid for @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping.

# @Import

@Import allows to import one or more @Configuration classes into another. In general, it is not used combined with @ComponentScan.

# @ImportResource

@ImportResource annotation indicates one or more XML based bean definition files to be imported.

# @Inherited

@Inherited (used when define an annotation) : could be used to let subclasses inherit that annotation.

# @InjectMocks

@InjectMocks (when using with Mockito Extension) it is the equivalent of @Autowired (when using SpringExtension.class).

# @Lazy

@Lazy annotation make a Bean to be created when needed, not when Spring IoC container is created.

# @Lookup

@Lookup used when in a Singleton Bean we inject a Prototype Bean, and we want to use a new Prototype Bean when we are calling a particular method of the Singleton Bean.

# @Mock

@Mock (when using with Mockito Extension) to inject a mock into an instance variable. The mock itself is not defined, but we must define the when(...).thenReturn(...) block for mock objects whose class methods will be invoked during actual test execution. If we inject a Bean we can use @MockBean instead.

# @MockBean

@MockBean (when using with Mockito Extension) to inject a mock Bean into an instance variable.

# @Order

@Order defines sorting order if injecting a list of beans, but it does not resolve the priority if only a single bean is expected. Lower numbers indicate a higher priority.

# @Override

@Override : If the annotated method does not actually override anything, the compiler issues a warning.

# @PathVariable

@PathVariable maps a path variable to a method parameter/argument.

Example
@GetMapping(path = "/api-url/{id}/{name}")
public AnyClass aMethod(@PathVariable long id,
                        @PathVariable(name = "name") String name) {
    // Code goes here
}

@RequestParam, @RequestBody, @PathVariable, @RequestHeader must be studied together.

# @PostConstruct & @PreDestroy

@PostConstruct annotation is used on a method that needs to be executed after dependency injection is done to perform some initialization.

@PreDestroy annotation is used on a method that needs to run just before the bean is destroyed to perform any required cleanup. It does the same think as destroy() method.

# @Primary

@Primary when the qualifier is not used, the Bean marked as "@Primary" will be used as default Bean for that Bean type.

# @Profile

@Profile tells Spring to create a Bean in a particular profile(s).

# @PropertySource

@PropertySource annotation (from Spring 3.1) adds property sources to the environment. Instead using @Value, we can inject the environment and use it:

@Configuration
@PropertySource("classpath:app-1.properties")
@PropertySource("classpath:app-2.properties")
public class MyConfiguration {

    @Autowired
    private Environment env;
    
    String appName = env.getProperty("APP_NAME")

We can have more @PropertySource annotation for a "Configuration" class. Also, we can group more @PropertySource into one @PropertySources, but this is not a good practice.

# @Qualifier

@Qualifier let Spring know which Bean must be used for injection. It is used together with @Autowired, when there are more Beans with the same type, but different name.

# @Repository

@Repository marks a class as a DAO or Repository class (a kind of Component). Spring Container will automatically create a Spring bean for that class.

# @ResponseBody

@ResponseBody annotation must be added to each of the @RequestMapping methods. For doing this we need to add the @ResponseBody at the class level.

# @ResponseStatus

@ResponseStatus could override the default response status (code & reason). It is used with classes which extends RuntimeException.

# @RequestMapping

@RequestMapping defines a request and map it to a method. It works together with @ResponseBody.

# @RequestBody

@RequestBody annotation in a Spring boot application to bind the request body parameters to method parameters

Examples
// using Map
@RequestMapping(path = "/uploadFile", method = RequestMethod.POST)
public ResponseEntity uploadFile(@RequestBody Map<String, String> userMap) throws SQLException, IOException {

    // Code goes here
}

// Using a class
@RequestMapping(path = "/uploadFile", method = RequestMethod.POST)
public ResponseEntity uploadFile(@RequestBody UserMap userMap) throws SQLException, IOException {

    // Code goes here
}

// Using a String
@RequestMapping(path = "/uploadFile", method = RequestMethod.POST)
public ResponseEntity uploadFile(@RequestBody String requestData) throws SQLException, IOException {

    // "org.json" library is a dependency here
    JSONObject jsonObject = new JSONObject(requestData);
    String fromUserEmail = jsonObject.getString("fromUserEmail"); 
    
    // More code goes here
}

@RequestParam, @RequestBody, @PathVariable, @RequestHeader must be studied together.

# @RequestParam

@RequestParam is used to extract request parameters into the method parameters directly. It is used to bind parameter values from "query string" e.g. in http://www.domain.com?myParam1=10&myParam2=20

Example
@RequestMapping(path = "/uploadFile", method = RequestMethod.POST)
    public ResponseEntity uploadFile(@RequestParam(name = "file") MultipartFile inputFile,
                                     @RequestParam("id") Integer id,
                                     @RequestParam String additionalInfo) throws SQLException, IOException {
                                     
    // Code goes here                                                               
}

@RequestParam, @RequestBody, @PathVariable, @RequestHeader must be studied together.

# @RequestHeader

@RequestHeader pass a specific header value in a method parameter (in Controller).

@RequestParam, @RequestBody, @PathVariable, @RequestHeader must be studied together.

# @Required

@Required mark a setter method to be mandatory. When the bean is created, that setter must set a value for that attributes.

# @RestController

@RestController combines @Controller and @ResponseBody. @Controller contains @Component.

# @Sql (tests)

@Sql annotation executes SQL scripts and SQL statements against a database in Spring integration test (on class & method level) for preparing the data for the tests.

# @Retention

@Retention(RetentionPolicy.RUNTIME) : Tell the compiler where the current annotation is used.

  • RetentionPolicy.RUNTIME -> the annotation is used by JVM.
  • RetentionPolicy.CLASS -> is written to Bytecode but will be discarded during the class loading.
  • RetentionPolicy.SOURCE -> used by the compiler, but discarded after the compilation.

# @SafeVarargs

@SafeVarargs : used to suppress the unsafe operation warnings at the compile time (introduced in Java 7).

Example:

@SafeVarargs  //we will have an issue if in the list we have a number
private void print(List... names) {
    for (List<String> name : names) {
       System.out.println(name);
    }
} 

# @Scheduled

@Scheduled added to a method will schedule that method based on the information provided. This is working together with @EnableScheduling which enable scheduling in the application.

# @Schedules

@Schedules is used when we want to have more @Scheduled annotations for a specific method.

# @Scope

@Scope annotation can be used with any Beans to let Spring IoC container to create one or mre Beans of that type.

Scopes:

  • Singleton (default scope): only one instance of the bean is created and shared across the entire application

  • Prototype: a new instance of the bean is created every time it is requested

  • Request (for web applications ONLY): a new instance of the bean is created for each HTTP request.

  • Session (for web applications ONLY): a new instance of the bean is created for each HTTP session.

  • Application (for web applications ONLY): a single instance of the bean is created and shared across the entire application context.

# @Service

@Service marks a class as a Service (a kind of Component). Spring Container will automatically create a Spring bean for that class.

# @SuppressWarnings

@SuppressWarnings : disable compilation warnings for a certain part of a program (type, field, method, parameter, constructor, and local variable).

Example:

@SuppressWarnings("deprecation")
public void peintCircle() {
  Circle c1 = new Circle();
  c1.peint();  // this is a deprecated method
}

# @Spy

@Spy (when using with Mockito Extension) : creates a partial mock on an object.

# @SpyBean

@SpyBean (when using with Spring ApplicationContext) : creates a partial mock on an object. It creates a wrapper on an existing object.

# @SpringBootApplication

@SpringBootApplication : add the following annotations to the class: @SpringBootConfiguration, @EnableAutoConfiguration, @ComponentScan, @Target, @Retention, @Documented, @Inherited.

# @SpringBootConfiguration

@SpringBootConfiguration : we can define Beans in the class (it acts like @Configuration).

# @SpringBootTest (tests)

@SpringBootTest creates an application context for testing the application. It is used on a test class that executes Spring Boot based tests. This annotation contains @ExtendWith().

# @Target

@Target({ElementType.TYPE}) : defines for which type of elements this annotation apply ( "ElementType.TYPE" = for Class, Interface (including annotation interface), enum, or record declaration).

# @Transactional

@Transactional is used to define transactional behaviour when working with databases. If the transaction is successful, the changes will be committed to the database. If an error occurs and the transaction is rolled back.

# @Valid

@Valid the validation of the parameter is triggered before the method is invoked. It is placed before the object to indicate that it should be validated.

Example:
@PostMapping
public ResponseEntity<User> createUser(@RequestBody @Valid User user) {

    // Code goes here
}

# @Validated

@Validated used for validating based on validation groups.

Example:
...
public interface BasicValid {}
public interface AdvancedValid {}
...
public class User {

    @NotNull(groups = BasicValid.class)
    @NotNull(groups = AdvancedValid.class)
    private String username;

    @NotNull(groups = AdvancedValid.class)
    private String email;
    
    // Other fields, methods goes here
}
...
@PostMapping
public ResponseEntity<User> createUser(@RequestBody @Validated(BasicValid.class) User user) {

    // Code goes here
}

# @Value

@Value is used to inject externalized properties into a class attribute.