annotation之@Autowired、@Inject、@Resource三者区别和示例
@Autowired注解
1、@Autowired是spring自带的注解,通过‘AutowiredAnnotationBeanPostProcessor’ 类实现的依赖注入;
2、@Autowired是根据类型进行自动装配的,如果需要按名称进行装配,则需要配合@Qualifier;
3、@Autowired有个属性为required,可以配置为false,如果配置为false之后,当没有找到相应bean的时候,系统不会抛错;
4、@Autowired可以作用在变量、setter方法、构造函数上。
@Autowired配合@Qualifier使用
@Qualifier
:限定描述符,用于细粒度选择候选者
@Autowired
默认是根据类型
进行注入的,因此如果有多个类型一样的Bean候选者,则需要限定其中一个候选者,否则将抛出异常。
@Qualifier
限定描述符除了能根据名字
进行注入,更能进行更细粒度的控制如何选择候选者
根据基于XML配置中的<qualifier>
标签指定的名字进行注入,使用如下方式指定名称:
其中type
属性可选,指定类型,默认就是Qualifier
注解类name
就是给Bean
候选者指定限定标识符
<bean id="springQualifierTestService1" class="xx.SpringQualifierTestServiceImpl1">
<qualifier type="org.springframework.beans.factory.annotation.Qualifier" value="springQualifierTestService1"/>
</bean>
一个Bean
定义中只允许指定类型不同的<qualifier>
,如果有多个相同type
后面指定的将覆盖前面的
-
缺省的根据Bean名字注入:
是在Bean上没有指定
<qualifier>
标签时一种容错机制,即缺省情况下使用Bean标识符注入
(下文的使用举例即是在Bean缺少@qualifier标签,通过容错机制使用Bean标识)
,
但如果你指定了标签将不会发生容错。
使用举例一(缺少容错根据Bean名字注入):
SpringQualifierTestService.java
public interface SpringQualifierTestService {
public String getId();
}
SpringQualifierTestServiceImpl1.java
import java.util.UUID;
import org.springframework.stereotype.Service;
@Service("springQualifierTestService1")
public class SpringQualifierTestServiceImpl1 implements SpringQualifierTestService {
private String uuid;
public SpringQualifierTestServiceImpl1() {
uuid = UUID.randomUUID().toString();
System.out.println("SpringQualifierTestServiceImpl1实例化"+uuid);
}
@Override
public String getId() {
// TODO Auto-generated method stub
return uuid;
}
}
SpringQualifierTestServiceImpl2.java
import java.util.UUID;
import org.springframework.stereotype.Service;
@Service("springQualifierTestService2")
public class SpringQualifierTestServiceImpl2 implements SpringQualifierTestService {
private String uuid;
public SpringQualifierTestServiceImpl2() {
uuid = UUID.randomUUID().toString();
System.out.println("SpringQualifierTestServiceImpl2实例化" + uuid);
}
@Override
public String getId() {
// TODO Auto-generated method stub
return uuid;
}
}
SpringQualifierTestController.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class SpringQualifierTestController {
@Autowired
@Qualifier("springQualifierTestService1")
SpringQualifierTestService springQualifierTestService;
@RequestMapping(value = "spring/qualifier/test", method = RequestMethod.GET)
public void testScopeSession() {
System.out.println(springQualifierTestService.getId());
}
}
使用举例二(扩展@Qualifier限定描述符注解):
QualifierService1.java
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
@Target(value = { ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE })
public @interface QualifierService1 {
}
QualifierService2.java
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
@Target(value = { ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE })
public @interface QualifierService2 {
}
SpringQualifierTestServiceImpl1.java
import java.util.UUID;
import org.springframework.stereotype.Service;
@Service
@QualifierService1
public class SpringQualifierTestServiceImpl1 implements SpringQualifierTestService {
private String uuid;
public SpringQualifierTestServiceImpl1() {
uuid = UUID.randomUUID().toString();
System.out.println("SpringQualifierTestServiceImpl1实例化"+uuid);
}
@Override
public String getId() {
// TODO Auto-generated method stub
return uuid;
}
}
SpringQualifierTestServiceImpl2.java
import java.util.UUID;
import org.springframework.stereotype.Service;
@Service
@QualifierService2
public class SpringQualifierTestServiceImpl2 implements SpringQualifierTestService {
private String uuid;
public SpringQualifierTestServiceImpl2() {
uuid = UUID.randomUUID().toString();
System.out.println("SpringQualifierTestServiceImpl2实例化" + uuid);
}
@Override
public String getId() {
// TODO Auto-generated method stub
return uuid;
}
}
SpringQualifierTestController.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class SpringQualifierTestController {
@Autowired
@QualifierService2
SpringQualifierTestService springQualifierTestService;
@RequestMapping(value = "spring/qualifier/test", method = RequestMethod.GET)
public void testScopeSession() {
System.out.println(springQualifierTestService.getId());
}
}
@Inject注解
1、@Injec
t是JSR330 (Dependency Injection for Java)中的规范,需要导入javax.inject.Inject;实现注入。
2、@Inject是根据类型
进行自动装配的,如果需要按名称进行装配,则需要配合@Named
;
3、@Inject可以作用在变量、setter方法、构造函数上
。
@Named
@Named
和Spring的@Component
功能相同。@Named
可以有值,如果没有值生成的Bean名称默认和类名相同。
例如:
@Named public class Person
该bean的名称就是person。@Named(“p”) public class Person
该bean的名称就是p。
@Inject配合@Qualifier使用
任何人都可以定义一个新的修饰语,一个qualifier注解应该满足如下条件:
● 定义的注解类有@Qualifier,@Retention(RUNTIME)和@Documented。
● 可以有属性
● 可以是公共API的一部分
● 可以用@Target注解限定使用范围
下面是Qualifier的例子:
pom.xml
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
Genre.java
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
@Target(value = { ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE })
public @interface Genre {
QualifierService qualifierService() default QualifierService.QUALIFIERSERVICE1;
public enum QualifierService {
QUALIFIERSERVICE1, QUALIFIERSERVICE2
}
}
QualifierTestService.java
public interface QualifierTestService {
public String getId();
}
QualifierTestServiceImpl1.java
import java.util.UUID;
import javax.inject.Named;
@Named
@Genre(qualifierService = QualifierService.QUALIFIERSERVICE1)
public class QualifierTestServiceImpl1 implements QualifierTestService {
private String uuid;
public QualifierTestServiceImpl1() {
uuid = UUID.randomUUID().toString();
System.out.println("QualifierTestServiceImpl1实例化" + uuid);
}
@Override
public String getId() {
// TODO Auto-generated method stub
return uuid;
}
}
QualifierTestServiceImpl2.java
import java.util.UUID;
import javax.inject.Named;
@Named
@Genre(qualifierService = QualifierService.QUALIFIERSERVICE2)
public class QualifierTestServiceImpl2 implements QualifierTestService {
private String uuid;
public QualifierTestServiceImpl2() {
uuid = UUID.randomUUID().toString();
System.out.println("QualifierTestServiceImpl2实例化" + uuid);
}
@Override
public String getId() {
// TODO Auto-generated method stub
return uuid;
}
}
QualifierTestController.java
import javax.inject.Inject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.gm.test16.Genre.QualifierService;
@Controller
public class QualifierTestController {
/*对QualifierTestService类的注入,如果对QualifierTestService类注入应该是:@Genre(qualifierService = QualifierService.QUALIFIERSERVICE1)或@Genre,因为@Genre默认的是QUALIFIERSERVICE1*/
@Inject
@Genre(qualifierService = QualifierService.QUALIFIERSERVICE2)
QualifierTestService qualifierTestService;
@RequestMapping(value = "qualifier/test", method = RequestMethod.GET)
public void testScopeSession() {
System.out.println(qualifierTestService.getId());
}
}
可参照上文的《使用举例二(扩展@Qualifier限定描述符注解)》进行扩展测试。
@Resource
1、@Resource是JSR250规范的实现,需要导入javax.annotation实现注入。
2、@Resource是根据名称
进行自动装配的,一般会指定一个name属性
3、@Resource可以作用在变量、setter方法上
。
总结:
1、@Autowired是spring自带的,@Inject是JSR330规范实现的,@Resource是JSR250规范实现的,需要导入不同的包
2、@Autowired、@Inject用法基本一样,不同的是@Autowired有一个request属性
3、@Autowired、@Inject是默认按照类型匹配的,@Resource是按照名称匹配的
4、@Autowired如果需要按照名称匹配需要和@Qualifier一起使用,@Inject和@Named一起使用