Spring Annotation-based Configuration


  • Annotation base configuration is possible from spring 2.5 onwords. Annotation-based configuration rely on bytecode metadata. Instead of writing xml developer moves the configuration into the component class itself by using annotations on the relavent class, method or field declarations.

  • Annotation injection is performed before XML injection. so xml injection will overried the properties if wired through both the approaches.

  • Annotation wiring is not enabled by default. So before using annotation based wiring we will need to enable it using component scaning.

  • Once <context:annotation-config/> is configured, You can use @Component,@Repository,@Service and @Controller annotation to configure bean in Spring application and you can start annotating your code to indicate that Spring should automatically wire values into properties, methods, and constructors. Ex:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version = "1.0" encoding = "UTF-8"?>

<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context = "http://www.springframework.org/schema/context"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context-3.0.xsd">

   <context:annotation-config/>
   <!-- bean definitions go here -->

</beans>

Below are the annotations used for bean configuration:

@Required

  • It applies to bean property setter method.
  • It indicates that the property should be populated at config time through explicit property value in bean definition or through autowiring.
  • The container throws exception if the bean property is not populated.
  • This avoids NullPointerException later.

Ex:

1
2
3
4
5
6
7
8
9
10
public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Required
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
    // ...
}

@Autowired

  • For using @Autowired annotation, we have register AutowiredAnnotationBeanPostProcessor bean in spring IoC container.
1
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />

(OR)

  • But once the <context:annotation-config/> element is included in configuration file, it automatically registers the below bean post processors as a result you do not need above bean to be registered seperately.
    • AutowiredAnnotationBeanPostProcessor
    • CommonAnnotationBeanPostProcessor
    • PersistenceAnnotationBeanPostProcessor
    • RequiredAnnotationBeanPostProcessor
  • The @Autowired annotation can apply to bean property setter methods, non-setter methods, constructor and properties.
  • Spring container can autowire a Map, List or an Array with all the beans defined in the bean configuration file whose types are compatible.

Ex:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
  http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<context:annotation-config/>	

	<bean id="company" class="com.examples.spring.Company">
		<property name="name" value="mycompany" />
	</bean>

	<bean id="key1" class="com.examples.spring.Employee">
		<constructor-arg name="name" value="Allan Donald" />
	</bean>
	<bean id="key2" class="com.examples.spring.Employee">
		<constructor-arg name="name" value="Sachin Tendulkar" />
	</bean>
	<bean id="key3" class="com.examples.spring.Employee">
		<constructor-arg name="name" value="Steven Waugh" />
	</bean>
</beans>

The Company class demonstrating the use of @Autowired annotation to populate a Map, a List and an Array

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.examples.spring;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;

public class Company
{
    private String companyName;

    private Map<String, Employee> mapOfEmployees;
    private List<Employee> listOfEmployees;
    private Employee[] arrayOfEmployees;

    public void setName(String name)    {        
		this.companyName = name;
    }
    public String getName() {
        return companyName;
    }
    @Autowired
    public void setEmployees(Map<String, Employee> employees) {
        this.mapOfEmployees = employees;
    }
    @Autowired
    public void setEmployees(Employee[] employees) {
        this.arrayOfEmployees = employees;
    }
    @Autowired
    public void setEmployees(List<Employee> employees) {
        this.listOfEmployees = employees;
    }
    public Map<String, Employee> getMapOfEmployees() {
        return mapOfEmployees;
    }
    public List<Employee> getListOfEmployees() {
        return listOfEmployees;
    }
    public Employee[] getArrayOfEmployees() {
        return arrayOfEmployees;
    }
}

The Employee class definition

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.examples.spring;

public class Employee {
 private String empName;

 public Employee(String name) {
  this.empName = name;
 }

 public String getName() {
  return empName;
 }
}

The client program prints the list of employees in the Map, List and Array populated earlier using the springs auto-wiring method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.examples.spring;

import java.util.List;
import java.util.Map;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App
{
    public static void main(String[] args)
    {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Company company = (Company)context.getBean("company");

        for (int i = 0; i < 2; ++i)
            System.out.println();

        System.out.println("Displaying Employee Map");
        Map<String, Employee> mapOfEmployees = company.getMapOfEmployees();
        for (Map.Entry<String, Employee> entry : mapOfEmployees.entrySet())
        {
            System.out.println("Key: " + entry.getKey() + " Name: " + entry.getValue().getName());
        }

        System.out.println();
        System.out.println("Displaying Employee List");
        List<Employee> listOfEmployees = company.getListOfEmployees();
        for (Employee emp : listOfEmployees)
        {
            System.out.println("Name: " + emp.getName());
        }

        System.out.println();
        System.out.println("Displaying Employee Array");
        Employee[] arrayOfEmployees = company.getArrayOfEmployees();
        for (Employee emp : arrayOfEmployees)
        {
            System.out.println("Name: " + emp.getName());
        }
    }
}