@Resource @Autowire 对比

说到 @Resource 大家肯定会想到 @Autowired, 至于两者的区别:

@Autowired 是按 byType 自动注入

@Resource 默认按 byName 自动注入,而且还提供了 name 和 type 两个属性,其含义也容易理解,分别按 byName 和 byType 注入。

如果两个属性都没有提供的话,则根据属性名称注入,我理解的是 byName,还有地方说是通过反射机制使用 byName自动注入。

在实现类单一的情况下,@Resource @Autowire 没有区别, 都可以使用;

一旦一个接口多个实现类, 可能会出问题, 如果实例结果不唯一,那么@Autowired将会抛出异常

举例:

前提:  MyTestService 有两个实现类,  myTestServiceImpl1,myTestServiceImpl2 

@Resource @Autowire 对比_第1张图片

场景1:  使用@Autowire  使用byType(默认)

public class MyTest extends SpringTest {
    @Autowired
    private MyTestService myTestService;

    @Test
    void testAutowire() {
        myTestService.print();
    }
}

结论: 报错❌

分析:@Autowired 是按 byType 自动注入, byType 即按照MyTestService, 但代码中myTestServiceImpl1,myTestServiceImpl2  都实现自MyTestService ,类型都是MyTestService, 所以会找到两个myTestServiceImpl1,myTestServiceImpl2,无法注入;

 

场景2: @Autowire   使用byName

public class MyTest extends SpringTest {
    @Autowired
    private MyTestService myTestServiceImpl2;

    @Test
    void testAutowire() {
        myTestServiceImpl2.print();
    }
}

结论: 成功

@Resource @Autowire 对比_第2张图片

分析: 默认按 byType 注入,发现多个时,会尝试按 byName 注入,即按找到 myTestServiceImpl2  进行注入, 找到了name 为 myTestServiceImpl2 的 Bean。成功执行。

场景三: @Autowire  + @Qualifier("name")

public class MyTest extends SpringTest {
    @Autowired
    @Qualifier("myTestServiceImpl2")
    private MyTestService myTestService;

    @Test
    void testAutowire() {
        myTestService.print();
    }
}

结论: 成功

@Resource @Autowire 对比_第3张图片

分析:  @Autowire  + @Qualifier("name"), 会先按byType查找, 没有则按byName查找, 效果相当于@resource, 所以按byName查找, 找到了name 为 myTestServiceImpl2 的 Bean。成功执行。

 

场景4: @Resource  指定的是接口类的名称

public class MyTest extends SpringTest {

    @Resource
    private MyTestService myTestService;

    @Test
    void testAutowire() {
        myTestService.print();
    }
}

结论: 错误

分析: @Resource  按byName查找, 因为没有myTestService的 Bean, 所以找不到name 为 myTestService的 Bean。成功错误。

场景5: @Resource  指定 具体实现类的name

public class MyTest extends SpringTest {

    @Resource
    private MyTestService myTestServiceImpl1;

    @Test
    void testAutowire() {
        myTestServiceImpl1.print();
    }
}

结论:正常

分析: @Resource  按byName查找, 找到了name 为 myTestServiceImpl1 的 Bean。成功执行。

场景6: @Resource 没指定name属性,且默认属性名匹配不上,但只匹配上一个实现类

MyTestServiceImpl2删除, 此时MyTestService 只有一个实现类MyTestServiceImpl1

还是使用场景4的测试代码: 指定的是接口类的名称, 或者 指定为name不存在的随意一个名字

public class MyTest extends SpringTest {

    @Resource
    private MyTestService myTestService; //或者随便起个名字如,myTestSSSS

    @Test
    void testAutowire() {
        myTestService.print();
    }
}

结论: 正常

分析: 当 @Resource 没有提供 name 和 type 属性的时候,如果 byName 没有找到对应的 Bean 时,则会根据依赖属性的类型去 Spring 容器中查找是否有提供了其他类型相同的 Bean,如果有则自动注入,如果没有则报错。当然如果根据 byName 找到了则直接注入。接下来,我们再来看看,name 和 type 的情况。
 

场景7: Resource 指定name属性,但属性名不匹配

同样将MyTestServiceImpl2删除, 此时MyTestService 只有一个实现类MyTestServiceImpl1

public class MyTest extends SpringTest {

    @Resource(name="myTestServiceImpl2")
    private MyTestService myTestService;

    @Test
    void testAutowire() {
        myTestService.print();
    }
}

结论: 报错

分析:  @Resource(name="myTestServiceImpl2") 指定名称按照myTestServiceImpl2查找, 但是不存在myTestServiceImpl2(因为刚才删除了), 所以在使用 name 属性查找时,无法找到对应的 Bean,所以直接报错,没有再次去通过类型到 Spring 容器中查找

总结:

1、@Autowired
@Autowired默认byType自动注入,如果发现多个类型相同的Bean,再根据byName装配Bean,如果找到了则装配成功,找不到则装配失败。

@Autowired可与@Qualifier("beanName")搭配使用,注入指定bean。

@Autowired
@Qualifier("baseDao")
private BaseDao baseDao;
如,同一个接口,两个实现类,就可以使用该方式指定注入

@Autowired(required=false)表示如果spring上下文中没有找到该类型的bean ,将会使用

new SoftPMServiceImpl();
 
private ISoftPMService softPMService = new SoftPMServiceImpl();


 

3、@Resource
@Resource默认按byName自动注入
但是@Resource有两个属性是比较重要的,分别是name和type;
如果使用name属性,则使用byName的自动注入策略; .
而使用type属性时则使用byType自动注入策略;

@Resource装配顺序
  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

使用方式如下:

@Resource(name="dataSource");
@Resource(type="DataSource.class");
@Resource
private DataSource dataSource;

我一般习惯使用@Autowire + @Qulifier

你可能感兴趣的:(java,spring)