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


相关文章
|
10天前
|
XML Java 数据格式
SpringBoot入门(8) - 开发中还有哪些常用注解
SpringBoot入门(8) - 开发中还有哪些常用注解
28 0
|
17天前
|
XML JSON Java
SpringBoot必须掌握的常用注解!
SpringBoot必须掌握的常用注解!
41 4
SpringBoot必须掌握的常用注解!
|
19天前
|
存储 缓存 Java
Spring缓存注解【@Cacheable、@CachePut、@CacheEvict、@Caching、@CacheConfig】使用及注意事项
Spring缓存注解【@Cacheable、@CachePut、@CacheEvict、@Caching、@CacheConfig】使用及注意事项
58 2
|
19天前
|
JSON Java 数据库
SpringBoot项目使用AOP及自定义注解保存操作日志
SpringBoot项目使用AOP及自定义注解保存操作日志
34 1
|
14天前
|
存储 安全 Java
springboot当中ConfigurationProperties注解作用跟数据库存入有啥区别
`@ConfigurationProperties`注解和数据库存储配置信息各有优劣,适用于不同的应用场景。`@ConfigurationProperties`提供了类型安全和模块化的配置管理方式,适合静态和简单配置。而数据库存储配置信息提供了动态更新和集中管理的能力,适合需要频繁变化和集中管理的配置需求。在实际项目中,可以根据具体需求选择合适的配置管理方式,或者结合使用这两种方式,实现灵活高效的配置管理。
10 0
|
6月前
|
Java API Spring
Spring容器如何使用一个注解来指定一个类型为配置类型
Spring容器如何使用一个注解来指定一个类型为配置类型
52 0
|
1月前
|
XML Java 数据格式
手动开发-简单的Spring基于注解配置的程序--源码解析
手动开发-简单的Spring基于注解配置的程序--源码解析
46 0
|
5月前
|
XML Java 数据格式
Spring5系列学习文章分享---第三篇(AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式))
Spring5系列学习文章分享---第三篇(AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式))
51 0
|
5月前
|
Java Spring
spring基于注解配置数据源
spring基于注解配置数据源
|
XML Java 数据格式
spring ioc中的一些常用annotation注解配置
spring ioc中的一些常用annotation注解配置