Spring中的@Autowired和@Resource注解对比

简介

@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,但是Spring支持该注解的注入。

本文代码已经上传至 gitee

简单对比

相同点

  • 都能进行依赖注入,可以加到属性上也可以加到setter方法上。

不同点

@Autowired注解
  • @Autowired注解是按照类型(byType)装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它的required属性为false
  • @Autowired注解装配对象如果根据类型能匹配到多个,可以通过@Qualifier指定名称通过名称注入。(优先级 高)
  • @Autowired注解装配对象如果根据类型能匹配到多个,可以在对应的需要注入的类上添加@Primary注解,来指定默认注入的对象(注意优先级不如@Qualifier)。 (优先级 中)
  • @Autowired注解装配对象如果根据类型能匹配到多个,则会按照属性名再去匹配找到对应的bean。(优先级 低)
@Resource注解
  • @Resource默认按照ByName自动注入。@Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性,这时将通过反射机制使用byName自动注入策略。
  • 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  • 如果指定了name,则从上下文中查找名称匹配的bean进行装配,找不到则抛出异常
  • 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  • 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

代码实战验证

@Autowired验证

// 验证一:@Qualifier注解配合使用

public interface AutowiredInterface {
    /**
     * 接口方法
     */
    void sayAutowired();
}



@Component
@Data
public class AutowiredBean implements AutowiredInterface{
    private String  name;

    @Override
    public void sayAutowired() {
        System.out.println("autowired:"+name);
    }
}

@Component
@Data
public class Autowired02Bean implements AutowiredInterface{
    private String  name;

    @Override
    public void sayAutowired() {
        System.out.println("autowired:"+name);
    }
}

// 不结合 @Qualifier注解,启动直接报错
@Service
public class TestService {

    @Autowired
//    @Qualifier(value = "autowired02Bean")
    private AutowiredInterface autowiredInterface;

    public void say() {
        System.out.println("开始说。。");
        autowiredInterface.sayAutowired();
        System.out.println("实际注入的对象:"+autowiredInterface.getClass());
    }

}

// 结合 @Qualifier注解,正常启动
@Service
public class TestService {

    // value 为指定的bean的名称
    @Autowired
    @Qualifier(value = "autowired02Bean")
    private AutowiredInterface autowiredInterface;

    public void say() {
        System.out.println("开始说。。");
        autowiredInterface.sayAutowired();
        System.out.println("实际注入的对象:"+autowiredInterface.getClass());
    }

}

// 验证二: @Primary注解结合使用
public interface AutowiredInterface {

    /**
     * 接口方法
     */
    void sayAutowired();
}

@Service
public class TestService {

    @Autowired
//    @Qualifier(value = "autowired02Bean")
    private AutowiredInterface autowiredInterface;

    public void say() {
        System.out.println("开始说。。");
        autowiredInterface.sayAutowired();
        System.out.println("实际注入的对象:"+autowiredInterface.getClass());
    }
}

@Component
@Data
public class AutowiredBean implements AutowiredInterface{
    private String  name;

    @Override
    public void sayAutowired() {
        System.out.println("autowired:"+name);
    }
}

// 不结合 @Primary 启动报错
@Component
@Data
// @Primary
public class Autowired02Bean implements AutowiredInterface{
    private String  name;

    @Override
    public void sayAutowired() {
        System.out.println("autowired:"+name);
    }
}

// 结合 @Primary 正常启动
@Component
@Data
@Primary
public class Autowired02Bean implements AutowiredInterface{
    private String  name;

    @Override
    public void sayAutowired() {
        System.out.println("autowired:"+name);
    }
}
// 验证三: 通过属性名注入bean
public interface AutowiredInterface {

    /**
     * 接口方法
     */
    void sayAutowired();
}


@Component
@Data
public class AutowiredBean implements AutowiredInterface{
    private String  name;

    @Override
    public void sayAutowired() {
        System.out.println("autowired:"+name);
    }
}

@Component
@Data
// @Primary
public class Autowired02Bean implements AutowiredInterface{
    private String  name;

    @Override
    public void sayAutowired() {
        System.out.println("autowired:"+name);
    }
}

@Service
public class TestService {

    // 属性名和具体实现的beanName不一致,启动报错
    @Autowired
//    @Qualifier(value = "autowired02Bean")
    private AutowiredInterface autowiredInterface;

    public void say() {
        System.out.println("开始说。。");
        autowiredInterface.sayAutowired();
        System.out.println("实际注入的对象:"+autowiredInterface.getClass());
    }
}


// 属性名和具体实现的一致,能成功注入启动
@Service
public class TestService {

    // 属性名和具体实现的beanName一致,启动成功
    @Autowired
//    @Qualifier(value = "autowired02Bean")
    private AutowiredInterface autowired02Bean;

    public void say() {
        System.out.println("开始说。。");
        autowired02Bean.sayAutowired();
        System.out.println("实际注入的对象:"+autowired02Bean.getClass());
    }
}
// 验证四: 验证上述三种的优先级
public interface AutowiredInterface {

    /**
     * 接口方法
     */
    void sayAutowired();
}


@Component
@Data
public class AutowiredBean implements AutowiredInterface{
    private String  name;

    @Override
    public void sayAutowired() {
        System.out.println("autowired:"+name);
    }
}

@Component
@Data
@Primary
public class Autowired02Bean implements AutowiredInterface{
    private String  name;

    @Override
    public void sayAutowired() {
        System.out.println("autowired:"+name);
    }
}


@Component
@Data
public class Autowired03Bean implements AutowiredInterface{
    private String  name;

    @Override
    public void sayAutowired() {
        System.out.println("autowired:"+name);
    }
}


// 接口有三个实现,上面三种分别命中其中的bean,看哪个能具体生效(两个直接的对比只要控制变量即可测出,这里只演示这里,其他自测即可,这里直接给出测出的结果如下: @Qualifier > @Primary > 属性名)
@Service
public class TestService {

    @Autowired
    @Qualifier(value = "autowiredBean")
    private AutowiredInterface autowired03Bean;

    public void say() {
        System.out.println("开始说。。");
        autowired03Bean.sayAutowired();
        System.out.println("实际注入的对象:"+autowired03Bean.getClass());
    }

}


@Resource验证

//这个验证前面的类可以不变,只要改注入的那部分代码即可,通用代码如下
public interface ResourceInterface {

    /**
     * 接口方法
     */
    void sayResource();
}

@Component
@Data
public class ResourceBean implements ResourceInterface {
    private String  name;

    @Override
    public void sayResource() {
        System.out.println("resource:"+name);
    }
}

@Component
@Data
public class Resource02Bean implements ResourceInterface {
    private String  name;

    @Override
    public void sayResource() {
        System.out.println("resource:"+name);
    }
}

@Component
@Data
public class Resource03Bean implements ResourceInterface {
    private String  name;

    @Override
    public void sayResource() {
        System.out.println("resource:"+name);
    }
}
// 验证一: 既不指定name也不指定type,默认走name,如果没匹配则尝试type,匹配不到报错
@Service
public class TestService {

    @Resource
    private ResourceInterface resourceInterface;

    public void sayResource() {
        System.out.println("开始说。。");
        resourceInterface.sayResource();
        System.out.println("实际注入的对象:"+resourceInterface.getClass());
    }

}

// 验证二: 只指定type,默认走name,如果没有或者也多个则报错
@Service
public class TestService {

    @Resource(type = ResourceInterface.class)
    private ResourceInterface resourceInterface;

    public void sayResource() {
        System.out.println("开始说。。");
        resourceInterface.sayResource();
        System.out.println("实际注入的对象:"+resourceInterface.getClass());
    }

}

// 验证三: 只指定name,匹配不到报错(spring中的beanName是要唯一的,所以不存在匹配多个)
@Service
public class TestService {
    @Resource(name = "hahaha")
    private ResourceInterface resourceInterface;

    public void sayResource() {
        System.out.println("开始说。。");
        resourceInterface.sayResource();
        System.out.println("实际注入的对象:"+resourceInterface.getClass());
    }

}

// 验证四: 既指定name也指定type,默认匹配同时满足的bean,匹配不到报错
@Service
public class TestService {
	// 无法匹配
    @Resource(name = "hahaha",type = ResourceInterface.class)
    private ResourceInterface resourceInterface;

    public void sayResource() {
        System.out.println("开始说。。");
        resourceInterface.sayResource();
        System.out.println("实际注入的对象:"+resourceInterface.getClass());
    }

}

@Service
public class TestService {
    // 无法匹配
    @Resource(name = "resourceBean",type = AutowiredInterface.class)
    private ResourceInterface resourceInterface;

    public void sayResource() {
        System.out.println("开始说。。");
        resourceInterface.sayResource();
        System.out.println("实际注入的对象:"+resourceInterface.getClass());
    }

}

@Service
public class TestService {
	// 正确匹配
    @Resource(name = "resourceBean",type = ResourceInterface.class)
    private ResourceInterface resourceInterface;

    public void sayResource() {
        System.out.println("开始说。。");
        resourceInterface.sayResource();
        System.out.println("实际注入的对象:"+resourceInterface.getClass());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值