使用@Inject和@Named注释进行Spring自动装配
在使用@Autowired注释的Spring自动装配中,我们已经看到了容器如何通过使用@Autowired注释对依赖项进行注释来自动解决bean之间的协作(bean依赖项)。或者,我们可以使用@Inject注释在Spring中自动布线。
Spring中的@Inject和@Named注释
Spring 3.0增加了对javax.inject包中包含的JSR-330(Java依赖注入)注释的支持,例如@Inject和@Named。
@Inject用于自动布线,它使我们有机会使用标准注释,而不是像@Autowired这样的Spring特定注释。
如果有多个相同类型的候选者,则@Named注释用于解决冲突。
要使用这些注释,需要javax.inject库,对于Maven的依赖关系如下。
<dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency>
使用@Inject注释
我们可以将@Inject注释应用于构造函数。
我们可以将@Inject注释应用于setter方法。
我们可以将@Inject应用于字段。
我们将使用上述所有选项查看@Inject注释的示例。
在setter上使用@Inject注释
使用配置文件进行自动装配时,setter方法上的@Inject注释等效于autowiring =" byType"。
在该示例中,有一个用于下订单的类称为OrderService,可以从商店进行购买。在OrderService类中,必须自动关联商店的依赖关系。
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();
}
}
在类中,使用@Inject注释对setter方法进行自动装配。
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");
}
}
组态
<?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.theitroad.springproject.service" />
</beans>
由于以与Spring注释相同的方式扫描JSR-330标准注释,因此组件扫描也可以扫描@Inject和@Named注释。
我们可以将以下类与main方法一起使用以读取配置并调用bean方法。
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();
}
}
输出:
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
在构造函数上使用@Inject注释
使用配置文件自动装配时,bean的构造函数上的@Inject注释等效于autowiring =" constructor"。
@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();
}
}
在字段上使用@Inject注释
使用配置文件进行自动装配时,@ Inject字段上的注释等效于autowiring =" byType"。
@Service
public class OrderServiceImpl implements OrderService {
// Autowiring on a field
@Inject
private IStore store;
public void buyItems() {
store.doPurchase();
}
}
@Inject注释与java.util.Optional或者@Nullable
@Inject也可以与java.util.Optional或者@Nullable一起使用。由于@Inject没有必需的属性,因此在某些情况下不能满足依赖关系的情况必须通过使用Optional或者@Nullable来解决,否则在创建bean时会抛出UnsatisfiedDependencyException。
例如,使用@Nullable注解声明被注解的元素在某些情况下可以为null。
@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();
}
}
通过使用@Nullable bean,将完成初始化,但是如果找不到所需的依赖项,则稍后将抛出Null指针专有内容。
使用Optional声明在某些情况下带注释的元素可以为null。
@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();
}
}
使用@Named和@Inject解决冲突
使用@Named注释,可以为应注入的依赖项使用限定名称。
当按类型自动装配时,在这种情况下,Spring容器将无法确定要自动装配哪个bean并抛出NoUniqueBeanDefinitionException。
例如,如果有两个商店的IStore类型为RetailStore和OnlineStore。
@Service
public class OnlineStore implements IStore {
public void doPurchase() {
System.out.println("Doing purchase from Online Store");
}
}
然后,我们的示例将失败,因为它无法确定要自动关联的商店。
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.theitroad.springproject.service.IStore' available: expected single matching bean but found 2: onlineStore,retailStore
在这种情况下,可以使用@Named注释来解决冲突,方法是使Bean具有自动装配资格。
@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();
}
}
在类中,合格名称用于应使用@Named注释注入的依赖项

