16 - Java Based Container Configurations

16.1 Overview

In previous chapters we discussed annotations and XML based configurations. Spring also supports Java based configuration where we can define an application context, bean definition as annotation.

In this chapter, we will discuss following annotations

  • @Configuration
  • @Bean
  • @Scope

16.2 @Configuration

The @Configuration annotation applies only at a class level. Once done that class acts as a spring bean configuration file. Class annotated with @Configuration must have a default constructor.

Refer below sample structure

@Configuration
public class AppConfiguration {
       public AppConfiguration()
       {    
       }
}

16.3 @Bean

@Bean annotation is applied  to a method of a class annotated with @Configuration. One method annotated with @Bean is equivalent to one bean definition in spring bean definition.

Refer below sample structure

@Configuration
public class AppConfiguration {
       public AppConfiguration()
        {                               
        }               
       @Bean
       public Student student()
       {
         return new Student();
       }
}

Above class is equivalent of defining a student bean

     <bean id=”student” class=”Student” />

16.4 Dependency Injection

The calling @Bean annotated bean from another @Bean annotated method can inject the beans. For example, if Hostel bean has a dependency on  Student object, then following structure can be used.

@Configuration
public class AppConfiguration {
       Public AppConfiguration()
       {                              
       }               
       @Bean
       public Student student()
       {
         return new Student();
       }               
       @Bean
       public Hostel hostel()
       {
         return new Hostel(student());
       }              
}

Above configuration is equivalent to

<bean id=”student” class=”Student” />
<bean id=”hostel” class=”Hostel” >
        <constructor-arg ref=”student” />
</bean>

16.5 Lifecycle Callbacks

In earlier chapters we discussed that we can define and configure custom initialization and destroy methods using init-method and destroy-method attributes of a bean.

Similarly @Bean annotation supports initMethod and destroyMethod attributes to configure the name of callback methods .

@Configuration
public class AppConfiguration {
       public AppConfiguration()
       {                               
       }               
       @Bean(initMethod="init" ,destroyMethod="destroy")
       public Student student()
       {
         return new Student();
       }           
}

Above code is equivalent to below configuration and Student class will have init() and destroy() methods defined.

       <bean id=”student” class=”Student” init-method="init" destroy-method="destroy"/>

16.6 Bean name configuration

We can pass the bean name of the bean in the name attribute of @Bean annotation. By default the name of the method becomes  a bean name.

@Configuration
public class AppConfiguration {
       public AppConfiguration()
       {                               
       }             
       @Bean(name="studentBean")
       public Student getStudent()
       {
         return new Student();
       }               
       @Bean
       public Hostel hostel()
       {
         return new Hostel();
       }
}

Above code is equivalent to

<bean id=”studentBean” class=”Student” />
<bean id=”hostel” class=”Hostel”/>

16.7 @Scope

@Scope annotation is defined on a method and is used to configure the scope of a bean. By default scope is singleton so if any method annotated with @Bean configuration is not annotated with @Scope will be of singleton scope.

Possible value  can be passed in @Scope annotation

  • singleton
  • prototype
  • request
  • session
  • globalSession
@Configuration
public class AppConfiguration {
       public AppConfiguration()
       {                             
       }                              
       @Bean
       @Scope("prototype")
       public Student student()
       {
         return new Student();
       }               
       @Bean
       public Hostel hostel()
      {
        return new Hostel();
      }
}

In above code student bean is defined as prototype where as hostel bean will be singleton as singleton is a default scope.

Note: Though hostel method returns new Hostel() does not mean that a new hostel instance  will be returned always.

16.8AnnotationContextApplicationContext

Spring provides AnnotationContextApplicationContext class which takes @Configuration annotated classes to load the class.

Below code snippet will load the AppConfiguration class

ApplicationContext context = new AnnotationConfigApplicationContext(AppConfiguration.class);

If multiple @Configuration classes need to be loaded then register and refresh methods need to be called (refer below code snippet)

AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();                               
context.register(AppConfiguration.class);
context.refresh();

16.9Example

Lets write an example to demonstrate the above topics.

a. Student class

publicclass Student 
{
    private String name ;
    public String getName() {
        return name;
    }
    publicvoid setName(String name) {
        this.name = name;
    }
} 
b. Hotel class
publicclass Hostel {    
    private Student student;    
    public Hostel(Student student)
    {
        this.student= student;
    }
    publicvoid init()
    {
        System.out.println("init method  called !!!");
    }    
    @Override
    public String toString() {
        return "Hostel [student=" + student.getName() + "]";
    }    
}    

c. AppConfiguration class

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
publicclass AppConfiguration {
    public AppConfiguration()
    {        
    }    
    @Bean(name="student")
    @Scope("prototype")
    public Student getStudent()
    {
        Student student = new Student();
        student.setName("Student A");
        return student;
    }    
    @Bean( initMethod="init")
    public Hostel hostel()
    {
        returnnew Hostel(getStudent());
    }
}   

d. TestAnnotationConfiguration class

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class TestAnnotationConfiguration {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = 
    new AnnotationConfigApplicationContext();
    context.register(AppConfiguration.class);
    context.refresh();
Student studentA = (Student)context.getBean("student");
    Student studentB = (Student)context.getBean("student");
System.out.println("Is student bean is singleton?  " + (studentA==studentB));
    Hostel hostel1 = (Hostel)context.getBean("hostel");
    Hostel hostel2 = (Hostel)context.getBean("hostel");
    System.out.println(hostel1);        
    System.out.println(hostel2);
System.out.println("Is Hostel bean is singleton?  " + (hostel1==hostel2));
    ((AbstractApplicationContext)context).registerShutdownHook();;
    }
}
  1. Run TestAnnotationConfiguration class. You will see below output.
  • Init method gets called only once because Hostel bean is a singleton
  • Hostel bean displays the student name which means student object is injected properly
  • StudentA and StudentB  beans are not singleton because Student class is annotated with @Scope( “ prototype “)

Like us on Facebook