@Autowired 和 @Resource 注解

1. 准备

先定义一个接口 Human,以及它的两个实现类 Male 和 FeMale。作为下面将用到的示例。

//Human.java
@Component
public interface Human {
    String say();
}

//Male.java
@Component
public class Male implements Human {
    @Override
    public String say() {
        return "I'm a man";
    }
}

//Female.java
@Component
public class FeMale implements Human {
    @Override
    public String say() {
        return "I'm a girl";
    }
}

2. @Autowired 和 @Resource 的相同点

Spring在实现依赖注入(DI)时可以使用 @Autowired 或 @Resource 来实现Bean的自动装配(即自动满足Bean依赖,在Spring初始化bean之后)。

@Component
public class DiTest{
    @Autorired
    private Human human;

//  @Resource
//  private Human human;

    public void test(){
        System.out.println(human.say());
    }
}

3. @Autowired 和 @Resource 的比较

(1)来源

@Autowired(org.springframework.beans.factory.annotation.Autowired) 是 Spring 自带的注解;

@Resource(javax.annotation.Resource) 是 J2EE 的注解。

(2)@Autowired 的用法

【###】注解源码

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;
}

【###】@Autowired 默认按照bean的类型进行匹配

    @Autowired
    private Human human;

上述示例中,@Autowired 注解会去Spring容器中寻找类型为Human或Human子类的Bean,并注入到变量human中。

如果匹配到多个结果则会抛出异常,因为它不知道该用哪个Bean。

同样,如果一个也没有匹配到,也会抛出异常,因为 @Autowired 注解默认情况下要求依赖对象必须存在(从上面源码可以看到 required 属性值默认为 true)。如果想要允许null值,可以设置它的 required 属性为 false。

@Autowired(required = false)
private Human human;

【###】按照bean名称进行匹配

bean名称即 Spring 容器中bean的id属性值,如果想要 @Autowired 注解按照bean名称进行匹配,则需要再加一个注解。

@Autowired
@Qualifier("male")
private Human human;

【###】@Autowired 注解还可以用在构造器上

@Component
public class DiTest{
    private Human human;

    @Autorired
    public DiTest(Human human){
        this.human = human;
    }

    public void test(){
        System.out.println(human.say());
    }
}

该注解会自动匹配构造器所有参数所需要的bean依赖。

【###】@Autowired 注解还可以用在普通方法上

无论是 setter 方法还是其他普通方法,都可以加上 @Autowired 注解来实现和上面一样的效果。

@Component
public class DiTest{
    private Human human;

    @Autorired
    public void hello(Human human){
        this.human = human;
    }

    public void test(){
        System.out.println(human.say());
    }
}

(3)@Resource 的用法

【###】注解源码

@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface Resource {
    String name() default "";
    String lookup() default "";
    Class<?> type() default java.lang.Object.class;
    enum AuthenticationType {
            CONTAINER,
            APPLICATION
    }
    AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
    boolean shareable() default true;
    String mappedName() default "";
    String description() default "";
}

【###】@Resource 默认按照bean名称进行bean匹配

@Resource
private Human human;

bean的名称默认为当前变量名。

上述示例中,@Resource 注解会去Spring容器中寻找名称(即id)为 “human” 的Bean,并注入到变量human中。

如果按照bean名称没有匹配到Bean,则退一步再按照bean类型(Human或Human子类)进行匹配;如果没有匹配到或匹配到多个则抛出异常。

【###】只按照bean名称匹配

@Resource(name="female")
private Human human;

指定了 name 属性值后,@Resource 注解则只按照 name 属性值所指定的bean名称去Spring容器中匹配。如果没有匹配到Bean则抛出异常。

注意:这种方式不可能出现匹配到多个Bean的情况,因为Bean的id值在Spring容器中是唯一的。如果有重复的属性值,则Spring应用在启动时就会抛出异常。

【###】只按照bean类型进行匹配

@Resource(type=Human.class)
private Human human;

从上述源码中可以看到,type属性的值为 Class 类型参数,默认为 java.lang.Object.class 。

指定了 type 属性值后,@Resource 注解则只按照 type 属性值所指定的bean类型(或子类类型)去 Spring 容器中匹配。如果没有匹配到 Bean 或匹配到多个结果则抛出异常。

【###】同时按照bean名称和bean类型进行匹配

@Resource(name="male",type=Human.class)
private Human human;

指定了 name 和 type 属性值后,@Resource 注解将去 Spring 容器中寻找 Id 属性值为 “male”,且类型为 Human(或Human子类类型)的Bean。如果没有匹配到,则抛出异常。

两个条件缺一不可。

【###】@Resource 注解不能用在类构造器上

【###】@Resource 注解可以用在普通方法上

@Resource 注解可以用在 setter 方法或其他普通方法上。

@Component
public class DiTest{
    private Human human;

    @Resource
    public void hello(Human human){
        this.human = human;
    }

    public void test(){
        System.out.println(human.say());
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值