In the Spring Framework, annotations are regularly used to perform Spring core tasks like Inversion of Control (IoC) and Dependency Injection (DI).
Before annotations were introduced in Java 5, the Spring Framework used XML files to manage Inversion of Control and Dependency Injection. Today, most Spring applications out there do this with annotations.
Annotations are not only used in the Spring Framework; in J2EE applications, developers use JSR-250, JSR-330, etc. standard annotations. The most used J2EE standard annotations are also explained at the end of this article.
Spring Framework annotations with examples:
The @Autowired Annotation
The @Autowired annotation is used on fields, setter methods, and constructors to inject a dependency.
The spring Framework instantiates all objects you need in an Inversion of Control container, you as developer wire objects with the @Autowired annotation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.example.demo; import org.springframework.stereotype.Component; import org.springframework.beans.factory.annotation.Autowired; @Component public class DemoApplication { private ComponentA ca; @Autowired DemoApplication(ComponentA ca) { this.ca = ca; } } |
If you have multiple constructors in your class, only one constructor can be marked with the @Autowired annotation
The @Bean Annotation
The @Bean annotation is used on methods within a class that is marked with the @Configuration annotation, these methods instantiate a new object and register it in the application context. In the following example, the sampleBean() method instantiates a new object of type SampleBean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.librescript.demo; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Bean; @Configuration public class DemoApplication { @Bean public SampleBean sampleBean() { return new SampleBean(); } } |
1 2 3 4 5 |
package com.librescript.demo; public class SampleBean { //ToDo } |
Methods can also be marked with the @Bean annotation in classes that are not marked with the @Configuration annotation. These @Bean methods are processed in a “lite” mode and should not invoke other @Bean methods.
The @Component Annotation
The @Component annotation is used on classes to be instantiated and managed by the Spring IoC (Inversion of Control) container. Similar to the @Bean annotation but @Component is used on classes and @Bean is used on methods.
In the Spring Framework, objects marked with the @Component annotation are called beans and are instantiated and passed to the the application context.
1 2 3 4 5 6 7 8 9 10 11 12 |
package com.example.demo; import org.springframework.stereotype.Component; @Component public class DemoApplication { public String demo() { return "class: DemoApplication, method: demo()"; } } |
The @Component annotation can also be used to name a component, for example @Component(“name1”). If no name is provided, Spring uses the camelCase convention to name the component (DemoApplication will be named demoApplication)
The @ComponentScan Annotation
The @ComponentScan annotation tells Spring to scan the current package and all of its subpackages for classes and methods with the annotations @Component, @Bean, @Service, @Repository, @Controller, @Restcontroller, etc., the found components are instantiated and passed to the application context.
1 2 3 4 5 6 7 8 9 10 11 |
package com.example.demo; import org.springframework.context.annotation.ComponentScan; @ComponentScan public class DemoApplication { public static void main(String[] args) { System.out.println("App running..."); } } |
The @ComponentScan annotation is implicit in the @SpringBootApplication annotation.
The @ComponentScan annotation has a basePackages attribute for scanning packages other than the current package e.g. @ComponentScan(basePackages = “com.librescript.demoapp.anotherpackage”)
The @Configuration Annotation
The @Configuration annotation is used on classes that implement one or more methods with the @Bean annotation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.librescript.demo; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Bean; @Configuration public class DemoApplication { @Bean public BeanA methodA() { return new BeanA(); } @Bean public BeanB methodB() { return new BeanB(); } } |
This is called Java-based configuration. With Java-based configuration, it is not necessary to use an XML configuration file. A Java-based configuration is just as good as an XML configuration and vice versa.
The @Controller Annotation
The @Controller annotation is used on controller classes in a MVC application (Model-View-Controller). A controller class implements methods that return a view or return a domain object (data in JSON or XML format).
Return a view means, this method points to a HTML template, in the example below myMethod() displays the show.html template found in the src/main/templates/contacts folder
└── src
└── main
└── templates
└── contacts
└── show.html
Return a domain object means, return JSON or XML that represents a class defined in the application
Methods within a controller class are usually marked with the following annotations:
@RequestMapping
@GetMapping
@DeleteMapping
@PostMapping
@PutMapping
The above annotations usually points to a URL e.g. @RequestMapping(“/contacts”), which handles an HTTP request (http://example.com/contacts)
If no URL is specified, Spring uses the default value, e.g. @RequestMapping is equivalent to @RequestMapping(“/”)
1 2 3 4 5 6 7 8 9 10 11 12 |
import org.springframework.web.bind.annotation.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller class SampleController { @RequestMapping("/contacts") public String sampleMethod() { //displays show.html template found in src/main/templates/contacts folder return "contacts/show“; } } |
The @DeleteMapping Annotation
The @DeleteMapping annotation is used on methods within a class that is marked with the @Controller annotation. The @DeleteMapping method handles the HTTP request if the specified URL matches and the HTTP method is DELETE.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.example.demo; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.DeleteMapping; @RestController @RequestMapping("/customers") public class RestTest { @DeleteMapping public void methodA() { System.out.println("HTTP method is DELETE"); } } |
The @DeleteMapping annotation is a shortcut for
@RequestMapping(method = RequestMethod.DELETE)
You can test this application by sending a HTTP DELETE request using an API Client such as Postman or a command line tool such as cURL.
The @GetMapping Annotation
The @GetMapping annotation is used on methods within a class that is marked with the @Controller annotation. The @GetMapping method handles the HTTP request if the specified URL matches and the HTTP method is GET
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.example.demo; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.GetMapping; @RestController @RequestMapping("/customers") public class RestTest { @GetMapping public void methodA() { System.out.println("HTTP method is GET"); } } |
The @GetMapping annotation is a shortcut for
@RequestMapping(method = RequestMethod.GET)
You can test this application by sending a HTTP GET request using an API Client such as Postman or a command line tool such as cURL.
The @Lazy Annotation
The @Lazy annotation is used on @Configurations and @Component classes. By default, @Bean methods and classes are instantiated when the application starts up. With the @Lazy annotation you tell Spring to wait until they are referenced by another component.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package com.librescript.demo; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Bean; @Lazy @Configuration public class DemoApplication { @Bean public BeanA methodA() { return new BeanA(); } @Bean public BeanB methodB() { return new BeanB(); } } |
The @PathVariable Annotation
The @PathVariable annotation is used on method parameters that should replace a URL template variable. In the following example, Spring reads the value from the URL and displays it on the command line or in the terminal, e.g.
http://localhost:8080/customers/865
output:
Customer ID is 865
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.librescript.springapp; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @RestController @RequestMapping("/customers") public class RestTest { @GetMapping("/{id}") public void myMethod(@PathVariable long id) { System.out.println("Customer ID is " + id); } } |
A URL template is a URL with parameters, usually in curly brackets. These parameters should be replaced with values to obtain a URL, e.g. http://example.com/customers/{id}
The @PostMapping Annotation
The @PostMapping annotation is used on methods within a class that is marked with the @Controller annotation. The @PostMapping method handles the HTTP request if the specified URL matches and the HTTP method is POST
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.example.demo; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.PostMapping; @RestController @RequestMapping("/customers") public class RestTest { @PostMapping public void methodA() { System.out.println("HTTP method is POST"); } } |
The @PostMapping annotation is a shortcut for
@RequestMapping(method = RequestMethod.POST)
You can test this application by sending a HTTP POST request using an API Client such as Postman or a command line tool such as cURL.
The @Primary Annotation
The @Primary annotation is used on classes or @Bean methods to tell Spring which class to wire if there is more than one class of the same type, e.g. more than one class implementing the same interface to avoid ambiguity. See the following example
1 2 3 4 5 |
package com.example.demo; public interface Country { public void name(); } |
1 2 3 4 5 6 7 8 9 10 11 12 |
package com.example.demo; import org.springframework.stereotype.Component; @Component public class Brasil implements Country{ @Override public void name(){ System.out.print("Country: Brasil"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.example.demo; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @Component @Primary public class Germany implements Country { @Override public void name() { System.out.print("Country: Germany"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class SampleApp { private Country country; @Autowired public SampleApp(Country country) { this.country = country; } public void printName() { country.name(); } } |
Removing the @Primary annotation would cause following error
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.example.demo.SampleApp required a single bean, but 2 were found:
– brasil: defined in file [/Users/MacBook/Desktop/JavaProjects/Tomcat/webapps/SampleApp/target/classes/com/example/demo/Brasil.class]
– germany: defined in file [/Users/MacBook/Desktop/JavaProjects/Tomcat/webapps/SampleApp/target/classes/com/example/demo/Germany.class]
Action:
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 @PutMapping Annotation
The @PutMapping annotation is used on methods within a class that is marked with the @Controller annotation. The @PutMapping method handles the HTTP request if the specified URL matches and the HTTP method is PUT
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.example.demo; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.PutMapping; @RestController @RequestMapping("/customers") public class RestTest { @PutMapping public void methodA() { System.out.println("HTTP method is PUT"); } } |
The @PutMapping annotation is a shortcut for
@RequestMapping(method = RequestMethod.PUT)
You can test this application by sending a HTTP PUT request using an API Client such as Postman or a command line tool such as cURL.
The @Qualifier Annotation
The @Qualifier annotation is used on classes to explicitly name a class or on fields and method parameters to tell Spring which class to wire if there is more than one class of the same type, e.g. more than one class implementing the same interface to avoid ambiguity. See the following example
1 2 3 4 5 |
package com.example.demo; public interface Country { public void name(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package com.example.demo; import org.springframework.stereotype.Component; @Component public class Germany implements Country { @Override public void name() { System.out.println("Country: Germany"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.example.demo; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component @Qualifier("brasil") public class Brasil implements Country { @Override public void name() { System.out.println("Country: Brasil"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component public class SampleApp { private Country country; @Autowired public SampleApp(@Qualifier("brasil") Country country) { this.country = country; } public void printName() { country.name(); } } |
Removing @Qualifier(“brasil”) in the constructor parameter Country would cause following error
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.example.demo.SampleApp required a single bean, but 2 were found:
– brasil: defined in file [/Users/MacBook/Desktop/JavaProjects/Tomcat/webapps/SampleApp/target/classes/com/example/demo/Brasil.class]
– germany: defined in file [/Users/MacBook/Desktop/JavaProjects/Tomcat/webapps/SampleApp/target/classes/com/example/demo/Germany.class]
Action:
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 @Repository Annotation
The @Repository annotation is used on a class that interacts with the database. In this case we use @Repository on an interface, Spring Data JPA creates a class that implements CustomersRepository at runtime.
1 2 3 4 5 6 7 8 9 |
package com.librescript.springapp.repository; import com.librescript.springapp.model.Customers; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface CustomersRepository extends JpaRepository<Customers, Long> { } |
The @RequestBody Annotation
The @RequestBody annotation is used on method arguments. The @RequestBody annotation maps the HTTP request body to a domain object.
In the example below, we have a HTTP POST request that is mapped to a Person object (See Person.java). Note that the keys in the body of the HTTP request (name, surname) match the fields in the Person class.
HTTP request body
{
“name”: “Elisabeth”,
“surname”: “Taylor”
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.example.demo; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @RestController public class RequestBodyTest { @PostMapping("/persons") public Person myMethod(@RequestBody Person p) { String name = p.getName(); String surname = p.getSurname(); Person person = new Person(name, surname); return person; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package com.example.demo; public class Person { public String name; public String surname; Person(String name, String surname) { this.name = name; this.surname = surname; } public String getName() { return name; } public String getSurname() { return surname; } } |
You can test this application by sending a HTTP POST request using an API Client such as Postman or a command line tool such as cURL.
1 2 3 4 5 6 7 |
The @RequestMapping Annotation The @RequestMapping annotation is used on @Controller methods or classes. This annotation takes a URL argument and returns a view or a domain object in JSON or XML format @RequestMapping(value = "/customers", method = { GET, HEAD }) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.librescript.springapp; import org.springframework.web.bind.annotation.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller class SampleController { @RequestMapping("/contacts") public String sampleMethod() { //displays show.html template found in src/main/templates/contacts folder return "contacts/show“; } } |
The @RequestParam(“textfield_name”) Annotation
The @RequestParam(“textfield_ name”) annotation is similar to the @PathVariable annotation but the @RequestParam annotation is used on query parameters and forms inputs (Webforms).
Query parameters, often referred to as “query string”, are parameters at the end of a URL. Query parameters start with a question mark “?” and separate key value pairs by the ampersand “&”, e.g.
http://example.com/index?id=21&=country=usa
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.example.demo; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @RestController @RequestMapping("/customers") public class RequestParamExample { @RequestMapping public void sampleMethod(@RequestParam String id) { System.out.println("Customer ID: " + id); } } |
output:
Customer ID: 865
The @ResponseBody Annotation
The @ResponseBody annotation is used on methods that return a domain object in JSON or XML format instead of a view. In the example below the following JSON object is returned.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.librescript.springapp; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; @RestController @RequestMapping("/persons") public class RestTest { @GetMapping @ResponseBody public Person methodA() { return new Person("Heike", "Berganza"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package com.example.demo; public class Person { public String name; public String surname; Person(String name, String surname) { this.name = name; this.surname = surname; } } |
Note that the keys in the JSON object (name, surname) match the fields in the Person class.
The @RestController Annotation
The @RestController annotation is used on classes that implements methods that return data in JSON or XML format instead of a view
The @RestController annotation is a combination of the @Controller and @ResponseBody annotations. In Fact, if you use @RestController, you do not need to use the @ResponseBody annotation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.example.demo; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.PostMapping; @RestController @RequestMapping("/books") public class RestTest { @PostMapping public void methodA() { System.out.println("HTTP method is POST"); } } |
The @Scope Annotation
The @Scope annotation overrides the default “singleton” scope (a bean is instantiated only once) e.g. @Scope(value=”prototype”) would allow many instances of a bean.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.example.demo; import org.springframework.stereotype.Component; import org.springframework.context.annotation.Scope; @Component @Scope(value="prototype") public class AnotherComponent { public String anotherMethod() { return "I am anotherMethod() in AnotherComponent"; } } |
The @SpringBootApplication Annotation
The @SpringBootApplication annotation is a shortcut for following annotations:
@Configuration
@ComponentScan
@EnableAutoConfiguration
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package com.librescript.springapp; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringApp { public static void main(String[] args) { SpringApplication.run(SpringApp.class, args); } } |
In the above example, @SpringBootApplication is located in the package com.librescript.springapp, so Spring will scan this package and all of its subpackages for classes and methods with the annotations @Component @Bean @Service, @Repository, etc. and pass them to the application context.
In addition to the Spring annotations, you can also use JSR-330 standard annotations
The @Entity Annotation
The @Entity annotation is used on a class that represents a table in the database. An @Entity class must have an @Id field.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.librescript.springapp.model; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.GeneratedValue; @Entity public class Contact { @Id @GeneratedValue private Long id; private String name; private String surname; } |
The @Id Annotation
The @Id annotation is used on a field in an @Entity class, this field represents an unique primary key column in the database table.
The @GeneratedValue Annotation
The @GeneratedValue annotation is used together with the @Id annotation to generate sequential value for an @Id field.
The @Override Annotation
The @Override annotation is used on a method that is inherited and overridden by this class.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package com.example.demo; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component public class Brasil implements Country { @Override public void name() { System.out.println("Country: Brasil"); } } |
The @Column Annotation
The @Column annotation is used on fields within an @Entity class. If no @Column annotation is specified, the field is mapped to a column with the same name.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.example.demo; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.GeneratedValue; import javax.persistence.Column; @Entity public class Contac { @Id @GeneratedValue private Long id; @Column(name = "new_column_name") private String city; } |