#
Annotations in Java Spring Boot
This tutorial explains some annotations used in Java Spring Boot.
Info
Java annotations are metadata (data about data) provided to the compiler and JVM. An annotation could be on classes, interfaces, variables, methods, or fields level. Annotations do not impact the execution of the code.
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 (we don't need to use @Value). For custom
.properties files (not application.properties), we need to use @PropertySource
(in this case we need to use an Environment variable or @Value).
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String name;
private String version;
private Security security;
public static class Security {
private boolean enabled;
private List<String> roles;
// Getters and setters
}
// Getters and setters for name, version, and security
}
#
@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.
@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,
Configuration are types of Components.
Info
@Configuration contains @Component annotation. So we can consider, Configuration as a Component as well.
#
@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.
Info
@ControllerAdvice can be viewed as an interceptor of exceptions thrown by methods annotated with @RequestMapping and similar. The exception handler is marked using @ExceptionHandler annotation.
#
@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).
@ConfigurationProperties("custom")
@ConstructorBinding
public class CustomProperties {
private final String song;
public CustomProperties(String song) {
this.song = song;
}
public String getSong() {
return song;
}
}
@ConfigurationProperties("custom")
// @ConstructorBinding --> not needed
public class CustomProperties {
private final String song;
public CustomProperties(String song) {
this.song = song;
}
public String getSong() {
return song;
}
}
@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})
Info
SpringExtension and MockitoExtension are both Java classes. SpringExtension implements more extensions.
#
@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.
@ComponentScan is more like convention, while @Import is more like configuration.
#
@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.
@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
Spring container. We can use @Value or Environment variable to access 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
Spring Boot will automatically serialize the returned objects to JSON or XML if a library like
Jackson (for JSON) or JAXB (for XML) is on the classpath. Spring Boot comes with Jackson included by default.
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
// 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
@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.
Info
- By default, the
@Transactional
annotation will create a new transaction for the marked method or class if one does not already exist. @Transactional(propagation = Propagation.REQUIRED)
: a new transaction will be created.@Transactional(isolation = Isolation.SERIALIZABLE)
: the transaction is completely isolated from the other transactions. More information you have here.
#
@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.
@PostMapping
public ResponseEntity<User> createUser(@RequestBody @Valid User user) {
// Code goes here
}
#
@Validated
@Validated
used for validating based on validation groups.
...
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
}
Info
BasicValid and AdvancedValid are marker interfaces created for different validation groups.
#
@Value
@Value
is used to inject externalized properties into a class attribute.