@Resource
@Resource并不是Spring中自带的注解,而是JSR-250中的注解,属于Java EE的范畴,它具有三种注入的模式
- Match by Name(按变量名注入)
- Match by Type(按类型注入)
- Match by Qualifier(使用Qualifier显式注入)
这些注入方式都支持通过setter方法注入或者是通过属性的方式注入。
通过属性注入
首先建立一个名为MyClass的测试类,类代码如下
public class MyClass {
String s;
public MyClass() {
}
public MyClass(String s) {
this.s = s;
}
}
Match by Name
首先声明一个bean,并设置其name
@Configuration
public class ApplicationContextTestResourceNameType {
@Bean(name="namedBean")
public MyClass namedBean() {
return new MyClass();
}
}
接着对另外一个bean中的String属性使用@Resource进行注入
@Resource(name="namedBean")
private MyClass defaultBean;
这样defaultBean在进行bean的初始化时就会被注入为一个MyClass的值。
Match by Type
接上面的测试样例,bean的配置相同,将注入的部分改为下面的形式,删去括号中的部分
@Resource
private MyClass defaultBean;
经过bean的初始化,会发现defaultBean仍然是有值的,因为当删去括号中的name属性后,Spring框架在初始化的过程中发现无法使用Match by Name,就会转而使用Match by Type,在bean容器中寻找类型为MyClass的bean来进行注入。
Match by Qualifier
为了测试显示注入,我们首先将上面的配置类改为如下形式,在bean容器中添加两个同样类型的bean
@Configuration
public class ApplicationContextTestResourceNameType {
@Bean(name="firstNamedBean")
public MyClass namedBean() {
return new MyClass("firstNamedBean");
}
@Bean(name="SecondNamedBean")
public MyClass namedBean() {
return new MyClass("SecondNamedBean");
}
}
接着对另一个bean的属性进行显示注入
@Resource
@Qualifier("firstNamedBean")
private MyClass firstNamedBean;
@Resource
@Qualifier("SecondNamedBean")
private MyClass SecondNamedBean;
当我们对这两个属性进行访问的时候就会发现firstNamedBean中的s属性值为"firstNamedBean",而SecondNamedBean中的s属性的值为"SecondNamedBean"。而如果我们不使用@Qualifier注解,则在Spring初始化的时候会报出org.springframework.beans.factory.NoUniqueBeanDefinitionException的异常,因为在Spring容器中有两个类型为MyClass的bean,无法使用Match by Type自动注入。
通过setter方法注入
通过setter方法注入的形式和通过属性注入是相同的,只是注入的位置不一样。
@Resource(name="namedBean")
public void setMyClass(MyClass myClass) {
this.myClass = myClass;
}
@Resource
public void setMyClass(MyClass myClass) {
this.myClass = myClass;
}
@Resource
@Qualifier(name="namedBean")
public void setMyClass(MyClass myClass) {
this.myClass = myClass;
}
@Inject
@Inject同样不是Spring自带的注解,它是属于JSP-330的,同样有三种注入方式
- Match by Name
- Match by Type
- Match by Qualifier
同样,也可以使用属性注入或者是setter方法注入
想要使用@Inject注解,需要在maven中引入相关依赖
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
对于@Inject注解,在Match by Type和Match by Qualifier的使用上和@Resource是完全一致的,只需要把@Resource注解替换为@Inject即可,下面主要说明以下Match by Name的情况
Match by Name
首先在配置类中定义相应的bean
@Configuration
public class ApplicationContextTestResourceNameType {
@Bean(name="namedBean")
public MyClass namedBean() {
return new MyClass();
}
}
接着对属性进行注入
@Inject
@Named("namedBean")
private MyClass MyClass;
可以看到这里和@Resource有很大的区别,@Inject这个注解自身是不带有name属性的,需要另外使用一个@Named注解来告诉Spring框架使用什么名字对属性进行注入。
@Autowired
@Autowired注解和@Inject的表现很相似,只是@Autowired是由Spring框架自身提供的,同样是支持以下三种注入方式
- Match by Type
- Match by Qualifier
- Match by Name
注入的方式也是支持属性注入和setter方法注入两种形式。
用属性方式注入
Match by Type
首先在配置类中声明一个用于注入的bean
@Configuration
public class ApplicationContextTestAutowiredQualifier {
@Bean
public MyClass autowiredMyClass() {
return new MyClass();
}
}
接着使用这个bean对另一个bean的属性进行注入
@Autowired
private MyClass MyClazz;
Spring容器在初始化的过程中遇到@Autowired就会从容器中寻找相应类型的bean来对属性进行注入,前提是容器中只有一个类型为MyClass的bean,否则在不进行任何其他指定的情况下会抛出NoUniqueBeanDefinitionException。
Match by Qualifier
@Autowired中使用@Qualifier的方式与其他两种注解相同
@Autowired
@Qualifier("autowiredFieldDependency")
private FieldDependency fieldDependency1;
Match by Name
首先声明一个bean,并为其指定它在bean容器中的名字
@Component(value="autowiredMyClass")
public class MyClass {
}
接着使用这个类型为MyClass的bean对另一个bean的属性进行注入
@Autowired
private MyClass autowiredMyClass;
这里是@Autowired与另外两种注入方式不同的地方,其他两种方式通过变量名进行注入的时候无论是声明bean的地方还是注入属性的地方都需要显示写出bean的name以此来进行匹配,但是对于@Autowired来说,只需要在声明bean的地方写上bean的名字即可,在进行注入的时候容器会自动将要注入的属性的变量名与容器中bean的名字进行匹配。
使用setter方式注入
使用setter方式注入与使用属性方式注入大体相同,只是注入的位置是在setter方法上,可以参见上文@Resource的注入形式