spring学习日记--DI的注解用法

引言

在Spring的依赖注入可以使用构造函数注入,也可以使用注解实现依赖注入,那么如何使用注解实现自动装配呢?

使用前提

1.导入约束:

 xmlns:context="http://www.springframework.org/schema/context"
        http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd"

2.配置注解的支持:易忘

代码示例:




    

1.@Autowired

用法: 这个注解我们需要加在需要进行自动装配的属性/属性的set方法上

好处:我们可以不写需要自动装配的属性的set方法

使用前提:这个属性在IOC容器中已经注册好了,且注册在容器中的bean满足byName的使用条件或byType的使用条件(必须有set方法存在),使用的时候它会先使用byType进行自动装配,byType失败就使用byName进行自动装配

代码示例:

实体类:

package com.lyc.pojo;

import org.springframework.beans.factory.annotation.Autowired;

public class People {
    @Autowired
    private Dog dog;
    @Autowired
    private Cat cat;
    private  String name;

    public Dog getDog() {
        return dog;
    }

//    public void setDog(Dog dog) {
//        this.dog = dog;
//    }

    public Cat getCat() {
        return cat;
    }

//    public void setCat(Cat cat) {
//        this.cat = cat;
//    }

    public String getName() {
        return name;
    }
    

    @Override
    public String toString() {
        return "People{" +
                "dog=" + dog +
                ", cat=" + cat +
                ", name='" + name + '\'' +
                '}';
    }
}

 

public class Cat {
    public void shout(){
        System.out.println("miao~");
    }
}
public class Dog {
    public void shout(){
        System.out.println("wang~");
    }
}

 

bean.xml




    
    
    
    

测试类:

 public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        People people = context.getBean("people", People.class);
        people.getDog().shout();
        people.getCat().shout();
    }

运行效果:

spring学习日记--DI的注解用法_第1张图片

让我们进入@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中还有一个默认的布尔值方法,经过测试得出

如果显示定义了Autowired的request属性为false,则表示该属性可以为null,否则不允许为空

让我们在探究一下,为空?这让我想到了@Nullable,经过测试,和'request = false'效果一致

2.@Qualifier

注解@Qualifier是配合@Autowired 一起/配套 使用的,它的使用场景就是当注解@Autowired的使用条件都不满足的时候,即容器中这个对象属性的时候既不满足byName自动装配的使用条件,又不满足byType自动装配的使用条件,此时,我们就可以通过@Qualifier注解,按照byName显式的为这个对象属性指定一个bean, 这样容器就知道怎么自动装配person bean了

拓展:

byname:会自动在容器上下文中查找,和自己对象set方法后面的值对应的bean id
bytype:会自动在容器上下文中查找,和自己对象属性类型相同的bean id

弊端:必须保证这个类型全局唯一,才能运行

案例代码:

其他类不变,主要变化在bean类与实体类

bean.xml




    
    
    
    
    
    

实体类:

   @Autowired
    @Qualifier(value = "dog111")
    private Dog dog;
    @Autowired
    @Qualifier(value = "cat111")
    private Cat cat;
    private  String name;

 测试类

 public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        People people = context.getBean("people", People.class);
        people.getDog().shout();
        people.getCat().shout();
    }

测试结果:

spring学习日记--DI的注解用法_第2张图片

3.@Resource

@Resource的作用 = @Autowired+@Qualifier,但是开发中最常用的还是@Autowired注解

首先,这个注解在javax.annotation.Resource包中,但是JDK11以后完全移除了javax扩展,所以不能直接使用@resource注解

解决办法:通过maven引入依赖

简单示例:

public class People {
    //如果显示定义了Autowired的request属性为false,则表示该属性可以为null,否则不允许为空
    @Resource(name = "dog111")
    private Dog dog;
    @Resource(name = "cat111")
    private Cat cat;
    private  String name;

 

小结

  • @Autowired:自动装配,先通过type,再使用name,都不行就报错[常用]

  • @Qualifier:配合@Autowired使用,当@Autowired报错时,使用@Qualifier(value=“指定bean的ID值”)

  • @Resource:Java自己的注解,使用的使用如果JDK>=11,可以使用maven依赖导入javax包,否则这个注解使用不了

    • @Resource先通过name,再使用type自动装配,都不行就报错

    • 可以通过@Resource(name = “XXX”)实现和@Qualifier相同的效果

  • @Nullable和@Autowired(required = false)效果相同,可以使得对象属性为NULL也不报错

拓展

Spring的依赖注入为什么推荐使用构造函数注入而不推荐使用@Autowired?

答:

在官网中讲到,Spring团队中通常提倡构造函数注入,因为构造函数注入允许将应用程序组件变为不可变对象,并确保所需的依赖项不为null,此外,构造函数注入的组件始终以完全初始化状态返回给客户端(调用)代码

被@Autowired修饰后,你就不能把该属性设为不可变量,即不能加上final关键字, 而构造函数可以,因为有时候我们确实需要将项目中的属性设为不可变量

而有时候我们可能会有多个构造函数,那这种情况,spring就会不知道选择哪个构造函数作为Bean,这一点,在官网中也有说到:顺便说,大量的构造函数参数是一种糟糕的代码设计,这意味着这类可能具有太多责任,应该重构以更好地解决适当的关注点分离问题

所以,这意味着我们的类最好是单一职责。

希望对大家有所帮助 

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