Spring Autowiring Using @Inject and @Named Annotations

In Spring Autowiring Using @Autowired Annotation we have already seen how container can automatically resolve collaboration among beans (bean dependencies) by annotating the dependencies with @Autowired annotation. As an alternative you can use @Inject annotation for autowiring in Spring.

@Inject and @Named annotations in Spring

Spring 3.0 added support for JSR-330 (Dependency Injection for Java) annotations contained in the javax.inject package such as @Inject and @Named.

  • @Inject is used for autorwiring, it gives you a chance to use standard annotations rather than Spring specific annotation like @Autowired.
  • @Named annotation is used for conflict resolution if there are multiple candidates of the same type.

To use these annotations javax.inject library is needed, Maven dependency for the same is as follows.

<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>

Using @Inject annotation

  • You can apply the @Inject annotation to constructors.
  • You can apply the @Inject annotation to setter methods.
  • You can apply @Inject to fields.

We’ll see examples of @Inject annotation using all the above options.

Using @Inject annotation on setter

@Inject annotation on a setter method is equivalent to autowiring=”byType” in autowiring using configuration file.

In the example there is a class to place order called OrderService and purchase can be done from a Store. In OrderService class dependency for store has to be autowired.

public interface OrderService {
	public void buyItems();
}
import javax.inject.Inject;
import org.springframework.stereotype.Service;

@Service
public class OrderServiceImpl implements OrderService {
	private IStore store;
	// Autowiring on Setter
	@Inject
	public void setStore(IStore store) {
		this.store = store;
	}
	public void buyItems() {
		store.doPurchase();
	}
}

In the class Autowiring on the setter method is done using @Inject annotation.

public interface IStore {
	public void doPurchase();
}
import org.springframework.stereotype.Service;

@Service
public class RetailStore implements IStore {
	public void doPurchase() {
		System.out.println("Doing purchase from Retail Store");
	}
}

Configuration

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context.xsd">
	<context:component-scan base-package="com.knpcode.springproject.service" />
</beans>

Since JSR-330 standard annotations are scanned in the same way as the Spring annotations so component-scan is able to scan @Inject and @Named annotations too.

You can use the following class with main method to read the configuration and call the bean method.

public class App {
    public static void main( String[] args ){
       	// create context using configuration
    	ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml");
        OrderService order =  context.getBean(OrderServiceImpl.class);
        order.buyItems();
        // close the context
        context.close();
    }
}

Output

17:34:09.769 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'orderServiceImpl'
17:34:09.806 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'retailStore'
Doing purchase from Retail Store

Using @Inject annotation on constructor

@Inject annotation on a bean’s constructor is equivalent to autowiring=”constructor” when autowiring using configuration file.

@Service
public class OrderServiceImpl implements OrderService {
  private IStore store;
  // Autowiring on constructor
  @Inject
  public OrderServiceImpl(IStore store){
    this.store = store;
  }
  public void buyItems() {
    store.doPurchase();
  }
}

Using @Inject annotation on field

@Inject annotation on a field is equivalent to autowiring=”byType” in autowiring using configuration file.

@Service
public class OrderServiceImpl implements OrderService {
  // Autowiring on a field
  @Inject
  private IStore store;

  public void buyItems() {
    store.doPurchase();
  }
}

@Inject annotation with java.util.Optional or @Nullable

@Inject can also be used with java.util.Optional or @Nullable. Since @Inject does not have a required attribute so the scenario where dependency can not be satisfied under some circumstances has to be taken care of by using either Optional or @Nullable otherwise UnsatisfiedDependencyException will be thrown at the time of bean creation itself.

For example using @Nullable annotation to declare that annotated elements can be null under some circumstance.

@Service
public class OrderServiceImpl implements OrderService {
	private IStore store;
	// Autowiring on Setter
	@Inject
	public void setStore(@Nullable IStore store) {
		this.store = store;
	}
	public void buyItems() {
		store.doPurchase();
	}
}

By using @Nullable bean initialization will be done but later Null pointer excpetion is thrown if the required dependency is not found.

Using Optional to declare that annotated elements can be null under some circumstance.

@Service
public class OrderServiceImpl implements OrderService {
	private IStore store;
	// Autowiring on Setter
	@Inject
	public void setStore(Optional<IStore> store) {
		if(store.isPresent())
			this.store = store.get();
	}
	public void buyItems() {
		store.doPurchase();
	}
}

Conflict resolution using @Named with @Inject

Using @Named annotation you can use a qualified name for the dependency that should be injected.

When autowiring by type there may be multiple candidates of the same type in such scenario Spring container won’t be able to decide which bean to autowire and throw NoUniqueBeanDefinitionException.

For example if there two stores RetailStore and OnlineStore of type IStore.

@Service
public class OnlineStore implements IStore {
	public void doPurchase() {
		System.out.println("Doing purchase from Online Store");
	}
}

Then our example will fail as it won’t be able to determine which store to autowire.

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'orderServiceImpl': 
Unsatisfied dependency expressed through method 'setStore' parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
No qualifying bean of type 'com.knpcode.springproject.service.IStore' available: 
expected single matching bean but found 2: onlineStore,retailStore

Using @Named annotation for conflict resolution in such scenario by qualifying a bean for autowiring.

@Service
public class OrderServiceImpl implements OrderService {
	private IStore store;
	@Inject
	@Named("retailStore")
	public void setStore(IStore store) {
		this.store = store;
	}
	public void buyItems() {
		store.doPurchase();
	}
}

In the class qualified name is used for the dependency that should be injected using @Named annotation

Related Posts

That’s all for the topic Spring Autowiring Using @Inject and @Named Annotations. If something is missing or you have something to share about the topic please write a comment.


You may also like

  • Difference Between CountDownLatch And CyclicBarrier in Java
  • HashSet Vs LinkedHashSet Vs TreeSet in Java
  • Variables in Java
  • GZIP Multiple Files in Java Creating Tar Archive
  • Exception Propagation in Java
  • Data Compression in Hadoop Framework

    One Comment

    1. Himanshu khurana

      you are awesome.keep helping the way you are helping others abhi

    Leave a Reply

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

    This site uses Akismet to reduce spam. Learn how your comment data is processed.