Spring框架从入门到入土(二):Spring之基于XML的DI(依赖注入)

Spring框架从入门到入土(二):Spring之基于XML的DI(依赖注入)

di的实现语法有两种,表示创建对象,给属性赋值。

di的实现有两种:

  1. 在spring的配置文件中,使用标签和属性完成,叫做基于xml的di实现。
  2. 使用spring中的注解,完成属性赋值,叫做基于注解的di实现

注入分类

di的语法分类有两种:

  1. set注入(设置注入):spring调用类的set方法,在set方法可以实现属性的赋值。
  2. 构造注入:spring调用类的有参数构造方法,创建对象,在构造方法中完成。

set注入(掌握)

简单类型的设置注入
  1. 编写配置文件
    <!--声明student对象
    注入:就是赋值的意思
    简单类型:spring规定,java的基本数据类型和String类型都是简单类型
    di:给属性赋值
    1. set注入(设置注入):spring调用类的set方法,可以在set方法中完成赋值。
    ①简单类型的set注入
    <property name = "属性名字" value = "此属性的值"/>
    一个property只能给一个属性赋值
    <property....../>
    -->
    <bean id="student" class="com.liar.ba01.Student">
        <property name="name" value="张三"/>
        <property name="age" value="20"/>
    </bean>
  1. 测试方法
    @Test
    public void test01(){
        String config = "ba01/applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);

        //从容器中获取某个对象,调用对象的方法
        Student stu = (Student)ac.getBean("student");
        //使用创建好的对象
        System.out.println(stu);
    }
  1. 测试结果,赋值成功

image-20220323131720218

注意事项:

  1. spring先执行无参构造,创建对象,再调用set方法进行赋值。

  2. 如果没有set方法,spring会报错。

  3. set方法不一定会赋值,因为spring只负责调用set方法,不负责检查set方法中是否赋值。

  4. 属性名对应的属性值即使是整形也必须要带上双引号

    <property name="age" value="20"/>
    
引用类型的设置注入
  1. 编写一个学校对象
package com.liar.ba02;



/**
 * @author liar
 * @date 编写时间: 2022/3/23 14:40
 */
public class School {

    private String name;
    private String address;

    public School() {
    }

    public School(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
  1. 编写一个含有school对象的Student对象
package com.liar.ba02;

/**
 * @author liar
 * @date 编写时间: 2022/3/23 12:58
 */
public class Student {
    private String name;
    private int age;
    /*
     * 声明一个引用类型
     */
    private School school;

    public Student() {
        System.out.println("spring会调用类的无参数构造方法创建对象!!");
    }

    public Student(String name, int age, School school) {
        this.name = name;
        this.age = age;
        this.school = school;
    }

    public School getSchool() {
        return school;
    }

    public void setSchool(School school) {
        this.school = school;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}
  1. 编写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.xsd">

    <!--
    ②引用类型的注入:spring调用类的set方法
    <bean id="xxx" class="xxx">
        <property name="属性名" ref="bean的id(对象的名称)"/>
    </bean>
    -->

    <!--声明School对象-->
    <bean id="mySchool" class="com.liar.ba02.School">
        <property name="name" value="北京大学"/>
        <property name="address" value="北京"/>
    </bean>
    <!--给student对象赋值-->
    <bean id="myStudent" class="com.liar.ba02.Student">
        <property name="name" value="李四"/>
        <property name="age" value="18"/>
        <!--赋值school-->
        <property name="school" ref="mySchool"/>
    </bean>


</beans>
  1. 编写测试方法
    @Test
    public void test02(){
        String config = "ba02/applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);

        //从容器中获取某个对象,调用对象的方法
        Student stu = (Student)ac.getBean("myStudent");
        //使用创建好的对象
        System.out.println(stu);
    }
  1. 测试结果

image-20220323150742211

构造注入(理解)

使用name属性实现构造注入
  1. 编写xml文件
    <!--声明School对象-->
    <bean id="mySchool" class="com.liar.ba02.School">
        <property name="name" value="北京大学"/>
        <property name="address" value="北京"/>
    </bean>

    <!--构造注入: spring调用类的有参数构造方法,在创建对象的同时,在构造方法中给属性赋值
     构造注入使用<constructor-arg>标签
     标签属性:
     name:表示构造方法的形参名
     index:表示构造方法的参数位置,参数从左到右位置是0,1,2....
     value:构造方法是简单类型的用value
     ref:构造方法是引用类型的,用ref
     -->
    <bean id="myStudent" class="com.liar.ba02.Student">
        <constructor-arg name="name" value="王五"/>
        <constructor-arg name="age" value="19"/>
        <constructor-arg name="school" ref="mySchool"/>
    </bean>
  1. 测试方法不变,测试结果如下

image-20220323152818613

使用index属性实现构造注入
    <!--声明School对象-->
    <bean id="mySchool" class="com.liar.ba02.School">
        <property name="name" value="清华大学"/>
        <property name="address" value="北京海淀区"/>
    </bean>   
    <bean id="myStudent" class="com.liar.ba02.Student">
        <constructor-arg index="0" value="赵六"/>
        <constructor-arg index="1" value="29"/>
        <constructor-arg index="2" ref="mySchool"/>
    </bean>
构造注入创建文件对象
    <!--创建file,使用构造注入-->
    <bean id="myFile" class="java.io.File">
        <constructor-arg name="parent" value="E:\Workplace\JWorkPlace\spring-course\spring-01-hello"/>
        <constructor-arg name="child" value="readme.txt"/>
    </bean>
    @Test
    public void test04(){
        String config = "ba02/applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);

        //创建文件
        File file = (File)ac.getBean("myFile");
        //读取文件名
        System.out.println(file.getName());

        //读取文件内容
        BufferedReader reader = null;
        StringBuffer sbf = new StringBuffer();
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempStr;
            while ((tempStr = reader.readLine()) != null) {
                sbf.append(tempStr);
            }
            reader.close();
            System.out.println(sbf.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

测试结果

image-20220323155601044

引用类型属性自动注入

对于引用类型属性的注入,可以不在配置文件中显式注入,可以通过为<bean/>表签设置autowire属性值,为引用类型属性进行隐式自动注入(默认是不注入属性)。根据自动注入的判断标准不同,可以分为两种:

byName:根据名称自动注入

byType:根据类型自动注入

byName自动注入

  1. xml文件
<!--
    引用类型的自动注入:spring框架可以根据某些规则给引用类型进行赋值
    byName:java类中引用属性名和spring容器中(配置文件)<bean>的id名称一样,且数据类型是一致的
           这样的容器中的bean,spring可以赋值给引用类

           语法:
           <bean id="xx" class="yyy" autowire="byName">
             简单属性赋值
           </bean>
    -->

    <!-- 声明School对象-->
    <bean id="school" class="com.liar.ba03.School">
        <property name="name" value="清华大学"/>
        <property name="address" value="海淀区"/>
    </bean>

    <bean id="myStudent" class="com.liar.ba03.Student" autowire="byName">
        <property name="name" value="小梁"/>
        <property name="age" value="20"/>
    </bean>
  1. 测试
    @Test
    public void test01(){
        String config = "ba03/applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);

        //从容器中获取某个对象,调用对象的方法
        Student stu = (Student)ac.getBean("myStudent");
        //使用创建好的对象
        System.out.println(stu);
    }

byType自动注入

测试同源的第二类:

  byType: java类中引用类型的数据类型和spring容器中(配置文件)<bean>的class属性是同源关系。
           这样的bean可以赋值给引用类型

   同源就是同一类的意思:
   1. java类中引用类型的数据类型和bean的class的值是一样的。
   2. java类中引用类型的数据类型和bean的class的值是父子类关系。
   2. java类中引用类型的数据类型和bean的class的值是接口和实现类的关系。

编写一个子类继承School

package com.liar.ba03;

/**
 * @author liar
 * @date 编写时间: 2022/3/23 17:14
 */
public class PrimarySchool extends School{


}
<!--声明一个学校的子类-->
    <bean id="primary" class="com.liar.ba03.PrimarySchool">
        <property name="name" value="北京小学"/>
        <property name="address" value="大兴区"/>
    </bean>

    <bean id="myStudent" class="com.liar.ba03.Student" autowire="byType">
        <property name="name" value="小梁"/>
        <property name="age" value="20"/>
    </bean>

image-20220323172013423

注意:在bytype中声明bean的时候,只能有一个符合条件的,多于两个会报错。

多配置文件

优势:

  1. 每个文件的大小比一个文件要小很多。效率高
  2. 避免多人竞争带来的冲突

多文件的配置方式:

  1. 按照功能模块:一个模块一个配置文件。
  2. 按照类的功能:数据库相关配置一个文件配置文件,做事务的一个配置文件,做service功能的一个配置文件。

包含关系的配置文件:

  1. 学生模块的配置文件
<?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="myStudent" class="com.liar.ba03.Student" autowire="byType">
        <property name="name" value="小梁"/>
        <property name="age" value="20"/>
    </bean>

</beans>
  1. 学校模块的配置文件
<?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">

     <!--声明School对象-->
    <bean id="school" class="com.liar.ba03.School">
        <property name="name" value="清华大学"/>
        <property name="address" value="海淀区"/>
    </bean>
</beans>
  1. 主配置文件
<?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">
    <!--
     主配置文件:包含其他的配置文件的,主配置文件一般不定义对象.
     语法:<import resource="其他配置文件的路径"/>
     关键字:"classpath:"表示类路径(class文件所在的目录),在spring的配置文件中要指定其他文件的位置,
            需要使用classpath,告诉spring到哪去加载读取文件.
    -->
    <import resource="classpath:ba03/spring-school.xml"/>
    <import resource="classpath:ba03/spring-student.xml"/>
  
    <!--也可以使用通配符号
     注意:主配置文件名称不能包含在通配符范围内
    -->
    <import resource="classpath:ba03/spring-*.xml"/>
</beans>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值