目录
一、概念及原理
1、什么是 IOC
2、原理
二、IOC 操作——Bean 管理
1、什么是 Bean 管理
2、Bean 管理操作有两种方式
3、基于 xml 方式创建对象
三、xml 方式注入普通类型属性
1、使用 set 方法注入
2、使用有参构造函数注入
四、xml 方式注入其他类型属性
1、注入字面量
2、注入外部 Bean
3、注入内部 Bean 和级联赋值
五、xml 方式注入集合类型属性
1、注入数组、List 、Map、 Set 集合类型属性
2、在集合内设置对象类型
3、抽取公共属性值
(1)控制反转(Inversion of Control),把对象创建(new)和对象之间的调用(.function()),交给 Spring 管理;
(2)使用 IOC 的目的:降低耦合度;
(3)IOC 底层原理:xml 解析、工厂模式、反射;
Class 之间的调用形式决定了耦合度的高低,从原始方式到工厂模式到IOC,耦合度做到了越来越低。
(1)原始方式
假如我们现在要编写一个 Dao 和 Service,但是我们不懂任何设计模式,于是做出了在 Service 方法中 new Dao 的操作。如果 Dao 代码更变,那么 Service 也得跟着改变,耦合度较高。
(2)工厂模式
使用一个中间类,写一个 static 方法获取 Dao 对象,然后 Service 调用这个方法获取 Dao 对象,这样可以降低 Service 和 Dao 的耦合度。
虽然产生了 Factory 和 Dao 的耦合,但耦合程度比原始方式低。
(3)IOC 容器底层
IOC 分两步,进一步降低耦合度,降低到最低限度,这样我们只需要修改配置文件即可。
(4)IOC 接口
(4-1)IOC 思想基于 IOC 容器完成,IOC 容器底层就是对象工厂;
(4-2)Spring 提供 IOC 容器实现两种方式(接口):
(4-3)特点:
(4-4)实现类:
是指两种操作:创建对象、属性注入。
(1)Spring 创建对象;
(2)Spring 属性注入
(1)基于 xml 配置文件方式实现
(2)基于注解方式实现
在 xml 中使用 bean 标签,添加对应属性,就可以实现创建对象。
(1)属性
(2)创建对象时,默认执行无参构造方法
DI:依赖注入,就是注入属性。
在 Spring 中,支持两种注入方式:有参构造和 set 方法。
(1)创建类,定义属性和对应的 set 方法
package com.demo.pojo;
public class Book {
private Integer id;
private String name;
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
}
(2)在 spring 配置文件配置对象创建,配置属性注入
在
(3)测试代码
这里是把 bean.xml 放到了 resources 文件夹下,并且标记为了源代码根目录。
import com.demo.pojo.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BookTest {
@Test
public void testCreate() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Book book = context.getBean(Book.class);
System.out.println(book.getId() + " " + book.getName());
}
}
有参构造注入与 set 方法注入的区别仅在于
(1)创建类,定义属性,创建属性对应有参数构造方法
package com.demo.pojo;
public class Order {
private String name;
private String address;
public String getName() {
return name;
}
public String getAddress() {
return address;
}
public Order(String name, String address) {
this.name = name;
this.address = address;
}
}
(2)在 spring 配置文件中进行配置
写完
(3)测试代码
import com.demo.pojo.Order;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class OrderTest {
@Test
public void testOrder() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Order order = context.getBean("order", Order.class);
System.out.println(order.getName() + " " + order.getAddress());
}
}
字面量就是一些常量。比如 private String s = "123"。
(1)null 值
给 Book 类添加一个属性 price,并且将其设置为 null。
(2)属性值包含特殊符号
把 Book 类的 name 属性值,加上 << >>(不是书名号,是两个大于、小于)。可以考虑使用 xml 提供的 CDATA
>]]>
(1)创建两个类 Service 类和 Dao 类
(1-1)UserService 类:
package com.demo.service.impl;
import com.demo.dao.UserDao;
import com.demo.service.UserService;
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void func() {
System.out.println("调用 UserService 的 func");
userDao.func();
}
}
(1-2)UserDao 类:
package com.demo.dao.impl;
import com.demo.dao.UserDao;
public class UserDaoImpl implements UserDao {
@Override
public void func() {
System.out.println("调用 UserDao 的 func");
}
}
(2)在 spring 配置文件中进行配置
为 userService 注入 userDao 对象:
(3)测试代码
import com.demo.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserServiceTest {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("Service-Dao-Bean.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.func();
}
}
(4)输出结果
数据库的表与表之间有一对一、一对多、多对一的关系,内部 Bean 和级联赋值就是处理这种数据的。其中主要关注一下级联赋值,因为内部 Bean 和外部 Bean 纯粹只是 xml 内的一点写法区别。
下面用一对多关系,部门与员工(1:n),来做个例子。
(1)Department 类和 Empolyee 类:
package com.demo.pojo;
public class Department {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.demo.pojo;
public class Employee {
private String name;
private String gender;
// 一个员工属于某一个部门
private Department department;
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
(2)Dep-Emp-Bean.xml:
在
其实我们发现,只要给对象类型的
而这其实就是级联赋值的第一种写法:
(3)测试代码:
import com.demo.pojo.Employee;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DepEmpTest {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("Dep-Emp-Bean.xml");
Employee employee = context.getBean("employee", Employee.class);
System.out.println(employee.getName() + " "
+ employee.getGender() + " "
+ employee.getDepartment().getName());
}
}
(4)输出结果:
(5)级联赋值的第二种写法
本质上就是先通过 ref 连接 department 对象,然后通过 getName() 方法获取 department 的 name 属性。(反射无处不在)
(6)输出结果
(1)创建类,定义数组、list、map、set 类型属性,生成对应 set 方法
package com.demo.pojo;
import java.util.*;
public class Student {
private String[] courses;
private List list;
private Map map;
private Set set;
public Set getSet() {
return set;
}
public void setSet(Set set) {
this.set = set;
}
public String[] getCourses() {
return courses;
}
public void setCourses(String[] courses) {
this.courses = courses;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
}
(2)在 spring 配置文件进行配置
对于每一种不同的集合,都有相对应的标签可以使用,在其对应的标签内添加
Java编程
Sql教学
list01
list02
set01
set02
(3)测试代码
import com.demo.pojo.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Arrays;
public class SetBeanTest {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("SetBean.xml");
Student student = context.getBean("student", Student.class);
System.out.println(Arrays.toString(student.getCourses()));
System.out.println(student.getList());
System.out.println(student.getMap());
System.out.println(student.getSet());
}
}
(4)输出结果
集合内保存的一般都是某些自定义的对象类型,所以需要知道如何注入对象到集合类型。
(1)Teacher 类和 Course 类
package com.demo.pojo;
import java.util.List;
public class Teacher {
private List courseList;
public List getCourseList() {
return courseList;
}
public void setCourseList(List courseList) {
this.courseList = courseList;
}
}
package com.demo.pojo;
public class Course {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Course{" +
"name='" + name + '\'' +
'}';
}
}
(2)SetObjectBean.xml
使用 的 bean 属性来链接外部 Bean,实现将对象类型属性值注入到 List(Map、Set、……)集合。
(3)测试代码
import com.demo.pojo.Teacher;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SetObjectBeanTest {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("SetObjectBean.xml");
Teacher teacher = context.getBean("teacher", Teacher.class);
System.out.println(teacher.getCourseList());
}
}
(4)输出结果
(1)在 spring 配置文件中引入名称空间 util
先添加名称空间,然后把 xsi 的值复制一份,紧接着后面粘贴上,把复制来的 beans 都改成 util。
(2)使用 util 标签完成 list 集合注入提取
其他类型的集合,输入 util: 会有提示。
Java
C++
Python
(3)ProgramLanguage 类:
package com.demo.pojo;
import java.util.List;
public class ProgramLanguage {
private List list;
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
}
(4)测试代码
import com.demo.pojo.ProgramLanguage;
import com.demo.pojo.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class commonTest {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("common.xml");
ProgramLanguage programLanguage = context.getBean("list", ProgramLanguage.class);
System.out.println(programLanguage.getList());
}
}
(5)输出结果