Spring中的Autowired、Qualifier、Resource注解详解

简介: 使用Spring系列的框架对这三个注解肯定都不会陌生,这三个注解有一个特性,就是用于属性注入,说白了点就是将Spring容器中的对象取出来,这样我们才可以使用,那么这三者到底是什么关系,又有什么区别呢?

前言:

使用Spring系列的框架对这三个注解肯定都不会陌生,这三个注解有一个特性,就是用于属性注入,说白了点就是将Spring容器中的对象取出来,这样我们才可以使用,那么这三者到底是什么关系,又有什么区别呢?


一.三个注解



若是不想深入了解,看这一段就够了:其实我们可以简单的这么看Autowired+Qualifier=Resource,这就是他们三者的关系,Autowired根据类型找实现类,一个接口有多个实现类时需要通过Qualifier来指明需要哪个实现类,这是就需要Autowired+Qualifier一起使用才可以。Resource则是不声明名称时按照类型查找效果与Autowired相同,声明名称时就等于Autowired+Qualifier的组合。下面我们就来详细的看一下这三个注解。


1.Autowired注解


相信大部分人在属性注入时使用的都是Autowired或者Resource注解,那么Autowired是怎么进行属性注入的呢?其实Autowired是根据接口的类型进行注入的,有如下代码

  @Autowired
    SupplierService supplierService;
    @RequestMapping("test")
    public void test(){
        supplierService.deleteByOid("2");
    }


我们使用Autowired注解后,Spring就会自动去容器中寻找SupplierService的实现类,进行注入进来。


1.问题一:怎么将对象的实例放入到Spring容器中呢?


自然就是我们常用的compoment、controller、service、repository这些注解了,这些注解都可以将类的实例放入到Spring容器中,且默认都是单利模式。然后我们可以使用Autowired进行依赖注入。


2.问题二:如果依赖注入的接口有多个实现类呢?


我们已经知道Autowired是根据接口的类型自动找到其实现类然后实现依赖注入,那么如果接口有多个实现类该怎么办?依赖注入的又是谁呢,这时就要说到Qualifier注解了。


2.Qualifier注解


上面已经说了,当一个接口有多个实现类时,Spring容器按照类型注入就会有一定问题,注入的可能就不是我们想要的类型了。比如下方代码:

//这是接口
public interface SupplierService {
    void deleteByOid(String oid);
}
//这是第一个实现类
@Service
public class SupplierServiceImplOne implements SupplierService{
    @Override
    public void deleteByOid(String oid) {
        System.out.println("One...我被执行了");
    }
}
//这是第二个实现类
@Service
public class SupplierServiceImplTwo implements SupplierService{
    @Override
    public void deleteByOid(String oid) {
        System.out.println("Two...我被执行了");
    }
}


一个接口有两个实现类,如果我们还是这么写(如下),那到底注入的是哪个呢?

@Controller
public class Test {
    @Autowired
    SupplierService supplierService;
    @RequestMapping("test")
    public void test(){
        supplierService.deleteByOid("2");
    }
}


事实上Spring在之前的版本中运行以上代码,不指定具体的实现类是会报错,具体哪个版本修改了不得而知,现在是有个默认模式会去执行其中一个实现类。那么如果执行的不是我们想要的实现类怎么办呢?就需要Qualifier注解了,该注解可以实现根据实现类的名称进行注入。如下:

@Controller
public class Test {
    @Autowired
    @Qualifier("supplierServiceImplTwo")
    SupplierService supplierService;
    @RequestMapping("test")
    public void test(){
        supplierService.deleteByOid("2");
    }
}


这样我们就可以在多个实现类的情况下实现准确注入了。

注意:Qualifier注解的值是小写字母开头的接口实现类的名称。这个是接口实现类的默认名称,我们可以使用@Service(“supplierService”)时显示的指定实现类的名称,然后使用Qualifier注解时进行使用,如果不指定,默认的就是接口实现类的小写字母开头的类名,就像上方代码那样。


1.问题一:只使用Qualifier可以吗?


答案是不可以的,使用Qualifier是在使用Autowired的基础上才有意义的。如果只使用Qualifier,那么Spring是不清楚你要注入什么类型的,Autowired告诉Spring我要什么类型,Qualifier告诉Spring我要这个名称的实现类,他俩配合完成了一次属性注入。


2.问题二:一个属性注入就需要两个注解,是不是太麻烦?


都说世界是懒人推动的。。。,懒人就问了,我一个属性注入就要两个注解?也太麻烦了,所以又有一个Resource注解来取代在多实现类的场景下必须多个注解才可完成的工作(不过Resource并不是Spring的注解)。


3.Resource注解


上面已经说了Resource等于Autowired+Qualifier注解,如果我们不给Resource指定name属性时,那么Resource是按照类型注入的,此时如果接口有多个实现类,就会报错,笔者记得之前一个接口多个实现类使用Autowired也是报这个错,如下

nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException


但是不知何时Spring修复了这一点,所以也就是说,使用Resource不声明name属性时其和Autowired是一样的效果都是按照类型进行注入,但是如果一个接口有多个实现类使用Resource是编译是过不去,但是使用Autowired还是可以编译过去。如果使用Resource并声明他的name属性那么就可以正常编译了,这个效果就等同于Autowired加Qualifier了。如下:

//    @Autowired
//    @Qualifier("supplierServiceImplTwo")
    @Resource(name ="supplierServiceImplTwo")


如上所示,注释掉的部分与Resource是相同的作用,所以我们说Resource就是为了取代Autowired与Qualifier的,加上名称后,就会根据名称去Spring容器中获取对象。这个名称前面也说了,并不是类名,如果在往Spring容器中注入对象时不显示声明,默认就是注入对象所属类的小写字母开头的类名。


二.总结



知道了这三个注解的区别,那么我们应该怎么用更合理,更不容易出错呢,在一个接口仅有一个实现类的场景中,我们使用Autowired和Resource其实效果一致,在一个接口多个实现类的场景。这时我们使用Resource更简便快捷,仅需要为Resource指明name属性即可准确进行属性注入了,以上就是关于Aotowired、Qualifier、Resource三个注解的总结了,总结是为了让自己记忆更清楚,如果能帮到路过的你就更好了。


相关文章
|
15天前
|
Java Spring
【Spring】方法注解@Bean,配置类扫描路径
@Bean方法注解,如何在同一个类下面定义多个Bean对象,配置扫描路径
144 73
|
10天前
|
Java Spring 容器
【SpringFramework】Spring IoC-基于注解的实现
本文主要记录基于Spring注解实现IoC容器和DI相关知识。
45 21
|
15天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
15天前
|
Java Spring
【Spring配置】idea编码格式导致注解汉字无法保存
问题一:对于同一个项目,我们在使用idea的过程中,使用汉字注解完后,再打开该项目,汉字变成乱码问题二:本来a项目中,汉字注解调试好了,没有乱码了,但是创建出来的新的项目,写的注解又成乱码了。
|
2月前
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
157 2
|
8月前
|
Java API Spring
Spring容器如何使用一个注解来指定一个类型为配置类型
Spring容器如何使用一个注解来指定一个类型为配置类型
64 0
|
3月前
|
XML Java 数据格式
手动开发-简单的Spring基于注解配置的程序--源码解析
手动开发-简单的Spring基于注解配置的程序--源码解析
57 0
|
7月前
|
XML Java 数据格式
Spring5系列学习文章分享---第三篇(AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式))
Spring5系列学习文章分享---第三篇(AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式))
67 0
|
7月前
|
Java Spring
spring基于注解配置数据源
spring基于注解配置数据源
|
XML Java 数据格式
spring ioc中的一些常用annotation注解配置
spring ioc中的一些常用annotation注解配置