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 Annotation | JSR 330 Annotation | Limitations of JSR 330 Annotation |
---|---|---|
@Autowired | @Inject | No 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”) | @Singleton | If 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 | @Named | Instead of using Qualifiers, can use @Named to resolve named dependencies. |
@Value | – | No equivalent |
@Required(Deprecated) | – | No equivalent |
@Lazy | – | No Equivalent |
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”
I like this site because so much useful stuff on here : D. Marybelle Andris Barta