Categories
Spring Spring Core

Dependency Injection using @Inject and @Named Annotations

We have many ways to Inject Dependencies in Spring. XML Configuration, @Autowired Annotation, @Resource annotation are few of them. Among these methods we have JSR 330 Standard annotations as well.

We can choose any one of these based on our application needs.

Key Points :

  • @Inject can be used instead of @Autowired and @Resource annotations and @Named can be used instead of @Qualifier and Stereotype annotations.
  • The Difference between @Autowired and @Inject is there is no required attribute available like @Resource in @Inject annotation also.
  • @Auto-wiring is Spring specific annotation, whereas @Inject is a JSR 330 Standard annotation as mentioned above.
  • The Dependency is Mandatory when using @Inject. If it is not available,it will throw an exception at run-time.
  • You can use @Nullable annotation to complement the required attribute of @Auto-wiring and make the dependency optional while using @Inject.
  • All the Bean’s annotated with @Inject is Singleton by default.
  • As like Stereotype annotations we don’t Separate annotation for Controller, Service and DAO layer. We have to use only @Named in all three layers.
  • Can provide Qualifier name via Named annotation to identify the bean while injecting dependency. Ex., @Named(“beanName”)
  • To use @Inject annotation in your application, you have to provide its dependency in the pom.xml file(In case of Maven).
<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>
Spring AnnotationJSR 330 AnnotationLimitations of JSR 330 Annotation
@Autowired@InjectNo required attribute.
Can be used with Java 8 Optional or @Nullable annotation
@Component, @Service, @Controller, @Repository@Named@Named for all three layers. No composed annotation to specific layers.
@Scope(“Singleton”)@SingletonIf you are using other than Singleton scope have to use Spring’s Scope annotation only. JSR’s @Scope is designed in the intention of to create our own scope
@Qualifier@NamedInstead of using Qualifiers, can use @Named to resolve named dependencies.
@ValueNo equivalent
@Required(Deprecated)No equivalent
@LazyNo Equivalent
Difference between Spring Annotations and JSR 330 Annotations

We can use @Inject in Identifiers, Constructor and Setter-Methods as like Autowiring

@Inject as Construction Injection

@Inject
	public VideoController(@Named("spanish") @Nullable VideoLister spanishVideo, @Named("english") VideoLister englishVideo) {
		// code goes here
	}

I have used @Nullable here, if the SpanishVideo Bean is not found. It won’t throw an exception.

Using @Named instead of Qualifier annotation. It will resolve the required dependency based on the qualifier value provided.

@Inject as Setter-Injection

@Inject
	public void setEnglishVideos(@Named("english") VideoLister englishVideos) {
		this.englishVideos = englishVideos;
	}

@Inject using Identifiers

	@Inject
	@Named("english")
	private VideoLister englishVideos;

	@Inject
	@Named("spanish")
	@Nullable
	private VideoLister spanishVideos;

If you missed to provide @Named annotation with qualifier value, then NoUniqueBeanDefinitionException will arise.

I hope you are clear on the usage of @Inject and @Named annotations from the above coding snippets.

We shall begin the example code. I’m going to use Injection from Identifiers and mention Qualifier names in Service layer classes to avoid NoUniqueBeanDefinitionException.

In this Article I’m going to use only JSR 330 Standard annotations to Inject dependencies.

I’m using JDK 8 and Spring 5.2.7 and created a Maven project using Eclipse. You can copy the below required dependencies in your pom.xml file to begin.

<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>5.2.7.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>5.2.7.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>
	</dependencies>

For our example application, We have a Controller Layer and Service layer. VideoController will be invoked from IoC Container and will call two methods of Controller. Then the call will flow to Service layer Bean’s to get the list of videos based on language.

Interface

Create an Interface under “net.geekcoders.service” package and copy below code.

package net.geekcoders.service;

import java.util.List;

public interface VideoLister {
	List<String> moviesList();
	List<String> songsList();
}

Implementation Classes of Service Layer

EnglishVideoListerImpl

Create EnglishMovieListerImpl under the same package of Interface you created already.

package net.geekcoders.service;

import java.util.ArrayList;
import java.util.List;
import javax.inject.Named;

@Named("english")
public class EnglishVideoListerImpl implements VideoLister{

	@Override
	public List<String> moviesList() {
		// Business logic goes here
		System.out.println("Will pull all the movies of English language and return it");
		return new ArrayList<String>();
	}

	@Override
	public List<String> songsList() {
		// Business logic goes here
		System.out.println("Will pull all the songs of English language and return it");
		return new ArrayList<String>();
	}

}

You can see in this coding snippet I have used @Named instead of @Service(Stereotype annotation)

SpanishMovieListerImpl

Create SpanishMovieListerImpl under the same package of Interface you created already.

package net.geekcoders.service;

import java.util.ArrayList;
import java.util.List;
import javax.inject.Named;

@Named("spanish")
public class SpanishMovieListerImpl implements VideoLister {

	@Override
	public List<String> moviesList() {
		// Business logic goes here
		System.out.println("Will pull all the movies of Spanish language and return it");
		return new ArrayList<String>();
	}

	@Override
	public List<String> songsList() {
		// Business logic goes here
		System.out.println("Will pull all the movies of Spanish language and return it");
		return new ArrayList<String>();
	}

}

Controller

This is the main part of the application, where we are going to use both the annotations of JSR 330 Standard provided.

Create VideoController Bean under “net.geekcoders.controller” package and copy below code.

package net.geekcoders.controller;

import javax.inject.Inject;
import javax.inject.Named;
import org.springframework.lang.Nullable;
import net.geekcoders.service.VideoLister;

@Named
public class VideoController {
	@Inject
	@Named("english")
	private VideoLister englishVideos;
	@Inject
	@Named("spanish")
	@Nullable
	private VideoLister spanishVideos;
	
	public void getAllEnglishMovies() {
		System.out.println("VideoController :: getAllEnglishMovies");
		this.getEnglishVideos().moviesList();
	}
	
	public void getAllSpanishMovies() {
		System.out.println("VideoController :: getAllSpanishMovies");
		this.getSpanishVideos().moviesList();
	}
	
	public VideoLister getEnglishVideos() {
		return englishVideos;
	}
	public void setEnglishVideos(VideoLister englishVideos) {
		this.englishVideos = englishVideos;
	}
	public VideoLister getSpanishVideos() {
		return spanishVideos;
	}
	public void setSpanishVideos(VideoLister spanishVideos) {
		this.spanishVideos = spanishVideos;
	}
}
  • Look at the highlighted code, I have used @Inject to inject the dependencies in Identifiers.
  • @Named to resolve the required dependencies based on the value provided.
  • @Nullable is provided because it is an Optional dependency. If not found, IoC won’t throw an exception.

Configuration

To run the above application, we have to configure it. I’m using Java class with @Configuration annotation and @Component annotation to scan and assemble the bean’s

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import net.geekcoders.controller.VideoController;

@Configuration
@ComponentScan(basePackages = "net.geekcoders.*")
public class AppConfig {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
		applicationContext.register(AppConfig.class);
		applicationContext.refresh();
		
		VideoController controller = applicationContext.getBean(VideoController.class);
		controller.getAllEnglishMovies();// to get list of English movies
		controller.getAllSpanishMovies();// to get list of Spanish movies
	}

}

ComponentScan will scan for all the sub folders from geekcoders and assemble the Beans that are marked with the @Named annotation.

Now the final structure of the example application will look as below.

Now run the application from AppConfig.java class as a Java application. You can see the output logs printed in Console as below.

That’s all for now on Dependency Injection using @Inject and @Named annotation in Spring and Spring Boot…

Happy Reading!!!

One reply on “Dependency Injection using @Inject and @Named Annotations”

Leave a Reply

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