What is a bean

A bean in java context is a simple java class which has some properties (also called fields) and their getter and setter methods.
These properties can be regarded as instance variables of the bean. The name of the properties and their getter/setter methods should adhere to the JavaBeans specifications (should start with a small letter, should be camel-case and so on).


How to create bean?
There are many ways to create a bean in Spring and all of them will be discussed here.

All of the methods involve creating a class which will be regarded as a bean.
So first let’s create a class called User.

package com.codippa;
 
  public class User {
  
     private String name;

     private String address;
  
     public String getName() {
        return name;
     }

     public void setName(String name) {
        this.name = name;
     }

     public String getAddress() {
        return address;
     }

     public void setAddress(String address) {
        this.address = address;
     }
  }

In a simple java program, we create an instance or object of a class using new keyword but in Spring, there are different ways to create an instance of a bean class without using new.

Although, using new keyword is permitted but is not recommended since injection of properties and Autowiring does NOT work if you create a bean using new.

Let’s discuss the ways to create a bean in Spring.
1. Declaring a bean in XML configuration file
This is the most primitive approach of creating a bean. A bean is declared in Spring’s XML configuration file.

Upon startup, Spring container reads this configuration file and creates and initializes all the beans defined in this file which can be used anytime during application execution.

Here is how we define a bean in configuration XML.

<bean id=”user” class=”com.codippa.User”></bean>

Note : This method assumes that you are familiar with Spring XML configuration and how it is configured.

Explanation
A bean in Spring XML configuration file is defined using element declaration.
The id attribute is used to uniquely identify the bean and get its reference during execution (shown later).
The class attribute should contain the fully qualified class name.

This bean can be retrieved and used in the application in the following way :

public class Main {
  @SuppressWarnings("resource")
  public static void main(String[] args) {
    ApplicationContext context = new AnnotationConfigApplicationContext(User.class);
    User user = (User)context.getBean("user");
    System.out.println(user.getName());
    System.out.println(user.getAddress());
  }
}

Let’s tweak in

  1. The id attribute is not mandatory and is only required when you want to access this bean in application or provide this bean as a dependency to some other bean.
  2. The id of a bean should be unique otherwise you will get an error at start up like

    org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Bean name ‘test’ is already used in this <beans> element.

  3. Scope of bean shall be singleton by default which means every time the bean is referred, same instance will be returned.
    The scope of bean can be changed by introducing a scope attribute in bean declaration.
  4. Bean properties referred in the property element should have valid setter methods otherwise following error will be received.

    Bean property ‘name’ is not writable or has an invalid setter method.

  5. Spring automatically does the string to number conversion in case the type of a class property is numeric while the values provided in XML configuration file are in string format.
    But you will get a java.lang.NumberFormatException if the property is not convertible to a number.
2. Using @Component annotation
@Component annotation above a class indicates that this class is a component and should be automatically detected and instantiated.
Thus, a Spring component bean will look like :

package com.codippa;
 
@Component
public class User {

   private String name;

   private String address;

   public String getName() {
     return name;
   }

   public void setName(String name) {
     this.name = name;
   }

   public String getAddress() {
     return address;
   }

   public void setAddress(String address) {
      this.address = address;
   }
}

Explanation
In order for a bean to be auto-discoverable and instantiated, we need to instruct Spring container to find our beans and tell it about the package where it should find the beans.

Hence, for instantiating annotated beans, we need to add following declaration in our Spring XML configuration file :

<context:component-scan base-package=”com.codippa” />

If the bean annotated with @Component annotation is outside of the package given in base-package attribute of the above element, then it will not be scanned and instantiated and thus will not be found.
This bean can also be used in the same way as the bean in the first method.
Thus, only bean declaration methods differ while the method of using them remains the same.

Let’s tweak in

  1. @Component annotation can only be applied at class level.
    Applying it to some other location such as above a field will result in a compiler error The annotation @Component is disallowed for this location.
  2. If a bean is referred and it has not been annotated with @Component or declared in XML configuration then there will be an exception as :

    org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.codippa.User] is defined

  3. Automatically instantiating a bean using @Component annotation requires that there is a default constructor present in the class.
    A default constructor is a constructor without any arguments.If there is no constructor present in a class then a default constructor is automatically created. If there is a constructor in your bean class which accepts some arguments then you have to create a default constructor yourself.
    Absence of default constructor will arise an error as

    org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.codippa.User]: No default constructor found

3. Using @Configuration annotation

This method does not require any XML file and it can be used to create a bean without XML configuration file.
Create a class which you want to get as a bean, say a user and annotate it with @Configuration as:

@Configuration
public class User {
  @Value("codippa")//initialize the value of this field
  private String name;
  @Value("India")
  private String country;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getCountry() {
    return country;
  }

  public void setCountry(String country) {
    this.country = country;
  }
  
}

Create an executable class having main method to test this method.
This class uses AnnotationConfigApplicationContext as ApplicationContext implementation to retrieve a bean from Spring context.

public class Main {

   @SuppressWarnings("resource")
   public static void main(String[] args) {
      ApplicationContext context = new AnnotationConfigApplicationContext(User.class);
      User user = (User)context.getBean("user");
      System.out.println(user.getName());
      System.out.println(user.getCountry());
   }
}

Note that the name of the bean used to get it from the context is the name of the class in camel case.
Above example print

codippa
India

Let’s tweak in

    1. You can also define packages where your beans reside instead of class names in AnnotationConfigApplicationContext as AnnotationConfigApplicationContext(“com.codippa”).
    2. @Configuration annotated class may also contain other bean definitions whose getter methods should be annotated with @Bean such as :
      @Configuration
      public class User {
         @Bean(name="extUser")
         public ExternalUser getUser() {
            return new ExternalUser();
         }
      }

      The bean with name “extUser” can be retrieved using getBean method of ApplicationContext as in above example.

    3. @Value is used to provide value to class fields. The value may be given there only or may be fetched from an external property file using ${propertyName}.
    4. @Configurationis a class-level annotation.
      Applying it to some other level (such as a method or a field) will generate a compiler error
      The annotation @Configuration is disallowed for this location.
Hope this post helped you learn various method of creating bean in Spring.

Leave a Reply