美文网首页SpringFrameworkSpring 开发程序员
@Autowired @Resource @Inject 区别简

@Autowired @Resource @Inject 区别简

作者: 殷天文 | 来源:发表于2018-04-27 16:10 被阅读230次
    先看例1
    // 一个接口
    public interface IOCService {
    }
    
    // 接口实现
    @Service
    public class IOCServiceImpl0 implements IOCService {
    }
    
    // 控制层
    @Controller
    public class TController {
    
        @Autowired private IOCService iOCService0;
        
        @Inject private IOCService iOCService01;
        
        @Resource private IOCService iOCService011;
        
        @RequestMapping("/t")
        @ResponseBody
        public void t() {
            System.out.println(iOCService0);
            System.out.println(iOCService01);
            System.out.println(iOCService011);
        }   
    }
    

    打印结果


    1. @Inject 与 @Autowired : 在Spring的环境下,@Inject 和 @Autowired是相同的,@Inject是 jsr-330 定义的规范,@Autowired 为 Spring 注解,二者默认都是 byType 策略进行注入。即 Spring会直接将 IOCService 类型的唯一 一个bean赋值给 iOCService0 这个成员变量
    2. @Resource :会先采用 byName 策略进行注入,如果byName 无法找到 会使用 byType 策略,如上述例子中。我们没有指定 name ,@Resource byName 无法找到bean,他会使用byType 策略进行注入。
    例2

    这个时候,我们为 IOCService 接口 增加一个实现类

    @Service
    public class IOCServiceImpl1 implements IOCService {
    }
    

    重启项目,这个时候 注入抛出异常,因为 当使用 byType 策略注入的时候 Spring 注入的接口所对应的bean 必须是唯一的,当有两个实现类的时候 Spring会找到 IOCService 的两个实例。

    nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
    No qualifying bean of type 'com.wansidong.communicate.test.IOCService' available: 
    expected single matching bean but found 2: IOCServiceImpl0,IOCServiceImpl1
    

    这时候需要使用 byName 策略进行注入

    @Controller
    public class TController {
    
        @Autowired
        @Qualifier("IOCServiceImpl0")
        private IOCService iOCService0;
        
        @Inject
        @Qualifier("IOCServiceImpl0")
        private IOCService iOCService00;
        
        @Resource(name="IOCServiceImpl0")
        private IOCService iOCService000;
        
        @Autowired
        @Qualifier("IOCServiceImpl1")
        private IOCService iOCService1;
        
        @Inject
        @Named("IOCServiceImpl1")
        private IOCService iOCService11;
        
        @Resource(name="IOCServiceImpl1")
        private IOCService iOCService111;
        
        @RequestMapping("/t")
        @ResponseBody
        public void t() {
            System.out.println("--------------------注入 IOCServiceImpl0");
            System.out.println(iOCService0);
            System.out.println(iOCService00);
            System.out.println(iOCService000);
            System.out.println("--------------------注入 IOCServiceImpl1");
            System.out.println(iOCService1);
            System.out.println(iOCService11);
            System.out.println(iOCService111);
        }
        
    }
    

    打印结果如下


    1. @Qualifier 与 @Named :可以看到 这两个注解配合 @Autowired 和 @Inject 都可以实现 byName 方式注入
    2. @Resource : 通过设置 @Resource(name="xxx") 完成 byName 注入

    疑问:
    写到这儿的时候,我发现一个问题,如果哪位知道的朋友,看到了可以私信,评论告诉我。
    我记得之前 我看过 Spring 通过@Controller @Service 创建的bean name 默认是首字母小写的类名,但是我这里抛出的 异常打印 bean 名称 是大写,而且我在指定 name 的时候 首字母小写也会报错,说明 Spring 为我创建的 bean 和 类名相同 ,为什么呢?

    对于 Spring 深层次的理解还是不够, 如果文章中哪里说的不对,还望各位看官指出。

    相关文章

      网友评论

      • 你终于懂:类名的前2个字符大写,直接返回类名
        殷天文:@你终于懂 👍厉害了,没有研究过源码
        你终于懂:源码里面有一条if判断前2个字符是不是大写,大写返回类名
        殷天文:@你终于懂 原来是编码规范造成的 😶

      本文标题:@Autowired @Resource @Inject 区别简

      本文链接:https://www.haomeiwen.com/subject/dpaakftx.html