IOC控制反转一对象属性赋值

di实现的语法有两种:

  1. spring配置文件完成,使用标签和属性
  2. 使用spring注解

di语法分类:

  1. set注入,spring调用set方法,在set方法中可以实现属性的赋值
  2. 构造注入,调用构造方法,创建对象

创建类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.zss.pojo;

/**
* @author zss
*/
public class Student {
String name;
Integer age;

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

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

set方法赋值

1
2
3
4
5
6
<!--spring规定Java对象的基本数据类型与String都是简单类型,下面的这种方法调用了set方法,哪怕你没有定义这个变量,但是写入的set方法,这样也会成功-->
而且不管这个类是不是我们自己定义的,比如系统的Date类,只要他有set方法,我们就可以赋值
<bean id="myStudent" class="com.zss.pojo.Student">
<property name="age" value="20"/>
<property name="name" value="里斯"/>
</bean>

测试

1
2
3
4
5
6
public static void main(String[] args) {
String config="applicationContext.xml";
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(config);
Student student= (Student) applicationContext.getBean("myStudent");
System.out.println(student);
}

image-20220503162615359

小插曲:Junit

单元测试,一个工具类库,做测试的使用,单元:指定的是方法,一个类中有很多方法,一个方法被称为单元

使用单元测试:

加入依赖

1
2
3
4
5
6
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>

创建一个测试类

在src/test/Java下面,创建测试方法,没有返回值,方法名称自定义,方法没有参数,并且拥有@test注解,这样的方法可以单独执行

image-20220503163340953

1
2
3
4
5
6
7
8
9
10
11
public class AppTest 
{
@Test
public void test01() {
String config = "applicationContext.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);
Student student = (Student) applicationContext.getBean("myStudent");
System.out.println(student);
}

}

引用类型赋值

现在student拥有除了拥有以上的信息外,还拥有一个school,而且school拥有名称和地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.zss.pojo;

public class School {
String name;
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 + '\'' +
'}';
}
}
1
2
3
4
5
6
7
8
9
<bean id="myStudent" class="com.zss.pojo.Student">
<property name="age" value="20"/>
<property name="name" value="里斯"/>
<property name="school" ref="school"/>
</bean>
<bean id="school" class="com.zss.pojo.School">
<property name="name" value="北京大中学"/>
<property name="address" value="北京"/>
</bean>

image-20220505084434943

构造方法赋值

1
2
3
4
5
<bean id="myStudent" class="com.zss.pojo.Student">
<constructor-arg name="name" value="张三"/>
<constructor-arg name="age" value="20"/>
<constructor-arg name="school" ref="school"/>
</bean>
1
2
3
4
5
public Student(String name, Integer age, School school) {
this.name = name;
this.age = age;
this.school = school;
}

顺序赋值

1
2
3
4
5
<bean id="myStudent" class="com.zss.pojo.Student">
<constructor-arg index="0" value="张三"/>
<constructor-arg index="1" value="20"/>
<constructor-arg index="2" ref="school"/>
</bean>

自动注入

前面的注入太麻烦,如果有多个值,就需要写很多行(此方法仅仅对引用类型有效

按照名称注入

Java的引用数据类型和spring的配置文件的id名称一致,数据类型一致可以自动赋值,此时student的school通过Name找到了id为school的类型,但是注意此时构造方法也要改变

1
2
3
4
5
6
7
8
<bean id="myStudent" class="com.zss.pojo.Student" autowire="byName">
<constructor-arg index="0" value="张三"/>
<constructor-arg index="1" value="20"/>
</bean>
<bean id="school" class="com.zss.pojo.School">
<property name="name" value="北京大中学"/>
<property name="address" value="北京"/>
</bean>

按照类型注入

Java中引用数据类型与spring容器中的的class属性关系同源,这样的bean能够赋值给引用数据类型,这一次匹配的是class,注意如果我们class为school的子类,也可以完成赋值操作,当然接口与接口的实现类也拥有这种关系

1
2
3
4
5
6
7
8
<bean id="myStudent" class="com.zss.pojo.Student" autowire="byType">
<constructor-arg index="0" value="张三"/>
<constructor-arg index="1" value="20"/>
</bean>
<bean id="myschool" class="com.zss.pojo.School">
<property name="name" value="北京大中学"/>
<property name="address" value="北京"/>
</bean>

多配置文件

  1. 每一个文件的大小比一个文件要小

  2. 避免多人竞争带来的冲突

    (一个模块配置一个文件或者按照类的功能(做事务的一个文件,做service一个配置文件))

    比如:

    spring-student

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?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.zss.pojo.Student" autowire="byType">
    <constructor-arg index="0" value="张三"/>
    <constructor-arg index="1" value="20"/>
    </bean>
    </beans>

spring-school

1
2
3
4
5
6
7
8
9
<?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="myschool" class="com.zss.pojo.School">
<property name="name" value="北京大中学"/>
<property name="address" value="北京"/>
</bean>
</beans>

spring-total

1
2
3
4
5
6
7
8
<?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:spring-student.xml"/>
<import resource="classpath:spring-school.xml"/>
</beans>

其实我们也可以使用通配符

,但是注意不同包含该文件,否则会一直循环读取