Spring Beans

Spring Bean is an object in the Spring framework that is initialized by spring container. A Java POJO class can be a spring bean if it is configured by Spring container. Configuration information can be given by XML, annotation or Java code.

Spring Bean Configuration

Beans in the spring container are defined by two ways:

  • XML Based Configuration: XML configuration files are used to define beans, their life cycle, dependency injects etc. Beans can be defined by XML tag or Annotations.

  • Java Based Configuration: Java configuration files are used to define beans, their life cycle, dependency injects etc. Beans are defined by only annotations in the this configuration. Annotation @Configuration, @ComponentScan and @Bean are used to configure the beans.

1. XML based configuration

In this configuration beans are defined using xml tags in applicationContext.xml file or annotations specified at the top of class.

  1. <bean> tag used to configure the bean and

  2. Annotations @Component, @Controller, @Service, @Repository, @RestController are used to define the beans. Basic annotation is @Component that will see here. Specialized annotations @Controller, @Service, @Repository, @RestController will be seen when we will study Spring MVC and Spring Boot

Here is example XML tag configuration by which we are configuring Role and User beans and injecting Role bean into User bean:

<bean id="roleBean" class="com.sunilos.spring.bean.Role" />

<bean id="userBean" class="com.sunilos.spring.bean.User">

<property name="firstName" value="SunilOS" />

<!--Inject role bean using setter injection -->

<property name="role" ref="roleBean" />

</bean>

In order to use annotation a you have make following entry in the ApplicationContext.xml file

<context:component-scan base-package="com.sunilos.spring" />

Above tag will enable component scanning in the given base and its sub packages. After scanning (called auto discovery) it will register annotated @Component beans to IOC container.

@Component

public class Payment {

...

}


@Component

public class Inventory {

...

}


public class Order {

@Autowired

private Payment p = null;


@Autowired

private Inventory i = null;


private int id = 0;

private double amount = 0;


public int getId() {

return id;

}


public void setId(int id) {

this.id = id;

}

public double getAmount() {

return amount;

}

public void placeOrder(int qty, double price) {

amount = qty * price;

p.makePayment(amount);

i.sold(qty);

System.out.println("Balance: " + p.getBalance());

System.out.println("Stock : " + i.getStock());

}

}


Above code defines three beans Payment, Inventory and Order using @Component annotation. Inventory and Payment beans are injected into Order bean using @Autowired annotation.

Property Initialization by XML

Bean properties can be initialized by <property> tag. In User bean we have initialized value of firstName by "SunilOS":

<property name="firstName" value="SunilOS" />

Collection values can be initialized by <LIST> and <MAP> xml tags.

<property name="city">

<list>

<value>Mumbai</value>

<value>Delhi</value>

</list>

</property>

<property name="role">

<map>

<entry>

<key><value>1</value></key>

<value>Super User</value>

</entry>

<entry>

<key><value>2</value></key>

<ref bean="admin"/>

</entry>

</map>

</property>

Property Initialization by Annotation

@Component

public class Payment {

@Value(value = "100")

double balance = 0;

}

Life Cycle methods

Bean is created and managed by container. Sometimes developer has to perform some custom operations after creation of the bean or before destruction of the bean. Container provides a way to perform some custom operations after bean creation and before bean destruction using life cycle methods.

Life cycle method can be defined by XML tag or Annotation:

XML bean tag has two attributes init-method and destroy-method to define the life cycle methods. Life cycle methods must be Zero argument methods.

Following example defines life cycle methods init() and destroy() for Customer bean:

<bean id="customerBean" class="com.sunilos.spring.bean.Customer" init-method="init" destroy-method="destroy">

<constructor-arg name="account" ref="accountBean"></constructor-arg>

</bean>

Following example defined life cycle methods using @PostConstruct and @PreDestroy annotations:

@Component("order")

@Scope("prototype")

public class Order {

...

@PostConstruct

public void init(){

System.out.println("This is order init method");

}

@PreDestroy

public void destroy(){

System.out.println("This is order destroy method");

}

}

2. Java based configuration

Instead of xml file you can use Java class to configure java beans. Java configuration uses @Configuration, @ComponentScan, @Bean, @Import, @DependsOn etc annotations.

  1. @Configuration annotation indicates that the class will be used to define beans. Spring container will use this class as source of bean definitions for the IOC container.

  2. @ComponentScan annotation is used to scan annotated beans in the given base package and its sub-packages.

  3. @Bean annotation is used to build custom bean and register with IOC container.

Following example has configuration java class that scans beans into base package "com.sunilos.spring" and register custom beans userBean, roleBean, accountBean, customerBean with IOC container using @Bean annotation.

@Configuration

@ComponentScan(basePackages = { "com.sunilos.spring" })

public class AppConfig {

@Bean(name = "userBean")

public User user() {

User user = new User();

user.setFirstName("SunilOS");// Initialize value

user.setRole(role());// Inject dependency

return user;

}

@Bean(name = "roleBean")

public Role role() {

Role role = new Role();

return role;

}

@Bean(name = "accountBean")

public Account account() {

Account account = new Account();

return account;

}

@Bean(name = "customerBean")

public Customer customer() {

Customer customer = new Customer();

customer.setAccount(account());//Inject dependency

return customer;

}

}

AnnotationConfigApplicationContext is used to read java configuration and get the container.

public class TestJavaConfig {

public static void main(String[] args) {

ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

User bean = context.getBean("userBean", User.class);

System.out.println("Bean contains " + context.containsBean("userBean"));

System.out.println("Type of bean " + context.getType("userBean"));

System.out.println("is Singlton " + context.isSingleton("userBean"));


// print first name value

System.out.println(bean.getFirstName());

System.out.println(bean.getRole().getName());


Order o = (Order) context.getBean("order");

o.placeOrder(2, 5);

System.out.println(o.getAmount());

System.out.println("------Customer bean--------");


Customer customer = (Customer) context.getBean("customerBean");

System.out.println("Account balance :" + customer.getAccount().getBalance());


}

}

Spring Annotations

Spring provides annotations to configure beans.

  1. Beans are defined using @Component, @Service, or @Repository annotations.

  2. Life cycle methods are defined by @PostConstruct and @PreDestroy annotations.

  3. Annotation @Value is used to initialize attributes.

  4. Scope of a bean can be defined by @Scope annotation.

  5. Dependency can be injected using @Autowired annotation.

Annotated classes are scanned and registered in container using <context:component-scan> tag in applicationContext.xml file. Scan tag scanned all annotated classes from base and its sub packages and register with container. If you do not use <context:component-scan> tag then you have to use <annotation-driven /> tag to enable annotations.

Annotations

1. @Component annotation

The @Component annotation is used to define and register a java class as a bean with spring container. Here payment and user service classes are annotated by @Component to define as a bean.

@Component

public class Payment{

}

@Component

public class UserService{

}

By default name of class is used to register and identify a bean in container. First character of class name is converted to lowercase to name the bean. Payment and UserService classes will be registered by “payment” and “userService” names respectively.

A custom bean name can be given as parameter to @Component annotation.

Here name "orderBean" is given to order bean:

@Component("orderBean")

public class Order {

...

}

Order o = context.getBean("orderBean ", Order.class);

Specialized (Child) annotation of @Component

The @Component annotation has three specialized annotations @ Controller, @Service and @Repository.

The @Controller is used to define controller classes in Spring MVC. @Service annotation is used to create business logic classes. @Repository is used to define data access objects.

2. @PostConstruct and @PreDestroy Annotations

These are used to define bean life cycle methods

3. @Value Annotations

The @Value annotation is used to set default value of an attribute.

@Value(value = "100")

int stock = 0;

4. @Required annotation

@Required annotation is applied on setter methods. It indicates that the bean property must be initialized in XML configuration file at configuration time. Otherwise container throws a BeanInitializationException exception.

public class User{

private String firstName = null;

@Required

public void setFirstName(String fn) {

this.firstName = fn;

}

..

}

<bean id="userBean" class="com.sunilos.spring.bean.User">

<property name="firstName" value="SunilOS" />

</bean>

5. Define scopes

Scope of a bean is defined by scope attribute of <bean> tag. By defining scope you can create singleton beans. Bean has five scopes; singleton, prototype, request, session and globalsession. Default scope is singleton.

<bean id="emailService" scope="singleton" class="com.sunilos.book.spring.bean.EmailService" />

Singleton beans has only one instance in its lifetime whereas instance of prototype bean is created again and again when you call getBean() method of container. Rest three scopes are used in web applications.

Scope can be defined by @Scope annotation:

@Scope("singleton")

public class UserService {

...

}


FAQ

Q: What are the difference between @Bean and @Component annotations.

  1. @Bean annotation is used to build custom bean and register with IOC container.

Q: What is the function of @ComponentScan annotation?

It is used to scan the component in the base package and register with the container. It s called auto discovery.

Q: What is the use of @Configuration annotation?