@AutoWired与@Resource注解
首先对于这俩个注解:
自动绑定(Autowiring)模式:
模式 |
说明 |
---|---|
no |
默认值,未激活 Autowiring,需要手动执行依赖注入对象 |
byName |
根据被注入属性的名称作为Bean名称进行依赖查找,并将对象设置到该属性 |
byType |
根据被注入属性的类型作为依赖类型进行查找,并将对象设置到该属性 |
constructor |
特殊的byType类型,用户构造器参数 |
@Autowired是Spring中的注解,他是通过byType模式去查找注入bean
package org.springframework.beans.factory.annotation; 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; @Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Autowired { boolean required() default true; }
@Resource是JSR-250中提供的注解,即Java提供的注解,从包名就可以看出来,他是通过byName模式去查找bean
Autowired:org.springframework.beans.factory.annotation.Autowired Resource:javax.annotation.Resource
package javax.annotation; import java.lang.annotation.*; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.*; @Target({TYPE, FIELD, METHOD}) @Retention(RUNTIME) public @interface Resource { String name() default ""; String lookup() default ""; Class<?> type() default java.lang.Object.class; enum AuthenticationType { CONTAINER, APPLICATION } AuthenticationType authenticationType() default AuthenticationType.CONTAINER; boolean shareable() default true; String mappedName() default ""; String description() default ""; }
@AutoWired
@Autowired的依赖注入过程是由AutowiredAnnotationBeanPostProcessor支持的
具体的注入逻辑在DefaultListableBeanFactory#doResolveDependency方法
@Autowired的注入逻辑如下
- 找到所有类型符合的bean
- 如果没有类型符合的bean,则看@Autowired的required属性是否为true,是则抛出异常,否则返回null
- 如果只有一个,则将这个bean注入
- 如果有多个bean 4.1 选择其中带有Primary注解的bean,如果只有一个直接注入,如果有多个bean带有Primary注解则报错,如果不存在就下一步 4.2 选择其中优先级最高的bean(优先级使用javax.annotation.Priority表明),如果只有一个直接注入,如果有多个bean的优先级并列最高则报错,如果不存在就下一步 4.3 选择beanName和当前要注入的属性名相同的bean进行注入,有则注入,没有则报错
例:
@Autowired private DictionaryService dictionaryService;
如上代码所示,这样装配回去spring容器中找到类型为DictionaryService 的类,然后将其注入进来。这样会产生一个问题,当一个类型有多个bean值的时候,会造成无法选择具体注入哪一个的情况,这个时候我们需要配合着@Qualifier使用。即为:ByType改为ByName,或者使用byType导入带有@Primary注解的bean
//byType改为ByName
@Autowired @Qualifier(name="dictionaryServiceImpl") private DictionaryService dictionaryService;
//配合bean带有@primary注解导入
@Autowired
private DictionaryService dictionaryService;
如果没有找到bean,有俩种处理方式required设置,需要抛异常设置为reqiured为true
@Autowired(required=ture) private DictionaryService dictionaryService;
@Resource
@Resource的依赖注入过程是由CommonAnnotationBeanPostProcessor支持的
具体的注入逻辑在CommonAnnotationBeanPostProcessor#autowireResource
@Resource的注入逻辑如下
- 如果@Resource指定了name,则只会按照name进行查找,当找不到时抛出异常,找到将bean注入
- 如果@Resource没有指定name,则把属性名作为名字进行查找,找到将bean注入,当按照名字查找不到时,按照类型进行查找
「注意:@Resource按照类型查找的逻辑和@Autowired的一样,因为都是调用了DefaultListableBeanFactory#doResolveDependency方法」
例:。
@Resource private OutstockService outstockService;
@Resource(name="outstockServiceImpl ")
private OutstockService outstockService;
@Resource(type="OutstockService ")
private OutstockService outstockService;
@Resource(name="outstockServiceImpl",type="OutstockService")
private OutstockService outstockService;
①如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
②如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
③如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
④如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配
总结
@Autowired:先byType再byName
@Resource:先byName再byType(当指定@Resource name属性时,只会byName)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!