×
☰ See All Chapters

Spring @Configuration Annotation

When a class is annotated with @Configuration annotation, spring container process that class and generates the beans from all the methods those annotated with @Bean annotation.

package com.java4coding;

 

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

 

@Configuration

public class SpringConfiguration {

       

    @Bean(name="mangoBean")

    public Mango getMangoBean() {

        return new Mango();

    }

       

    @Bean(name="appleBean")

    public Apple getAppleBean() {

        return new Apple();

    }

}

We can have multiple classes annotated with @Configuration annotation.

package com.java4coding;

 

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

 

@Configuration

public class MangoConfiguration {

        @Bean(name="mangoBean")

    public Mango getMangoBean() {

        return new Mango();

    }

}

 

package com.java4coding;

 

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

 

@Configuration

public class AppleConfiguration {

    @Bean(name="appleBean")

    public Apple getAppleBean() {

        return new Apple();

    }

}

How to bootstrap configuration class

Classes annotated with @Configuration can be bootstrapped using either AnnotationConfigApplicationContext or AnnotationConfigWebApplicationContext. We have the below three ways to register the configuration class with AnnotationConfigApplicationContext or AnnotationConfigWebApplicationContext.

  1. By Calling register method of AnnotationConfigApplicationContext 

  2. By passing Class objects of all configuration classes to constructor of AnnotationConfigApplicationContext 

  3. By passing package name to constructor of AnnotationConfigApplicationContext 

By Calling register method of AnnotationConfigApplicationContext

Create a new AnnotationConfigApplicationContext and then call register(java.lang.Class...) method to register the configuration classes. register method accepts multiple configuration classes Class objects and bootstrap them, register method has below signature.

public void register(java.lang.Class<?>... annotatedClasses)

package com.java4coding;

 

import org.springframework.context.ConfigurableApplicationContext;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

 

public class Demo {

        public static void main(String[] args) {

                AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

                context.register(MangoConfiguration.class, AppleConfiguration.class);

                context.refresh();

                Apple apple = (Apple) context.getBean("appleBean");

                Mango mango = (Mango) context.getBean("mangoBean");

                mango.printFruitName();

                apple.printFruitName();

                ((ConfigurableApplicationContext)context).close();

        }

}

It is very important to call refresh() method after all configuration classes’ registration. Otherwise we will get IllegalStateException error when we try to get any bean from the context.

By passing Class objects of all configuration classes to constructor of AnnotationConfigApplicationContext

Create a new AnnotationConfigApplicationContext by passing Class objects of all configuration classes to its constructor

package com.java4coding;

 

import org.springframework.context.ConfigurableApplicationContext;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

 

public class Demo {

  public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MangoConfiguration.class, AppleConfiguration.class);

        Apple apple = (Apple) context.getBean("appleBean");

        Mango mango = (Mango) context.getBean("mangoBean");

        mango.printFruitName();

        apple.printFruitName();

        ((ConfigurableApplicationContext) context).close();

  }

}

In this case it is not necessary to call refresh() method and spring bootstraps the configuration classes by automatically refreshing the context.

By passing package name to constructor of AnnotationConfigApplicationContext

Create a new AnnotationConfigApplicationContext by passing package name. In this case we can pass the each package name separately or we can pass single base package of all other packages.

AnnotationConfigApplicationContext context

= new AnnotationConfigApplicationContext(

"com.java4coding.apple", "com.java4coding.mango" );

OR

AnnotationConfigApplicationContext context

= new AnnotationConfigApplicationContext(

"com.java4coding" );

In both the case it is not necessary to call refresh() method and spring bootstraps the configuration classes by automatically refreshing the context.

package com.java4coding;

 

import org.springframework.context.ConfigurableApplicationContext;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

 

public class Demo {

  public static void main(String[] args) {

        //AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.java4coding.apple", "com.java4coding.mango" );

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.java4coding" );

        Apple apple = (Apple) context.getBean("appleBean");

        Mango mango = (Mango) context.getBean("mangoBean");

        mango.printFruitName();

        apple.printFruitName();

        ((ConfigurableApplicationContext) context).close();

  }

}

Spring @Configuration Annotation Example

pom.xml

<project xmlns="https://maven.apache.org/POM/4.0.0"

        xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">

        <modelVersion>4.0.0</modelVersion>

        <groupId>com.java4coding</groupId>

        <artifactId>Spring3_Configuration_Example</artifactId>

        <packaging>jar</packaging>

        <version>1.0-SNAPSHOT</version>

        <name>Spring3_Configuration_Example</name>

        <url>https://maven.apache.org</url>

        <properties>

                <org.springframework.version>3.2.0.RELEASE</org.springframework.version>

        </properties>

        <dependencies>

                <dependency>

                        <groupId>cglib</groupId>

                        <artifactId>cglib</artifactId>

                        <version>2.2.2</version>

                </dependency>

                <dependency>

                        <groupId>org.springframework</groupId>

                        <artifactId>spring-core</artifactId>

                        <version>${org.springframework.version}</version>

                </dependency>

                <dependency>

                        <groupId>org.springframework</groupId>

                        <artifactId>spring-beans</artifactId>

                        <version>${org.springframework.version}</version>

                </dependency>

                <dependency>

                        <groupId>org.springframework</groupId>

                        <artifactId>spring-context</artifactId>

                        <version>${org.springframework.version}</version>

                </dependency>

                <dependency>

                        <groupId>org.springframework</groupId>

                        <artifactId>spring-context-support</artifactId>

                        <version>${org.springframework.version}</version>

                </dependency>

        </dependencies>

</project>

Apple.java

package com.java4coding;

 

public class Apple{

        public void printFruitName(){

                System.out.println("Apple");

        }

}

Mango.java

package com.java4coding;

 

public class Mango {

        public void printFruitName(){

                System.out.println("Mango");

        }

}

SpringConfiguration.java

package com.java4coding;

 

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

 

import com.java4coding.Mango;

 

@Configuration

public class SpringConfiguration {

        @Bean(name = "mangoBean")

        public Mango getMangoBean() {

                return new Mango();

        }

 

        @Bean(name = "appleBean")

        public Apple getAppleBean() {

                return new Apple();

        }

}

Demo.java

package com.java4coding;

 

import org.springframework.context.ConfigurableApplicationContext;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

 

public class Demo {

  public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.java4coding" );

        Apple apple = (Apple) context.getBean("appleBean");

        Mango mango = (Mango) context.getBean("mangoBean");

        mango.printFruitName();

        apple.printFruitName();

        ((ConfigurableApplicationContext) context).close();

  }

}

Output:

Mango

Apple

What if class is not annotated with @Configuration annotation

@Bean annotation can be used methods whose class is not annotated with @Configuration. For example, bean methods may be declared in a @Component class or even in a plain old class. In such cases, a @Bean method will get processed in a so-called 'lite' mode. In lite mode, spring will not create any proxy for such classes; Spring does not intercept the invocation via a CGLIB proxy. This is analogous to inter-@Transactional method calls where in proxy mode, Spring does not intercept the invocation - Spring does so only in AspectJ mode.

Hence in lite mode bean methods will be treated as plain factory methods by the container (similar to factory-method declarations in XML), with scoping and lifecycle callbacks properly applied.

'inter-bean references' are not supported in lite mode. Instead, when one @Bean-method invokes another @Bean-method in lite mode, the invocation is a standard Java method invocation; For the below configuration class we have removed @Configuration by commenting, In this case getAppleConsumerBean() method will get a new instance of Apple bean. Hence we will have two instances of Apple bean.

package com.java4coding;

 

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

 

import com.java4coding.AppleConsumer;

 

//@Configuration

public class SpringConfiguration {

        @Bean(name = "appleConsumerBean")

        public AppleConsumer getAppleConsumerBean() {

                return new AppleConsumer(getAppleBean());

        }

 

        @Bean(name = "appleBean")

        public Apple getAppleBean() {

                return new Apple();

        }

}

The below two images show you the two execution by annotating with @Configuration annotation and without using @Configuration annotation.

spring-configuration-annotation-0
 
spring-configuration-annotation-1
If @Configuration annotation is removed from SpringConfiguration class, then we cannot register the beans by passing package name to AnnotationConfigApplicationContext. We can reigister either by calling register() method or by passing Class object of configuration class to AnnotationConfigApplicationContext.
 
spring-configuration-annotation-2
 

All Chapters
Author