Categories
Spring Spring Core

Java-Based Container Configuration

In our previous Articles we saw XML Based container configuration and Annotation based container configuration in detail. In this Article we are going to look at how Spring applications can be configured using Java classes and few annotations with a simple example. 

Two main annotations on Java based container configuration in Spring are @Configuration and @Bean. We first look at the important key points on Each annotation first and then go for the simple working example.

@Configuration

  • @Configuration is a Class level annotation
  • Its basic functionality is to Configure and assemble the bean objects that are defined with @Bean annotation.
  • Ex.,:
@Configuration
public class AppConfig {
    @Bean
    public VideoController controller() {
        return new EnglishVideoImpl();
    }
}

The above example is equivalent to the following XML Configuration:

<bean class=”net.geekcoders.EnglishVideoImpl”></bean>
  • All the @Bean annotated methods will get instantiated in Spring IoC Container and referred from there for every call. Since, for Singleton scoped Bean only one time the object will get created and for other scopes their own life-cycle will be performed accordingly.

@Bean

  • @Bean is a Method level annotation
  • Bean objects will register in ApplicationContext when a Method is annotated with @Bean.
  • Bean annotations refers to the method going to Instantiate, Configure and initializes a new bean in Spring IoC Container(ApplicationContext).
  • We can use @Bean annotated method in @Configuration annotated Class or @Component annotated class. Mostly we use @Bean in @Configuration classes only.
  • @Bean is equivalent to <bean/> tag in XML configuration.
  • Bean annotation supports various attributes provided by <bean/> tag. Those are init-method, destroy-method, autowiring and name.

Ex.,:

@Bean(name = "EnglishVideos", destroyMethod = "destroy", initMethod = "init", autowire = Autowire.BY_NAME)
	public VideoManager EnglishVideoImpl() {
		return new EnglishVideoImpl();
	}
  • From the example above, the Bean name will be “EnglishVideos”.If no name is declared in @Bean attribute, IoC Container will take method name as Bean name. 
  • For Java Based container configuration, always use Direct class name as return type. You can also use the Object’s type as return type as like the above example(VideoManager is an Interface implemented by EnglishVideoImpl class). 
  • If you are using more than one Bean in the same context with the same type, then Spring will throw nouniquebeandefinitionexception. To avoid such exceptions you can use the name attribute in @Bean annotation and @Qualifier annotation where you are injecting the dependency. 

Ex.,:

@Bean
	public VideoController videoController(@Qualifier("EnglishVideos") VideoManager englishVideos, @Qualifier("SpanishVideos") VideoManager spanishVideos) {
		VideoController controller = new VideoController();
		controller.setEnglishVideos(englishVideos);
		controller.setSpanishVideos(spanishVideos);
		return controller;
	}
  • The above example uses @Qualified to avoid NONUNIQUEBEANDEFINITIONEXCEPTION and Setter-Based Dependency Injection.
  • You can use any number of Parameters to the Bean method to Inject dependencies. 
  • Java Based Configuration supports both Setter-Based Dependency Injection and Constructor-Based Dependency Injection.

Constructor-Based Dependency Injection Example :

@Bean
	public VideoController videoController(@Qualifier("EnglishVideos") VideoManager englishVideos, @Qualifier("SpanishVideos") VideoManager spanishVideos) {
		return new VideoController(englishVideos, spanishVideos);
	}

Setter-Based Dependency Injection Example :

@Bean
	public VideoController videoController(@Qualifier("EnglishVideos") VideoManager englishVideos, @Qualifier("SpanishVideos") VideoManager spanishVideos) {
		VideoController controller = new VideoController();
		controller.setEnglishVideos(englishVideos);
		controller.setSpanishVideos(spanishVideos);
		return controller;
	}
  • You can add scope to the @Bean method by using @Scope annotation as below.
@Bean(name = "EnglishVideos")
	@Scope("prototype")
	public VideoManager EnglishVideoImpl() {
		return new EnglishVideoImpl();
	}

Java-Based Container configuration in Spring Example : 

I’m using Eclipse IDE, Java 8 and Spring 5.2.7 Libraries for this example.

Step 1 : Controller

Create VideoController class and copy below code.

package net.geekcoders.controllers;

import net.geekcoders.services.VideoManager;

public class VideoController {
	private VideoManager englishVideos;
	private VideoManager spanishVideos;
	
	/**
	 * Method to get English and Spanish Language videos
	 */
	public void getAllVideos() {
		System.out.println("getAllVideos :: Method to get English and Spanish Language Videos");
		this.getEnglishVideos().listOfVideos();
		this.getSpanishVideos().listOfVideos();
	}

	public VideoManager getEnglishVideos() {
		return englishVideos;
	}

	public void setEnglishVideos(VideoManager englishVideos) {
		this.englishVideos = englishVideos;
	}

	public VideoManager getSpanishVideos() {
		return spanishVideos;
	}

	public void setSpanishVideos(VideoManager spanishVideos) {
		this.spanishVideos = spanishVideos;
	}
	
}

Step 2 : Interface

Now Create VideoManager Interface and copy below code.

package net.geekcoders.services;

import java.util.List;

public interface VideoManager {
	List<String> listOfVideos();
}

Step 3 : Implementations

EnglishVideoImpl.java

package net.geekcoders.services;

import java.util.ArrayList;
import java.util.List;

public class EnglishVideoImpl implements VideoManager {

	@Override
	public List<String> listOfVideos() {
		System.out.println("EnglishVideoImpl :: getting list of English Videos from DB/Files");
		return new ArrayList<String>();
	}

}

SpanishVideoImpl.java

package net.geekcoders.services;

import java.util.ArrayList;
import java.util.List;

public class SpanishVideoImpl implements VideoManager {

	@Override
	public List<String> listOfVideos() {
		System.out.println("SpanishVideoImpl :: getting Spanish videos from DB/Files");
		return new ArrayList<String>();
	}

}

Step 4 : IoC Configuration with Java class

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import net.geekcoders.controllers.VideoController;
import net.geekcoders.services.EnglishVideoImpl;
import net.geekcoders.services.SpanishVideoImpl;
import net.geekcoders.services.VideoManager;

@Configuration
public class AppConfig {

	public static void main(String[] args) {
		System.out.println("AppConfig");
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
		applicationContext.register(AppConfig.class);
		applicationContext.refresh();

		VideoController controller = applicationContext.getBean(VideoController.class);
		controller.getAllVideos();

	}

	@Bean
	public VideoController videoController(@Qualifier("EnglishVideos") VideoManager englishVideos, @Qualifier("SpanishVideos") VideoManager spanishVideos) {
		VideoController controller = new VideoController();
		controller.setEnglishVideos(englishVideos);
		controller.setSpanishVideos(spanishVideos);
		return controller;
	}

	@Bean(name = "EnglishVideos")
	public VideoManager EnglishVideoImpl() {
		return new EnglishVideoImpl();
	}

	@Bean(name = "SpanishVideos")
	public VideoManager SpanishVideoImpl() {
		return new SpanishVideoImpl();
	}

}
  • In the above AppConfig class, we have three Bean’s configured with @Bean annotation. @Configuration denotes that the AppConfig class is a Configuration class with Bean definitions.
  • We have used Setter-Based Dependency Injection in this example code.
  • When you run the above program from the AppConfig class you are able to see the below output in console.
  • You can observe that, we have not used any one annotation or xml configuration other than AppConfig.java class to configure and run this example. This will help us to manage the application Bean’s and components in one single place.

That’s all for now on Spring Java Based Configuration with example…

Happy Reading!!! 

Leave a Reply

Your email address will not be published. Required fields are marked *