IOC中自动装配注解@Autowired和@Resource的区别

首先两者依赖的jar包不同

@Autowired

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.1.5.RELEASE</version>
</dependency>
org.springframework.beans.factory.annotation.Autowired;

IOC在通过@Autowired进行自动装配时依据的是Type:个人理解是是否实现的接口相同。假设有一个接口TestDao,该接口有一个实现类TestDaoImpl,我们在Service层注入TestDao通过@Autowired注入没有任何问题。

public interface TestDao {
    void print();
}
import com.tt.dao.TestDao;
import org.springframework.stereotype.Repository;

@Repository
public class TestDaoImpl implements TestDao {
    @Override
    public void print() {
        System.out.println("dao0");
    }
}
import com.tt.dao.TestDao;
import com.tt.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("service")
public class TestServiceImpl implements TestService {
    @Autowired
    TestDao dao;
    @Override
    public void print(){
        dao.print();
    }
}

//此时只有一个TestDao的实现类,所以注入成功,没有任何问题

如果我们再实现一个TestDao的实现类TestDaoImpl1,那么再使用@Autowired进行自动和装配时则程序报错

报错信息:

No qualifying bean of type 'com.tt.dao.TestDao' available: expected single matching bean but found 2: testDaoImpl,testDaoImpl1

大致意思是不知道选择哪个Bean去进行自动注入因为发现俩个Type一样的类

从此处也可以看出来,虽然我再@Repositoy并没有进行设置此bean的name,系统的默认命名规则是将该Bean的类名首字母小写来作为此bean的name

 

这里系统的默认命名规则是可以通过实现Spring提供的一个接口来自定义的

该接口为:BeanNameGenerator可以自定义实现BeanName的生成规则具体操作可参照以下文档

https://docs.spring.io/spring/docs/5.1.9.RELEASE/spring-framework-reference/core.html#beans

解决办法:搭配@Qualifier("testDaoImpl")混合使用此时选择的是名为testDaoImpl的Bean进行注入,此时@Qualifier必须有值,也就是在byType的基础上通过byName来获取指定的Bean。

两者必须混合使用才能达到效果:

如果只使用@Qualifier则不能完成注入

Exception in thread "main" java.lang.NullPointerException
    at com.tt.service.impl.TestServiceImpl.print(TestServiceImpl.java:15)
    at com.tt.Test.main(Test.java:11)

 

@Resource

<groupId>javax.annotation</groupId>
  <artifactId>javax.annotation-api</artifactId>
  <version>1.3.2</version>
</dependency>
javax.annotation.Resource;

 这里TestDao还是有俩个实现TestDaoImpl和TestDaoImpl1,我通过@Resource注解实现注入会发生什么异常?

import com.tt.dao.TestDao;
import com.tt.service.TestService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service("service")
public class TestServiceImpl implements TestService {
    @Resource
    TestDao dao;
    @Override
    public void print(){
        dao.print();
    }
}
果不其然:@Resource(name = "testDaoImpl")

报错信息:

No qualifying bean of type 'com.tt.dao.TestDao' available: expected single matching bean but found 2: testDaoImpl,testDaoImpl1

这说明@Resource首先默认是根据byType来查找的

此时我将想要的BeanName绑定在该注解的name参数上,程序顺利运行@Resource在没有给name赋值时默认byType注入

 

验证:

接下来验证一个问题当我给的name是testDaoImpl1,而我已将这个实现类删除,我们如果能注入成功,那么我们可以验证的是@Resource先进行byType注入,如果成功就不再去根据name找对应的BeanName了

如果注入失败,那么该注解在name有值得时候直接是根据byName进行注入的。

结果是:注入失败

结论:当@Resource(name="?")参数name那么有值时通过byName进行注入。

@Resource默认是通过byType进行查找Bean注入的。

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值