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>