> 文章列表 > Spring核心容器(一) | IoC和DI快速入门

Spring核心容器(一) | IoC和DI快速入门

Spring核心容器(一) | IoC和DI快速入门

文章目录

  • Core Container核心容器
    • 核心概念
    • 创建容器
    • Ioc快速入门
    • DI快速入门

Core Container核心容器

核心概念

一个概念的提出往往是为了解决一些问题的, 那么我们现在编写的代码存在什么样的问题呢? 我们看下面一段代码:

有如下一段业务层的代码: 创建一个数据层BookDaoImpl2的对象, 并调用该对象的save方法

public class BookServiceImpl implements BookService {private BookDao bookDao = new BookDaoImpl1();public void save() {bookDao.save();}
}

数据层实现代码:

public class BookDaoImpl implements BookDao {public void save() {System.out.println("book dao save ...");}
}

如果我们此时想要换一套如下代码的全新数据层的实现, 那么业务层中的new BookDaoImpl1()需要换成new BookDaoImpl2()

public class BookDaoImpl2 implements BookDao {public void save() {System.out.println("book dao save ...2");}
}

现在书写代码带来的问题就是, 耦合度偏高; 而我们程序的书写追求的是低耦合

解决方案:

使用对象时,在程序中不要主动使用new产生对象,转换为由外部提供对象, 而这种思想就是IoC(Inversion of Control) 控制反转

IoC (Inversion of Control) 控制反转:

使用对象时,由主动new产生对象, 转换为由外部提供对象; 对象的创建控制权由程序转移到外部,这种思想称为控制反转

Spring技术对IoC思想进行了实现:

Spring提供了一个容器,称为IoC容器,用来充当IoC思想中的 “外部”

IoC容器负责对象的创建、初始化等一系列工作,被IoC容器创建或管理的对象在IoC容器中统称为Bean

DI (Dependency Injection) 依赖注入:

在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入;

例如某一个bean需要作为对象给其他的bean使用

最终目标: 充分解耦:

步骤一: 使用IoC容器管理bean(IoC)

步骤二: 在IoC容器内将有依赖关系的bean进行关系绑定(DI)

最新效果: 使用对象时不仅可以直接从IoC容器中获取,并且获取到的bean已经绑定了所有的依赖关系

创建容器

创建容器的方式:

方式一:类路径加载配置文件

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

方式二:文件绝对路径路径加载配置文件

ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\\\applicationContext.xml");

不管使用哪种方式, 都可以加载多个配置文件

ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml", "bean2.xml");

容器类层次结构图如下:

BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载

ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载

ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能

ApplicationContext接口常用初始化类

  • ClassPathXmlApplicationContext
  • FileSystemXmlApplicationContext

在这里插入图片描述

Ioc快速入门

我们通过案例快速入门IoC(XML版), 案例的准备工作如下

案例的目录结构如下

在这里插入图片描述

BookDao接口和BookDaoImpl实现类代码如下

public interface BookDao {void save();
}
public class BookDaoImpl implements BookDao {public void save() {System.out.println("book dao save...");}
}

BookService接口和BookServiceImpl实现类代码如下

public interface BookService {void save();
}
public class BookServiceImpl implements BookService {private BookDao bookDao = new BookDaoImpl();public void save() {System.out.println("book service save");// 调用BookDaoImpl中的方法bookDao.save();}
}

有一个App类调用BookServiceImpl的实例方法

public class App {public static void main(String[] args) {BookService bookService = new BookServiceImpl();bookService.save();}
}

IoC入门案例思路分析:

导入使用Spring的依赖坐标(pom.xml)

此案例中我们需要IoC管理Service和Dao

通过配置方式, 将被管理的对象告知IoC容器

被管理的对象交给IoC容器后,我们可以通过接口获取到IoC容器

IoC容器得到后,通过接口方法从容器中获取bean

IoC入门案例实现(XML版):

在pom.xml文件中导入Spring坐标

<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.10.RELEASE</version>
</dependency>

在resource文件夹中创建一个Spring的配置文件applicationContext.xml,配置对应类作为Spring管理的bean

  • 注意: bean定义时id属性在同一个上下文中不能重复
<?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属性表示给bean取名字--><!--class属性表示给bean定类型--><bean id="bookService" class="com.chenyq.service.impl.BookServiceImpl"/></beans>

初始化IoC容器(Spring核心容器/Spring容器),通过容器获取bean

public class App {public static void main(String[] args) {// 获取IoC容器, 参数是Spring配置文件名ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");// 获取bean, 通过getbean方法BookService bookService = (BookService) ctx.getBean("bookService");bookService.save();}
}

DI快速入门

在上面IoC案例中, 我们业务层其实还是没有解耦的:

在BookServiceImpl类的save方法中还是使用的new BookDao的形式创建的对象

DI入门案例思路分析(XML版):

DI是基于IoC管理bean

Service中使用new创建的Dao对象的形式不保留, 需要通过DI解耦

Service中需要的Dao对象, 需要通过提供方法的方式, 让Dao对象进入到Service中

Service与Dao间的关系需要 描述通过配置文件描述

DI入门案例实现(XML版):

删除使用new的形式创建对象的代码

public class BookServiceImpl implements BookService {// private BookDao bookDao = new BookDaoImpl();private BookDao bookDao; // 不使用new形式创建对象public void save() {bookDao.save();}
}

提供依赖对象对应的setter方法, 该setter方法是容器调用的

public class BookServiceImpl implements BookService {private BookDao bookDao;public void save() {System.out.println("book service save");bookDao.save();}// 提供setter方法public void setBookDao(BookDao bookDao) {this.bookDao = bookDao;}
}

配置service与dao之间的关系

<?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属性表示给bean取名字--><!--class属性表示给bean定类型--><bean id="bookDao" class="com.chenyq.dao.impl.BookDaoImpl"/><bean id="bookService" class="com.chenyq.service.impl.BookServiceImpl"><!--配置Service和Dao的关系, property标签标识当前bean的属性--><!--name属性表示配置当前bean的哪一个属性--><!--ref属性表示配置参照哪一个bean--><property name="bookDao" ref="bookDao"/></bean></beans>