属性注入
在Java开发中给属性赋值的常规手段有两种:
- 通过set方法赋值
Student student = new Student();
student.setName("小明");
- 通过构造器赋值
Worker worker = new Worker("张三", 20);
set方法注入
代码部分:
Student.java
/**
* 学生类,用于演示属性注入
* @author Katrina
*
*/
public class Student {
/*
* 一个类中若不添加构造方法,该类会有默认的无参构造方法(在顶级父类Object内)
*/
private String name;
/**
* 有参构造函数
* @param studentName 学生的姓名
*/
public Student(String studentName) {
this.name = studentName;
}
/**
* 无参构造方法 -> 默认构造方法
*/
public Student() {
System.out.println("无参构造方法被调用了");
}
public String getName() {
return name;
}
//如果注释掉,报错
public void setName(String name) {
this.name = name;
System.out.println("student的set方法被调用");
}
}
student-config.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">
<!-- 注入学生类 -->
<!-- 验证路径是否正确:按住Ctrl鼠标放上去,可跳转 -->
<!--
相当于:Student student = new Student();
student.setName("小明");
set方法注入的注意事项:
1.需要注入的属性必须有set方法,没有set方法无法注入
2.需要由默认的无参构造方法,没有则会报错
-->
<bean class="property.Student" id="student">
<property name="name" value="小明"></property>
</bean>
</beans>
StudentTest.java
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 学生测试类,用于测试属性注入
* @author Katrina
*
*/
public class StudentTest {
public static void main(String[] args) {
//1.获取容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("student-config.xml");
//2.获取类并操作
Student student = (Student) context.getBean("student");
System.out.println(student.getName());
//3.关闭容器
context.close();
}
}
效果图:
构造器注入
1.注入方式是:通过“构造器”给实例的属性赋值
2.使用注意事项
2.1必须要有指定构造器,否则会调用构造器失败出现错误
2.2使用时,constructor-arg标签的name属性指向的是构造器中参数的名称
3.使用方式
3.1constructor-arg标签的name属性指定值进行注入
3.2constructor-arg标签的index属性指定指定位置的参数注入,注意index的下标从0开始
4.注入值
4.1单值注入:
4.1.2直接量的单值:value属性进行赋值
4.1.3引用类型的单值:ref属性进行赋值
4.2多值注入:array、list、set、map
代码部分:
Worker.java
import java.util.Map;
import java.util.Map.Entry;
/**
* 工人类,用于演示构造器注入
* @author Katrina
*
*/
public class Worker {
private String name;
private int age;
private Mobile mobile;
private Map<String, String> income;
//数组的属性、list的属性、set属性
/**
* 含有map的构造方法
* @param income 收入
*/
public Worker(Map<String, String> income) {
this.income = income;
}
/**
* 含有引用类型的构造方法
* @param name 姓名
* @param age 年龄
* @param mobile 手机
*/
public Worker(String name, int age, Mobile mobile) {
this.name = name;
this.age = age;
this.mobile = mobile;
}
/**
* 有参构造函数
* @param name 姓名
*/
public Worker(String workerName) {
System.out.println("worker的构造方法被调用");
System.out.println("worker传入的name是:" + workerName);
this.name = workerName;
}
/**
* 多个参数的构造函数
* @param name 姓名
* @param age 年龄
*/
public Worker(String name, int age) {
System.out.println("worker的两个参数的构造方法被调用了");
this.name = name;
this.age = age;
}
/**
* 打印工人信息
*/
public void printInfo() {
// System.out.println("工人的姓名:" + name + ",工人的年龄是:" + age);
System.out.println("工人的姓名:" + name + ",工人的年龄是:" + age + ",手机品牌是:" + mobile.getName());
}
/**
* 打印工人的收入
*/
public void printIncome() {
for (Entry<String, String> entry : income.entrySet()) {
System.out.println("收入方式是:" + entry.getKey() + ",收入金额是:" + entry.getValue());
}
}
}
Mobile.java
/**
* 手机类
* @author Katrina
*
*/
public class Mobile {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
worker-config.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">
<!-- 注入工人类 -->
<!--
执行的代码相当于:Worker worker = new Worker("李四");
构造器注入的注意事项:
1.要有匹配的构造器方法
2.constructor-arg的name属性指向的是参数的名字,要与参数名字保持一致
-->
<!--
<bean class="constructor.Worker" id="worker">
构造器注入
<constructor-arg name="workerName" value="李四"></constructor-arg>
</bean>
<bean class="constructor.Worker" id="worker1">
构造器注入
<constructor-arg name="name" value="王五"></constructor-arg> 一个标签就是给一个参数赋值
<constructor-arg name="age" value="26"></constructor-arg>
</bean>
-->
<!--
<bean class="constructor.Worker" id="worker2">
<constructor-arg index="0" value="赵柳"></constructor-arg>
<constructor-arg index="1" value="30"></constructor-arg>
</bean>
-->
<!--
<bean id="mobile" class="constructor.Mobile">
<property name="name" value="华为"></property>
</bean>
<bean id="worker3" class="constructor.Worker">
<constructor-arg name="name" value="小明"></constructor-arg>
<constructor-arg name="age" value="20"></constructor-arg>
<constructor-arg name="mobile" ref="mobile"></constructor-arg> 关联的类必须是已经注入到容器中的类,例如:Mobile
</bean>
-->
<!-- map构造器注入 -->
<bean id="worker4" class="constructor.Worker">
<constructor-arg name="income">
<map>
<entry key="兼职" value="1000"></entry>
<entry key="工资" value="2000"></entry>
</map>
</constructor-arg>
</bean>
</beans>
WorkerTest.java
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 工人测试类,用于演示构造器注入
* @author Katrina
*
*/
public class WorkerTest {
public static void main(String[] args) {
//1.获取容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("worker-config.xml");
//2.获取类并测试
// Worker worker = (Worker) context.getBean("worker");
// Worker worker1 = (Worker) context.getBean("worker1");
// worker1.printInfo();
// Worker worker2 = (Worker) context.getBean("worker2");
// worker2.printInfo();
// Worker worker3 = (Worker) context.getBean("worker3");
// worker3.printInfo();
Worker worker4 = (Worker) context.getBean("worker4");
worker4.printIncome();
//3.关闭容器
context.close();
}
}
效果图:
part1:
注意:为什么前两句话仍然会显示在控制台上?
解释:只要在容器中注入实例,在Test代码中使用ClassPathXmlApplicationContext就会被创建出来
part2:
part3:
part4:
注意:修改worker-config.xml及Worker.java实现效果图
junit测试
1.使用步骤:
1.1引入jar包
1.2编写测试单元:注意方法是无参数无返回值public的方法
2.常用注解
2.1@Before:在测试单元运行之前执行的
2.2@Test:测试单元,只有使用@Test标注的方法才是测试单元
2.3@After:在测试单元完成之后运行的
引入的jar包,如图所示:
注意:使用junit,而junit依赖hamcrest-core-1.3
bean标签
bean标签的常用属性:
1.class:指向要注入实例的类的全路径
2.id:注入的实例在容器中的表示
3.init-method(初始化方法):值为方法的名字,在实例创建出来以后自动调用初始化的方法
4.destroy-method(销毁方法):值为方法的名字,在实例被销毁的时候调用
5.lazy-init(懒加载):值为true和false,默认为false,实例在容器初始化的时候并不创建,在使用到的时候才会创建
代码部分:
Demo.java
/**
* demo类,用于演示bean的属性
* @author Katrina
*
*/
public class Demo {
public Demo() {
System.out.println("Demo构造方法被调用了");
}
/**
* 初始化方法
*/
public void initMethod() {
System.out.println("Demo初始化方法被调用了");
}
/**
* 销毁方法
*/
public void destroyMethod() {
System.out.println("Demo销毁方法被调用了");
}
}
demo-config.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标签的属性:
destroy-method:销毁方法,值为类中方法的名字
init-method:初始化方法,值为类中方法的名字
lay-init:懒加载,默认值是false,容器创建时并不创建实例,只有当调用的时候才会创建
-->
<!-- 演示初始化方法和销毁方法 -->
<!-- <bean id="demo" class="bean.Demo" destroy-method="destroyMethod" init-method="initMethod"></bean> -->
<!-- 演示懒加载 -->
<bean id="demo1" class="bean.Demo" lazy-init="false"></bean>
</beans>
DemoTest.java
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* demo测试类,用于演示bean的属性
* @author Katrina
*
*/
public class DemoTest {
private ClassPathXmlApplicationContext context;
@Before
public void beforeTest() {
//1.创建容器
context = new ClassPathXmlApplicationContext("demo-config.xml");
}
@After
public void afterTest() {
//3.关闭容器
context.close();
}
/**
* 定义一个无参数无返回值的public方法
*/
@Test
public void text1() {
//2.获取类并测试
// Demo demo = (Demo) context.getBean("demo");
// Demo demo = (Demo) context.getBean("demo1"); //这一句并不是创建,这一句是从容器中取用
}
}
效果图:
在test1上右击选择JUnit Test
part1:
part2:
part3:
part4:
注意:修改demo-config.xml实现效果图