Spring的setter注入和构造器注入

187 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情

1.项目准备

1.1 接口和实体类

public interface Person {
}
public class Student implements Person {

    private Integer sid;

    private String sname;

    private Integer age;

    private String gender;

    private Double score;

    public Student() {
    }

    public Student(Integer sid, String sname, String gender,Integer age) {
        this.sid = sid;
        this.sname = sname;
        this.age = age;
        this.gender = gender;
    }

    public Student(Integer sid, String sname, String gender,Double score) {
        this.sid = sid;
        this.sname = sname;
        this.score = score;
        this.gender = gender;
    }

    //set和get方法
    //toString方法
}

1.2 spring配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

</beans>

2.依赖注入

依赖注入是IOC思想的具体实现。在spring里,依赖注入其实就是为实体类的属性赋值,比如我们这里的例子:Student类依赖它里面的属性,我们通过依赖注入来为这些属性赋值。

2.1 依赖注入-setter注入

proerty标签的name是去指定属性名。注意,是属性名而不是属性值。**什么是属性名?**实体类有set和get方法,你将这些方法的set和get删除,其余部分的首字母大写改小写就是属性名,比如:getSname或者setSname,将get或set去掉,S改为s,得到sname。这个sname就是属性名。你在idea里,将鼠标移动到name属性的值上,你会看到一个set方法。这也是为什么上面的实体类要设置get和set方法的原因。

property标签的value就是用来为属性名赋值。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="studentTwo" class="com.atguigu.spring.pojo.Student">
        <!--property:通过成员变量的set方法进行赋值 name:指定属性名  value:为属性名注入的值-->
        <property name="sid" value="1001"></property>
        <property name="sname" value="张三"></property>
        <property name="age" value="23"></property>
        <property name="gender" value="男"></property>
    </bean>

</beans>
@Test
public void testDI() {
    //获取IOC容器
    ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    //获取bean
    Student student = ioc.getBean("studentTwo", Student.class);
    System.out.println(student);
}

实验结果

image-20221125213552815.png

2.2 依赖注入-构造器注入

spring的通过构造器进行依赖注入的前提是实体类必须有有参构造方法。注入的方式一般是按照有参构造方法的参数,依次在配置文件里赋值

有参构造器方法的参数顺序如下:

public Student(Integer sid, String sname, String gender,Integer age);
<bean id="studentThree" class="com.atguigu.spring.pojo.Student">
    <constructor-arg value="1002"></constructor-arg>
    <constructor-arg value="李四"></constructor-arg>
    <constructor-arg value="女"></constructor-arg>
    <constructor-arg value="24" ></constructor-arg>
</bean>

测试代码

@Test
public void testDI() {
    //获取IOC容器
    ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    //获取bean
    Student student = ioc.getBean("studentThree", Student.class);
    System.out.println(student);
}

实验结果

image-20221125214131033.png

如果我们多出一个形式和现在的有参构造器一样的构造器呢?注意下:下面两个构造器的形参只有后面一个类型不同,其他都相同。

public Student(Integer sid, String sname, String gender,Integer age) {
    this.sid = sid;
    this.sname = sname;
    this.age = age;
    this.gender = gender;
}

public Student(Integer sid, String sname, String gender,Double score) {
    this.sid = sid;
    this.sname = sname;
    this.score = score;
    this.gender = gender;
}

配置文件还是这样。那问题来了,运行是报错还是正常赋值?

<bean id="studentThree" class="com.atguigu.spring.pojo.Student">
    <constructor-arg value="1002"></constructor-arg>
    <constructor-arg value="李四"></constructor-arg>
    <constructor-arg value="女"></constructor-arg>
    <constructor-arg value="24" ></constructor-arg>
</bean>

运行代码,结果如下。配置文件里的24赋值给了Double类型,没有报错。

image-20221125214656701.png

从上面的结果我们得知,spring可能对不同类型的数据在赋值时有不同的优先级。但这不重要,重要的是我们能不能自己确定数据要赋值给那个属性?答案是可以。具体的做法是用constructor-arg标签的name属性指定要赋值的属性。比如:我们指定将24赋值给age。

<bean id="studentThree" class="com.atguigu.spring.pojo.Student">
    <constructor-arg value="1002"></constructor-arg>
    <constructor-arg value="李四"></constructor-arg>
    <constructor-arg value="女"></constructor-arg>
    <constructor-arg value="24" name="age"></constructor-arg>
</bean>

实验结果如下:

image-20221125215901575.png