构造函数的注入(Java学习笔记)

所谓 Bean 属性注入,简单点说就是将属性注入到 Bean 中的过程,而这属性既可以普通属性,也可以是一个对象(Bean)。

Spring 主要通过以下 2 种方式实现属性注入:

构造函数注入
setter 注入(又称设值注入)

构造函数注入

我们可以通过 Bean 的带参构造函数,以实现 Bean 的属性注入。

使用构造函数实现属性注入大致步骤如下:
在 Bean 中添加一个有参构造函数,构造函数内的每一个参数代表一个需要注入的属性;
在 Spring 的 XML 配置文件中,通过 及其子元素 对 Bean 进行定义;
在 元素内使用 元素,对构造函数内的属性进行赋值,Bean 的构造函数内有多少参数,就需要使用多少个 元素。
Grade类,使用Log记录信息:

package org.example;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Grade {
    private static final Log LOGGER = LogFactory.getLog(Grade.class);
    private Integer gradeId;
    private String gradeName;

    public Grade(Integer gradeId,String gradeName){
        LOGGER.info("正在执行Grade的有参构造方法,参数分别为:gradeId="+gradeId+",gradeName="+gradeName);
        this.gradeId = gradeId;
        this.gradeName=gradeName;
    }

    @Override
    public String toString() {
        return "Grade{" +
                "gradeId=" + gradeId +
                ", gradeName='" + gradeName + '\'' +
                '}';
    }
}

Student类

package org.example;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Student {
    private static final Log LOGGER= LogFactory.getLog(Student.class);
    private int id;
    private String name;
    private Grade grade;

    public Student(int id,String name,Grade grade){
        LOGGER.info("正在执行Student的有参构造方法,参数分别时:id="+id+",name="+",grade="+grade);
        this.id =id;
        this.name=name;
        this.grade = grade;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", grade=" + grade +
                '}';
    }
}

Beans.xml

<?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-3.0.xsd">

    <bean id="helloWorld" class="org.example.HelloWorld">
        <property name="message" value="Hello World!" />
    </bean>

    <bean id="grade" class="org.example.Grade">
        <constructor-arg name="gradeId" value="1"></constructor-arg>
        <constructor-arg name="gradeName" value="一年级"></constructor-arg>
    </bean>
    <bean id="student" class="org.example.Student">
        <constructor-arg name="id" value="1"></constructor-arg>
        <constructor-arg name="name" value="学生1"></constructor-arg>
        <constructor-arg name="grade" ref="grade"></constructor-arg>
    </bean>

</beans>

Mian类

public class Main {
    private static final Log LOGGER = LogFactory.getLog(Main.class);
    public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        Student student = context.getBean("student",Student.class);
        LOGGER.info(student.toString());
    }
}

执行Main中的main()方法,控制台输出:
在这里插入图片描述

setter 注入

我们可以通过 Bean 的 setter 方法,将属性值注入到 Bean 的属性中。

在 Spring 实例化 Bean 的过程中,IoC 容器首先会调用默认的构造方法(无参构造方法)实例化 Bean(Java 对象),然后通过 Java 的反射机制调用这个 Bean 的 setXxx() 方法,将属性值注入到 Bean 中。

使用 setter 注入的方式进行属性注入,大致步骤如下:
在 Bean 中提供一个默认的无参构造函数(在没有其他带参构造函数的情况下,可省略),并为所有需要注入的属性提供一个 setXxx() 方法;
在 Spring 的 XML 配置文件中,使用 及其子元素 对 Bean 进行定义;
在 元素内使用 元素对各个属性进行赋值。
Student2类

package org.example;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Student2 {
    private static final Log LOGGER = LogFactory.getLog(Student.class);
    private int id;
    private String name;
    private Grade grade;

    //无参构造方法,在没有其他带参构造方法的情况下,可以省略
    public Student2() {
    }

    //id 属性的 setter 方法
    public void setId(int id) {
        LOGGER.info("正在执行 Student2 类的 setId() 方法…… ");
        this.id = id;
    }

    //name 属性的 setter 方法
    public void setName(String name) {
        LOGGER.info("正在执行 Student2 类的 setName() 方法…… ");
        this.name = name;
    }

    public void setGrade(Grade grade) {
        LOGGER.info("正在执行 Student2 类的 setGrade() 方法…… ");
        this.grade = grade;
    }

    @Override
    public String toString() {
        return "Student2{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", grade=" + grade +
                '}';
    }
}


Grade2类

package org.example;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Grade2 {
    private static final Log LOGGER = LogFactory.getLog(Grade.class);
    private Integer gradeId;
    private String gradeName;

    /**
     * 无参构造函数
     * 若该类中不存在其他的带参构造函数,则这个默认的无参构造函数可以省略
     */
    public Grade2() {
    }

    public void setGradeId(Integer gradeId) {
        LOGGER.info("正在执行 Grade2 类的 setGradeId() 方法…… ");
        this.gradeId = gradeId;
    }

    public void setGradeName(String gradeName) {
        LOGGER.info("正在执行 Grade2 类的 setGradeName() 方法…… ");
        this.gradeName = gradeName;
    }

    @Override
    public String toString() {
        return "Grade2{" +
                "gradeId=" + gradeId +
                ", gradeName='" + gradeName + '\'' +
                '}';
    }
}

Beans.xml

 <bean id="student2" class="org.example.Student2">
        <!--使用 property 元素完成属性注入
            name: 类中的属性名称,例如 id,name
            value: 向属性注入的值 例如 学生的 id 为 1,name 为张三
        -->
        <property name="id" value="1"></property>
        <property name="name" value="张三"></property>
        <property name="grade" ref="grade"></property>
    </bean>
    <bean id="grade2" class="org.example.Grade2">
        <property name="gradeId" value="3"></property>
        <property name="gradeName" value="三年级"></property>
    </bean>

Main.java类

package org.example;

import com.sun.media.jfxmedia.logging.Logger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    private static final Log LOGGER = LogFactory.getLog(Main.class);
    public static void main(String[] args) {
//
//        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
//        HelloWorld obj = context.getBean("helloWorld",HelloWorld.class);
//        System.out.println(obj.getMessage());

//        BeanFactory factory = new ClassPathXmlApplicationContext("Beans.xml");
//        HelloWorld obj = factory.getBean("helloWorld", HelloWorld.class);
//        System.out.println(obj.getMessage());

        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
//        Student student = context.getBean("student",Student.class);
//        LOGGER.info(student.toString());

        Grade2 grade2 = context.getBean("grade2",Grade2.class);
        LOGGER.info(grade2.toString());
    }

}

运行结果:
运行结果

短命名空间注入

我们在通过构造函数或 setter 方法进行属性注入时,通常是在 元素中嵌套 和 元素来实现的。这种方式虽然结构清晰,但书写较繁琐。

Spring 框架提供了 2 种短命名空间,可以简化 Spring 的 XML 配置,如下表。

短命名空间简化的 XML 配置说明
p 命名空间 元素中嵌套的 property 元素是 setter 方式属性注入的一种快捷实现方式
c 命名空间 元素中嵌套的 constructor元素是构造函数属性注入的一种快捷实现方式

p 命名空间注入

p 命名空间是 setter 方式属性注入的一种快捷实现方式。通过它,我们能够以 bean 属性的形式实现 setter 方式的属性注入,而不再使用嵌套的 元素,以实现简化 Spring 的 XML 配置的目的。

首先我们需要在配置文件的 元素中导入以下 XML 约束。

xmls:p="htttp://www.springframework.org/schema/p"

在导入XML约束后,我们就会使用以下的形式及逆行属性注入

< bean id="Bean是唯一的标识“ class="包名+类名" p:普通属性=”普通属性值“ p:对象属性 ref="对象的引用">

使用 p 命名空间注入依赖时,必须注意以下 3 点:
Java 类中必须有 setter 方法;
Java 类中必须有无参构造器(类中不包含任何带参构造函数的情况,无参构造函数默认存在);
在使用 p 命名空间实现属性注入前,XML 配置的 元素内必须先导入 p 命名空间的 XML 约束。

实例:
Dept

package org.example;

public class Dept {
    private String deptNo;
    private String deptName;

    public void setDeptNo(String deptNo){
        this.deptName=deptName;
    }
    public void setDeptName(String deptName){
        this.deptName=deptName;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptNo='" + deptNo + '\'' +
                ", deptName='" + deptName + '\'' +
                '}';
    }
}

Employee类

package org.example;

public class Employee {
    private String empNo;
    private String empName;
    private Dept dept;

    public String getEmpNo() {
        return empNo;
    }

    public void setEmpNo(String empNo) {
        this.empNo = empNo;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "empNo='" + empNo + '\'' +
                ", empName='" + empName + '\'' +
                ", dept=" + dept +
                '}';
    }
}

Beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean id="employee" class="org.example.Employee" p:empName="小李" p:dept-ref="dept" p:empNo="22222"></bean>
    <bean id="dept" class="org.example.Dept" p:deptNo="1111" p:deptName="技术部"></bean>
</beans>

Main主类

package org.example;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    private static final Log LOGGER = LogFactory.getLog(Main.class);
    public static void main(String[] args) {
     ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        Employee employee = context.getBean("employee",Employee.class);

        LOGGER.info(employee.toString());
    }

}

运行结果:
运行结果

c 命名空间注入

c 命名空间是构造函数注入的一种快捷实现方式。通过它,我们能够以 属性的形式实现构造函数方式的属性注入,而不再使用嵌套的 元素,以实现简化 Spring 的 XML 配置的目的。

首先我们需要在配置文件的 元素中导入以下 XML 约束。

xmlns:c="http://www.springframework.org/schema/c"

在导入 XML 约束后,我们就能通过以下形式实现属性注入。

<bean id="Bean 唯一标志符" class="包名+类名" c:普通属性="普通属性值" c:对象属性-ref="对象的引用">

使用 c 命名空间注入依赖时,必须注意以下 2 点:


Java 类中必须包含对应的带参构造器;
在使用 c 命名空间实现属性注入前,XML 配置的 元素内必须先导入 c 命名空间的 XML 约束


Dept1

package org.example;

public class Dept1 {
    //部门编号
    private String deptNo;
    //部门名称
    private String deptName;
    public Dept1(String deptNo, String deptName) {
        this.deptNo = deptNo;
        this.deptName = deptName;
    }
    @Override
    public String toString() {
        return "Dept{" +
                "deptNo='" + deptNo + '\'' +
                ", deptName='" + deptName + '\'' +
                '}';
    }
}

Employee1

package org.example;


public class Employee1 {
    //员工编号
    private String empNo;
    //员工姓名
    private String empName;
    //部门信息
    private Dept1 dept1;
    public Employee1(String empNo, String empName, Dept1 dept1) {
        this.empNo = empNo;
        this.empName = empName;
        this.dept1 = dept1;
    }
    @Override
    public String toString() {
        return "Employee{" +
                "empNo='" + empNo + '\'' +
                ", empName='" + empName + '\'' +
                ", dept=" + dept1 +
                '}';
    }
}

Beans,xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="employee1" class="org.example.Employee1" c:empName="小胡" c:dept1-ref="dept1" c:empNo="999"></bean>

    <bean id="dept1" class="org.example.Dept1" c:deptNo="2222" c:deptName="测试部"></bean>

</beans>

Mian

package org.example;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

 
public class Main {
    private static final Log LOGGER = LogFactory.getLog(Main.class);
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        Employee1 employee1 = context.getBean("employee1",Employee1.class);

        LOGGER.info(employee1.toString());
    }

}

运行结果
在这里插入图片描述

学习文献

学习文献地址

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值