Spring依赖注入基于XML的 DI

x33g5p2x  于2021-09-18 转载在 Spring  
字(11.4k)|赞(0)|评价(0)|浏览(330)

DI:给属性赋值

spring调用类的无参数构造方法,创建对象。 对象创建后给属性赋值。

给属性赋值可以使用 :

  1. xml配置文件中的标签和属性
  2. 使用注解

DI分类:

  1. set注入,也叫做设值注入
  2. 构造注入

set注入

public class Student {
	//姓名
    private String name;
    //年龄
    private int age;
	//无参构造器
    public Student() {
        System.out.println("Student无参数构造方法");
    }

    public void setName(String name) {
        System.out.println("setName==="+name);
        this.name = "Hello:"+name;
    }

    public void setAge(int age) {
        System.out.println("setAge=="+age);
        this.age = age;
    }

    public void setEmail(String email){
        //email属性 <property name="email" value="lisi@qq.com" />
        System.out.println("setEmail==="+email);
    }

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

定义一个Student类:
定义属性:name和age
生成它们的set方法
注意:上面没有定义属性email,只生成set方法(setEmail)
重写toString方法

定义applicationContext配置文件:

set注入

property用来绑定属性:name为要绑定的属性名称

set注入分为2种类型:普通类型和引用类型。

普通类型:java中的基本数据类型和String。
引用类型:除了基本数据类型其它都是引用类型(这里除了`String`)

普通类型赋值使用value=""
引用类型赋值使用ref=""

普通类型set注入

配置文件:

<?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-->
    
    <!--普通类型set注入-->
    <bean id="myStudent" class="com.bjpowernode.ba01.Student">
        <property name="name" value="李四"/><!--setName("李四")-->
        <property name="age" value="22" /><!--setAge(22)-->
        <property name="email" value="lisi@qq.com" /><!--setEmail("xxx)-->
    </bean>

    <!--声明日期类-->
    <!--这里绑定了time属性,会调用setTime()方法 Java Date类的setTime()方法设置日期对象。它将日期对象设置为代表格林尼治标准时间1970年1月1日00:00:00之后的时间毫秒。 用法: public void setTime(long time) 参数:该函数接受单个参数时间,该时间指定毫秒数。 -->
    <bean id="mydate" class="java.util.Date">
        <property name="time" value="933295249276"/><!--setTime()-->
    </bean>
</beans>

普通类型set注入语法:

set注入: spring调用类的set方法,通过set方法完成属性赋值
          简单类型的set注入:
          语法: <bean id="xxx" class="yyy">
                   <property name="属性名" value="简单类型属性值"/>
                   ...
                </bean>

定义测试类:

public class MyTest01 {

    @Test
    public void test01(){
    	//指定配置文件的名称和路径
        String config="applicationContext.xml";
        //获取spring容器对象
        ApplicationContext ctx  = new ClassPathXmlApplicationContext(config);
		//从容器中获取student自定义对象
        Student student = (Student) ctx.getBean("myStudent");
		//调用student的toString方法
        System.out.println("student="+student);
		//从容器中获取java提供的日期对象Date
        Date date = (Date) ctx.getBean("mydate");
        //打印日期
        System.out.println("date==="+date);
    }
}

分析打印顺序:

  1. 首先spring是通过调用类的无参构造器创建对象的,所以第一次打印的是Student类的无法构造方法
  2. 然后spring在进行set注入时,会调用属性对应的set方法,在调用的时候会把你的属性名首字母变为大写(如果属性首字母原本就是大写即字母不变),然后在前面加上set,这样就调用到属性对应的set方法。由于setName()和setAge()都是在做属性赋值和打印操作,setEmail()方法中只是做了打印操作,因为没有定义属性email,所以顺序2是做了setName、setEmail()、setEmail()中的打印操作
  3. 在测试类中打印了student对象,由于重写了toString方法,所以会调用student中的toString方法,做打印信息操作
  4. 最后是在测试类中打印了Date对象,由于Date对象的toString方法也被重写了,返回的是时间信息,所以最后一步打印的是时间信息

运行测试:

在这里插入图片描述

引用类型set注入

定义一个School类:
定义属性:普通类型name和address
生成它们的set方法
重写toString方法

public class School {

    private String name;
    private String address;

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

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

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

定义一个Student类:
定义属性:普通类型name和age,引用类型school
生成它们的set方法
注意:上面没有定义属性email,只生成set方法(setEmail)
重写toString方法

public class Student {

    private String name;
    private int age;
    //引用类型
    private School school;

    public Student() {
        System.out.println("Student无参数构造方法");
    }

    public void setName(String name) {
        System.out.println("setName==="+name);
        this.name = "Hello:"+name;
    }

    public void setAge(int age) {
        System.out.println("setAge=="+age);
        this.age = age;
    }

    public void setSchool(School school) {
        System.out.println("setSchool="+school);
        this.school = school;
    }

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

配置文件

<?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="mySchool" class="com.bjpowernode.ba02.School">
        <property name="name" value="北京大学"/>
        <property name="address" value="北京的海淀区"/>
    </bean>

    <!--引用类型set注入-->
    <bean id="myStudent" class="com.bjpowernode.ba02.Student">
        <property name="name" value="李四"/>
        <property name="age" value="22" />
        <!--引用类型的赋值-->
        <property name="school" ref="mySchool" /><!--setSchool(mySchool)-->
    </bean>
    
</beans>

引用数据类型set注入语法:

set注入:
          引用类型set注入:
          语法:<bean id="xxx" class="yyy">
                   <property name="属性名" ref="bean的id"/>
                   ...
                </bean>

定义测试类:

public class MyTest2(){
	@Test
    public void test01(){

        Student student = new Student();
        student.setName("lisi");
        student.setAge(20);

        School school = new School();
        school.setName("北京大学");
        school.setAddress("北京海淀区");

        student.setSchool(school);
    }

}

测试类:

  1. spring通过无参构造方法创建对象所以会走所有的无参构造器
  2. 由于student中的setName和setAge中有打印操作所以会打印姓名和年龄
  3. 最后打印了school对象,然后调用了toString方法,school对象也重写了toString方法,所以会打印school的属性name和address

运行结果:

在这里插入图片描述

构造注入

构造注入: Spring调用类的有参数构造方法,创建对象同时给属性赋值

语法:
    <bean id="xxx" class="yyy">
       <constructor-arg>: 表示一个构造方法的形参
       标签有属性: name :构造方法形参名
                   index:构造方法的参数位置
                   value:简单类型的形参值
                   ref:  引用类型的形参值

    </bean>

配置文件:

<?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-->
    <!-- 构造注入: Spring调用类的有参数构造方法,创建对象同时给属性赋值 语法: <bean id="xxx" class="yyy"> <constructor-arg>: 表示一个构造方法的形参 标签有属性: name :构造方法形参名 index:构造方法的参数位置 value:简单类型的形参值 ref: 引用类型的形参值 </bean> -->

    <!--构造注入,使用name属性-->
    <bean id="myStudent" class="com.bjpowernode.ba03.Student">
        <constructor-arg name="myage" value="22" />
        <constructor-arg name="myname" value="李四"/>
        <constructor-arg name="mySchool" ref="mySchool"/>
    </bean>

    <!--构造注入,使用index,参数的位置,构造方法参数从左往右位置是0,1,2-->
    <bean id="myStudent2" class="com.bjpowernode.ba03.Student">
        <constructor-arg index="1" value="28"/>
        <constructor-arg index="0" value="张三"/>
        <constructor-arg index="2" ref="mySchool" />
    </bean>

    <!--构造注入,省略index属性-->
    <bean id="myStudent3" class="com.bjpowernode.ba03.Student">
        <constructor-arg value="张峰"/>
        <constructor-arg value="28"/>
        <constructor-arg ref="mySchool" />
    </bean>

    <!--声明School-->
    <bean id="mySchool" class="com.bjpowernode.ba03.School">
        <property name="name" value="北京大学"/>
        <property name="address" value="北京的海淀区"/>
    </bean>

    <!--声明File对象-->
    <bean id="myFile" class="java.io.File">
        <constructor-arg name="parent" value="D:\\course"/>
        <constructor-arg name="child" value="2009班级网盘.txt" />
    </bean>

</beans>

引用类型自动注入

引用类型自动注入: spring根据byName,byType规则给引用类型赋值

byName注入:

1.byName(按名称注入):java类中引用类型的属性名称和spring容器中bean的id名称一样,且数据类型一样的, 这样的bean能够赋值给引用类型。
      语法:
       <bean id="xxx" class="yy" autowire="byName">
          简单类型属性赋值
       </bean>

配置文件:

<?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-->
    <!-- byName 自动注入 -->
    <bean id="myStudent" class="com.bjpowernode.ba04.Student" autowire="byName">
        <property name="name" value="李四"/>
        <property name="age" value="22" />
        <!--引用类型的赋值-->
        <!--<property name="school" ref="mySchool" />-->
    </bean>

    <!--声明School-->
    <bean id="school" class="com.bjpowernode.ba04.School">
        <property name="name" value="清华大学"/>
        <property name="address" value="北京的海淀区"/>
    </bean>

</beans>

byType注入:

2.byType(按类型注入):java类中引用类型的数据类型和bean的class是同源的,
                              这些的bean能够赋值给引用类型。

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

           语法:
           <bean id="xxx" class="yy" autowire="byType">
              简单类型属性赋值
           </bean>

           注意: 在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">

    <!--声明bean-->
    
    <!-- byType 自动注入 -->
    <bean id="myStudent" class="com.bjpowernode.ba05.Student" autowire="byType">
        <property name="name" value="张三"/>
        <property name="age" value="26" />
        <!--引用类型的赋值-->
        <!--<property name="school" ref="mySchool" />-->
    </bean>

    <!--声明School-->
    <bean id="mySchool" class="com.bjpowernode.ba05.School">
        <property name="name" value="航空大学"/>
        <property name="address" value="北京的海淀区"/>
    </bean>

    <!--声明School的子类-->
    <!--<bean id="primarySchool" class="com.bjpowernode.ba05.PrimarySchool"> <property name="name" value="北京大兴小学" /> <property name="address" value="北京的大兴区"/> </bean>-->

</beans>

为应用指定多个 Spring 配置文件

在实际应用里,随着应用规模的增加,系统中 Bean
数量也大量增加,导致配置文件变得非常庞大、臃肿。为了避免这种情况的产生,提高配置文件的可读性与可维护性,可以将 Spring
配置文件分解成多个配置文件。

包含关系的配置文件:

多个配置文件中有一个总文件,总配置文件将各其它子文件通过
import标签引入。在 Java 代码中只需要使用总配置文件对容器进行初始化即可。

举例:

在这里插入图片描述

语法:

当前是总的文件, 目的是包含其他的多个配置文件, 一般不声明bean
        语法:
        <import resource="classpath:其他文件的路径" />

        classpath:表示类路径。类文件所在的目录, spring通过类路径加载配置文件

通过import标签引入多个配置文件:

<import resource="classpath:ba06/spring-school.xml" />
<import resource="classpath:ba06/spring-student.xml" />

也可使用通配符/。但,此时要求父配置文件名不能满足//所能匹配的格式,否则将出现循环递归包含。就本例而言,父配置文件不能匹配 spring-/.xml 的格式,即不能起名为 spring-total.xml。

语法:

包含关系的配置文件,可使用通配符(*:表示任意字符)
        注意:总的文件名称,不能包含在通配符范围内(applicationContext.xml不能叫做
        spring-applicationContext.xml)

使用通配符/*引入多个配置文件:

<import resource="classpath:ba06/spring-*.xml" />

相关文章