Resource和Autowired区别

1.使用场景

@Resource和@Autowired都是做bean注入时使用
@Resource是jdk的注解,不是spring的注解;由包javax.annotation.Resource提供,需要导入,但是Spring支持该注解注入

2.相同点,不同点

共同点:两者都可以写在setter方法,和字段上,不需要再写setter方法
不同点:

2.1 @Autowired是spring提供的注解,只按照byType注入

public class TestServiceImpl {
    // 下面两种@Autowired只要使用一种即可
    @Autowired
    private UserDao userDao; // 用于字段上
    
    @Autowired
    public void setUserDao(UserDao userDao) { // 用于属性的方法上
        this.userDao = userDao;
    }
}

Autowired是按照类型byType装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置required属性值为false。如果想按照名称(byName)来装配,可以结合Qualifier注解一起使用
(通过类型匹配多个candidate,在没有Qualifier的情况下,会使用对象名作为最后的fallback匹配)

public class TestServiceImpl {
    @Autowired
    @Qualifier("userDao")
    private UserDao userDao; 
}

2.2 @Resource

Resource默认是按照ByName自动注入的,@Resource有两个属性:name和type
spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型
如果使用name属性,使用byName自动注入策略,而使用 type属性时则使用byType自动注入策略
如果既不指定name也不指定type属性,这是将通过反射机制使用byName自动注入策略

public class TestServiceImpl {
    // 下面两种@Resource只要使用一种即可
    @Resource(name="userDao")
    private UserDao userDao; // 用于字段上
    
    @Resource(name="userDao")
    public void setUserDao(UserDao userDao) { // 用于属性的setter方法上
        this.userDao = userDao;
    }
}

@Resource装配顺序:

  1. 既不指定name属性,也不指定type属性,则按照注解的字段的名字自动按byName方式进行查找。如果没有找到符合的bean,则回退为一个原始类型,然后按照类型进行查找,如果找到就注入
    范例
@Service
public class DemoServiceImpl implements DemoService {
    /**
     * 返回“hello world”字符串
     * @return 字符串“hello world”
     */
    @Override
    public String helloWorld() {
        return "hello world";
    }

}

此时DemoServiceImpl是实现了DemoService接口,但是springboot加载后的bean的名字还是demoServiceImpl而非demoService

后续controller进行注入

@Slf4j
@Controller
public class HelloWorldController {

    @Resource
    DemoService demoService;


    @Resource
    BeanContext beanContext;

    @RequestMapping("/")
    @ResponseBody
    public String hello() {
        System.out.println(1);
        return demoService.helloWorld();
    }
}

上述既没有指定resource后面注解的name参数,修饰的变量名字是demoService,
1.就按照demoService的bean名字去context上下文里去找,但是springboot加载出来的是demoServiceImpl。上面截图中有记录所以找不到
2.就按照修饰的类型DemoService接口去找,发现接口里面对应类只有一个。找到。后续其他中间件如果要找到某个实现类,指定ref的时候,需要指定到demoServiceImpl上才对

①如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。

②如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。

③如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。

④如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。

@Resource的作用相当于@Autowired,只不过@Autowired按照byType自动注入。


在启动spring的时候,首先要启动容器;
启动spring容器时,会默认寻找容器扫描范围内的可加载bean,然后查找哪些bean上的属性和方法上有@Resource注解;
找到@Resource注解后,判断@Resource注解括号中的name属性是否为空,如果为空:看spring容器中的bean的id与@Resource要注解的那个变量属性名是否相同,如相同,匹配成功;如果不相同,看spring容器中bean的id对应的类型是否与@Resource要注解的那个变量属性对应的类型是否相等,若相等,匹配成功,若不相等,匹配失败。
如果@Resource注解括号中的name属性不为空,看name的属性值和容器中的bean的id名是否相等,如相等,则匹配成功;如不相等,则匹配失败。

posted @ 2021-05-31 15:57  SpecialSpeculator  阅读(1693)  评论(0编辑  收藏  举报