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三个注解的总结了,总结是为了让自己记忆更清楚,如果能帮到路过的你就更好了。


相关文章
|
7月前
|
缓存 监控 Java
SpringBoot @Scheduled 注解详解
使用`@Scheduled`注解实现方法周期性执行,支持固定间隔、延迟或Cron表达式触发,基于Spring Task,适用于日志清理、数据同步等定时任务场景。需启用`@EnableScheduling`,注意线程阻塞与分布式重复问题,推荐结合`@Async`异步处理,提升任务调度效率。
1095 128
|
6月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
676 2
|
7月前
|
XML Java 数据格式
常用SpringBoot注解汇总与用法说明
这些注解的使用和组合是Spring Boot快速开发和微服务实现的基础,通过它们,可以有效地指导Spring容器进行类发现、自动装配、配置、代理和管理等核心功能。开发者应当根据项目实际需求,运用这些注解来优化代码结构和服务逻辑。
487 12
|
7月前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
376 0
探索Spring Boot的@Conditional注解的上下文配置
|
7月前
|
智能设计 Java 测试技术
Spring中最大化@Lazy注解,实现资源高效利用
本文深入探讨了 Spring 框架中的 `@Lazy` 注解,介绍了其在资源管理和性能优化中的作用。通过延迟初始化 Bean,`@Lazy` 可显著提升应用启动速度,合理利用系统资源,并增强对 Bean 生命周期的控制。文章还分析了 `@Lazy` 的工作机制、使用场景、最佳实践以及常见陷阱与解决方案,帮助开发者更高效地构建可扩展、高性能的 Spring 应用程序。
294 0
Spring中最大化@Lazy注解,实现资源高效利用
|
开发框架 Java Spring
Spring中@Autowired注解、@Resource注解的区别
转自:http://blog.csdn.net/gst6062825/article/details/8765157
213 0
|
9月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
1295 0
|
10月前
|
人工智能 Java 测试技术
Spring Boot 集成 JUnit 单元测试
本文介绍了在Spring Boot中使用JUnit 5进行单元测试的常用方法与技巧,包括添加依赖、编写测试类、使用@SpringBootTest参数、自动装配测试模块(如JSON、MVC、WebFlux、JDBC等),以及@MockBean和@SpyBean的应用。内容实用,适合Java开发者参考学习。
1105 0
|
6月前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
546 5

热门文章

最新文章

下一篇
开通oss服务