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名称默认和类名相同。
例如:

  1. @Named public class Person
    该bean的名称就是person。
  2. @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一起使用

posted on 2020-03-02 14:37  疯狂的小萝卜头  阅读(566)  评论(0编辑  收藏  举报