ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

@Autowired 与@Resource的异同点

2021-12-24 13:02:12  阅读:304  来源: 互联网

标签:Resource name Autowired 异同 laymanService bean LaymanService public


前言

最近写代码的时候,碰到一个小问题;
在这里插入图片描述
可以看到,Spring Boot不推荐使用@Autowired的方式进行属性注入。

我之前一直这样写,从来没觉得这有什么问题,看到这个报错,心里咯噔一下,然后忽然想,@Autowired 与@Resource有什么不同。

然后我发现,我竟然完全不记得了。

因此,写这篇笔记记录一下。

先解释一下,为什么Spring Boot不推荐使用@Autowired的方式进行属性注入。

  • @Autowired是spring定义的注解,与Spring框架强耦合,换成别的框架,可能不支持。
  • @Resource是JSR-250定义的注解,是Java标准,支持几乎所有java框架。

换言之,@Autowired能用的,@Resource也能用,@Autowired不能用的,@Resource还能用。

不过现在java程序员几乎等同于Spring程序员,说这个,似乎没有必要。

简单举例

LaymanController.java

@Controller
public class LaymanController {
    
    @Autowired
    public LaymanService laymanService;

    @GetMapping(value = "/sayHello")
    public void sayHello() {
         laymanService.sayHello();
    }
}

LaymanService

public interface LaymanService {
    void sayHello();
}

LaymanServiceImpl

@Service
public class LaymanServiceImpl implements LaymanService{
	public void sayHello(){
		System.out.println("你好,我是layman"); 
	}		
}

@Autowired

@Autowired默认按类型注入,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false。

public @interface Autowired {
	# 注册时该类型必须存在,如果不存在则报错。
	boolean required() default true;
}

如果注入的类型有可能为null,可以这样配置:@Autowired(required = false)

言归正传,还是说下,下面这个例子的加载顺序:

	@Autowired
    public LaymanService laymanService;

项目启动后,由于我们在LaymanServiceImpl 上配置了@Service注解,那么它会被CompentScan扫描进容器内,注册为bean。

由于未指定name属性,使用默认值(类名首字母转小写)为bean命名(laymanServiceImpl

@Autowired查找类型为LaymanService 的bean,如果找不到,则找名称为laymanService的bean。

很明显,有类型为LaymanService 的bean,名为laymanServiceImpl(多态),注入成功!

在这里插入图片描述

做个小改动,让它报个错

此时我们再添加一个类,叫做LaymanServiceImpl2

LaymanServiceImpl2.java

@Service
public class LaymanServiceImpl2 implements LaymanService{
	public void sayHello(){
		System.out.println("你好,我是layman2"); 
	}		
}

此时,IOC容器中,存在两个类型为LaymanService的bean,一个名为laymanServiceImpl,另一个名为laymanServiceImpl2

那么,项目启动会报错,为什么?

因为@Autowired默认按类型匹配,而且只匹配一个,现在找到两个,它不知道应该注入哪个?

于是它纠结,迷茫,最后一咬牙,还是报错吧。

如何解决该BUG

使用@Qualifier 注解。

修改代码。

LaymanServiceImpl2改动如下:

@Service("laymanService")
public class LaymanServiceImpl2 implements LaymanService{
	public void sayHello(){
		System.out.println("你好,我是layman"); 
	}		
}

@Service("laymanService")为LaymanServiceImpl2 指定bean的name属性

LaymanController.java 改动如下:

	@Autowired
	@Qualifier("laymanService")
    public LaymanService laymanService;

@Autowired扫描到两个类型为LaymanService 的bean,但是@Qualifier指定了bean的名称,因此它会去查找名为laymanService的bean,找到一个,装配成功!

@Autowired加载顺序图

在这里插入图片描述

@Resource

@Resource默认按名称进行装配,且有两个极其重要的属性:name和type

Spring将@Resource注解的name属性解析为bean的名字,type属性则解析为bean的类型。

逻辑

如果既不指定name,也不指定type,则按照Name进行装配(默认为变量名)
如果指定name,则从上下文中查找名称(id)唯一匹配的bean进行装配,找不到则抛出异常
如果指定type,则从上下文中找到类型唯一匹配的bean进行装配,找不到或者找到多个,抛出异常
如果同时指定name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常

// 默认查找名为laymanService的bean,如果找到唯一一个,则匹配,如果找不到,再按类型去查找
@Resource  
public LaymanService laymanService;

@Resource的装配顺序

  1. 既不指定name,也不指定type
    在这里插入图片描述

  2. 指定name

在这里插入图片描述

  1. 指定type
    在这里插入图片描述

  2. 同时指定name和type
    在这里插入图片描述

为什么不推荐使用@Autowired,可是依然那么人用

  • 历史遗留问题(以前就这一种方式,开发用习惯了,改不了。)
  • 省事,bean的名字不用写。(按类型匹配,只要扔个@service就行了),@resource要写@service("service_name"),否则就要两次查找,浪费性能。(@resource先找name,因为默认名不匹配,所以找不到,还会再找type,而@Autowired直接找type)

但是,架构设计考虑性能的话,推荐使用@resource

一是因为耦合度,契合大部份java框架。
二是写上@service("service_name"),访问速度会很快,毕竟可以通过name精准搜索。

缺点是,每个bean都要手动添加name属性。

补充

@AutowiredcommonAnnotationBeanPostProcessor处理器负责处理,而@ResourceautowiredAnnotationBeanPostProcessor处理器负责处理。

有兴趣的可以看看源码:

推荐的源码博客:https://blog.csdn.net/ijavaweb/article/details/25553231

标签:Resource,name,Autowired,异同,laymanService,bean,LaymanService,public
来源: https://www.cnblogs.com/amigou/p/15726937.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有