@Resource与@Autowired用法区别

常用注解的区别:

 spring中,@Resource和@Autowired都是做bean的注入时使用。使用过程中,有时候@Resource 和 @Autowired可以替换使用;有时,则不可以。

    下面,根据自己的学习,整理下这两个注解使用中的共同点和不同点,及用法上的不同。

     共同点

     @Resource和@Autowired都可以作为注入属性的修饰,在接口仅有单一实现类时,两个注解的修饰效果相同,可以互相替换,不影响使用。

    不同点

@Resource是Java自己的注解,@Resource有两个属性是比较重要的,分是name和type;Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
@Autowired是spring的注解,是spring2.5版本引入的,Autowired只根据type进行注入,不会去匹配name。如果涉及到type无法辨别注入对象时,那需要依赖@Qualifier或@Primary注解一起来修饰。
     

     我们创建一个简单的springboot项目demo,

         定义一个接口Human.java,里面一个方法 runMarathon,

         一个实现类Man.java

         一个Controller类HumanController.java,里面注入Human接口的实现

           

           附各Java类源码

package com.example.annotation.service;
 
/**
 * service接口定义
 * @author Administrator
 */
public interface Human {
    
    /**
     * 跑马拉松
     * @return
     */
    String runMarathon();
}
 
package com.example.annotation.service.impl;
 
import com.example.annotation.service.Human;
import org.springframework.stereotype.Service;
 
/**
 * service接口第一实现类
 * @author Administrator
 */
@Service
public class Man implements Human {
 
    public String runMarathon() {
        return "A man run marathon";
    }
}
 
package com.example.annotation.controller;
 
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.annotation.service.Human;
 
/**
 * controller层实现类
 * @author Administrator
 */
@RestController
@RequestMapping("/an")
public class HumanController {
 
    @Resource
    private Human human;
    
    @RequestMapping("/run")
    public String runMarathon() {
        return human.runMarathon();
    }
}
           至此,代码整理完成,启动springboot,浏览器地址栏输入http://localhost:8080/an/run

改动一:

将HumanController.java 类中的注解替换为@Autowired,再次启动,可以正常访问,与上图相同,这里不再贴访问结果图。

改动二:

再增加一个实现类Woman.java

package com.example.annotation.service.impl;
 
import com.example.annotation.service.Human;
import org.springframework.stereotype.Service;
 
/**
 * service接口第二实现类
 * @author Administrator
 */
@Service
public class Woman implements Human {
 
    public String runMarathon() {
        return "An woman run marathon";
    }
}
HumanController.java 注解使用@Resource

        @Resource
    private Human human;
启动springboot,控制台会报错,报错信息太多,截取关键信息

2018-09-10 16:07:10.362  WARN 5592 --- [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'humanController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.annotation.service.Human' available: expected single matching bean but found 2: man,woman
找关键信息 expected single matching bean but found 2: man,woman,被期望的单一结果被匹配到两个结果man和woman。

这里,我们需要借助@Resource注解的name属性或@Qualifier来确定一个合格的实现类

代码修改为 

        @Resource(name="woman")
    private Human human;
或 

        @Resource
    @Qualifier("woman")
    private Human human;
上面,我们指定了Human接口的实现类是Woman.java,启动springboot,访问 http://localhost:8080/an/run

改动三:

在改动二的基础上,将注解替换为@Autowired,启动报错

Description:
 
Field human in com.example.annotation.controller.HumanController required a single bean, but 2 were found:
    - man: defined in file [D:\DEV_ENV\springbootws\annotation\target\classes\com\example\annotation\service\impl\Man.class]
    - woman: defined in file [D:\DEV_ENV\springbootws\annotation\target\classes\com\example\annotation\service\impl\Woman.class]
 
 
Action:
 
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
报错信息很明显,HumanController需要一个bean实现,但是找到了两个 man 和woman

解决方案:使用@Primary注解,在有多个实现bean时告诉spring首先@Primary修饰的那个;或者使用@Qualifier来标注需要注入的类。

@Qualifier修改方式与改动二的相同,依然是修改HumanController.java 中间注入的Human上面,这里不再复述

@Primary是修饰实现类的,告诉spring,如果有多个实现类时,优先注入被@Primary注解修饰的那个。这里,我们希望注入Man.java ,那么修改Man.java为

package com.example.annotation.service.impl;
 
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import com.example.annotation.service.Human;
 
/**
 * service接口第一实现类
 * @author Administrator
 */
@Service
@Primary
public class Man implements Human {
 
    public String runMarathon() {
        return "A man run marathon";
    }
}
启动springboot后,可以看到注入的已经是Man.java 了。

以上,个人学习总结,如有不当之处,欢迎留言批评斧正。谢谢


加个菜,熟悉dubbo的知道,在服务层调用的使用就不能用Spring的Autowired来访问实现的接口

要通过RPC,远程访问的方式,也就是微服务的调用思想: 

1.在提供服务层: - 同类与Spring的接口实现@Service

@Component
org.apache.dubbo.config.annotation.Service(version = "提供者的代码版本")

2.服务消费层: - 同类与Spring的Controller中的调用服务@AutoWired

@Reference(version = "${comsumer.service.version}")

这样,你的代码就能实现跑通。可以去网上找一个Sprngboot实现bubbo的例子

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值