In this Spring tutorial, you will learn how to configure dependency injection in Spring framework using Java-based configuration (Java config).

You know, Spring allows you to make dependency injection using XML and annotations - but they have some drawbacks:

- Dependency injection via XML: though this makes configured classes independent of Spring API, the nature of XML makes it hard to navigate through the dependency relationship among classes when the application’s code grows and becomes more complex.

- Dependency injection using annotations: this makes the configured classes tightly coupled with Spring API - the @Component, @Service, @Autowired… annotations.

Therefore, Spring provides Java config approach for dependency injection, which can eliminate the drawbacks of XML and annotations: configured classes are not polluted by Spring annotations and they are easily navigable.

Let’s see how dependency injection can be done with Java configuration in Spring.

 

1. How to use Java Configuration for Dependency Injection

With Java config approach, you don’t put annotations into your business classes anymore. Instead, you write a separate Java configuration class to configure the dependency injection by instantiating the objects directly. Consider the following class:

package net.codejava;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
	
	@Bean("client1")
	public Client getClient1(Service service1) {
		return new ClientImpl(service1);
	}
	
	@Bean("service1")
	public Service getService1() {
		return new ServiceImpl1();
	}
}
Here, the AppConfig class is marked with the@Configuration annotation indicates that this class will be processed by Spring IoC (Inversion of Control) container to generate bean instances based on the@Bean methods. You can see:

@Bean("client1")
public Client getClient1(Service service1) {
	return new ClientImpl(service1);
}
This getClient1() method is marked with the @Bean annotation - tells Spring that it returns a bean to be managed by the application context. This bean is an instance of the Client interface and has name client1. The Client interface is defined as follows:

package net.codejava;

public interface Client {
	void doSomething();
}
And the ClientImpl class:

package net.codejava;

public class ClientImpl implements Client {

	private Service service;
	
	public ClientImpl(Service b) {
		this.service = b;
	}

	@Override
	public void doSomething() {
		String info = service.getInfo();
		System.out.println(info);
	}
}


You can see a ClientImpl object depends on an object of type Service, which can be injected via constructor. Look at the next @Bean method:

@Bean("service1")
public Service getService1() {
	return new ServiceImpl1();
}
This method creates a bean instance of type Service with name service1 - the return type and the name match the parameter of the getClient1() method so Spring injects the bean service1 to the bean client1. And these two beans are managed in application context.

The Service interface is defined as follows:

package net.codejava;

public interface Service {
	String getInfo();
}
And the ServiceImpl1 class:

package net.codejava;

public class ServiceImpl1 implements Service {

	@Override
	public String getInfo() {
		return "Service 1's Info";
	}
}
That’s basically how to configure dependency injection in Spring using Java config - and the technique above called inter-bean references. You see, the configured classes are really pure - they are not polluted by Spring annotations. And you can easily navigate the code of the configuration class AppConfig to understand the dependency among classes.

 

More about bean name resolution:

If you omit the name in the @Bean annotation, Spring will use the method name as bean name. This may helpful in reducing the boiler-plate code and use the defaults. For example:

@Bean
public Client client2() {
	return new ClientImpl(service2());
}

@Bean
public Service service2() {
	return new ServiceImpl2();
}
Here, the method client2() registers a bean named client2 and the method service2() registers a bean named service2.

A bean can have multiple names like this:

@Bean({"service", "srv", "SRV"})
public Service service3() {
	return new ServiceImpl3();
}
Here, the bean returned by this method has a primary name and two aliases. Of course you can get this bean by using any name listed.


2. Create Maven Project in Eclipse

Now, let’s see how to create a simple Java console program in Eclipse IDE to make use of dependency injection with Java config in Spring.

In Eclipse, click File > New > Maven project. Check the option Create a simple project (skip archetype selection). Type Group Id and Artifact Id for the project, and then add the following XML in the pom.xml file:

<dependencies>
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.7.RELEASE</version>
  </dependency>
</dependencies>
At least, you need to use this dependency to use dependency injection with Spring framework. Then create Java classes as describe above: Client, ClientImpl, Service, ServiceImpl1, ServiceImpl2 and ServiceImpl3 under the package net.codejava in src/main/java folder.

And write the configuration class as follows:

package net.codejava;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
	
	@Bean("client1")
	public Client getClient1(Service service1) {
		return new ClientImpl(service1);
	}
	
	@Bean("service1")
	public Service getService1() {
		return new ServiceImpl1();
	}

	@Bean
	public Client client2() {
		return new ClientImpl(service2());
	}
	
	@Bean
	public Service service2() {
		return new ServiceImpl2();
	}
	
	@Bean({"service", "srv", "SRV"})
	public Service service3() {
		return new ServiceImpl3();
	}
}
That’s all for the dependency injection configuration.


3. Test Spring Dependency Injection with Java Config

To load the configuration class, we need to create an instance of the AnnotationConfigApplicationContextclass and pass the name of the configuration class to its constructor, for example:

ApplicationContext appContext = new AnnotationConfigApplicationContext(AppConfig.class);
And then you can obtain a bean from the application context like this:

Client client1 = (Client) appContext.getBean("client1");
client1.doSomething();
In case you have multiple configuration classes, you can specify them like this (using var-arg constructor):

ApplicationContext appContext = new AnnotationConfigApplicationContext(AppConfig1.class, AppConfig2.class, AppConfig3.class);
You can also use the register() method, but then you have to refresh the application context. For example:

AnnotationConfigApplicationContext appContext = new AnnotationConfigApplicationContext();
appContext.register(AppConfig.class, AppConfig2.class, AppConfig3.class);
appContext.refresh();
Therefore, create class with main method named SpringDependencyInjectionExample as follows:

package net.codejava;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class SpringDependencyInjectionExample {

	public static void main(String[] args) {
		ApplicationContext appContext = new AnnotationConfigApplicationContext(AppConfig.class); 
		
		Client client1 = (Client) appContext.getBean("client1");
		client1.doSomething();
		
		Client client2 = (Client) appContext.getBean("client2");
		client2.doSomething();
		
		Service service = (Service) appContext.getBean("srv");
		System.out.println(service.getInfo());
	}
}
Run this program and you can see the following output:

Service 1's Info
Service 2's Info
Service 3's Info
That’s how to configure dependency injection with Java config in Spring. We hope you have found this tutorial helpful to get started with Spring framework.

 

 

References:

 

Related Spring Dependency Injection Tutorials: 

 

Other Spring Tutorials:


About the Author:

is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.



Attachments:
Download this file (SpringDependencyInjectionJavaConfig.zip)SpringDependencyInjectionJavaConfig.zip[Sample project for Spring dependency injection using Java config]16 kB