IoC 概念
IoC (Inversion of Control)也称为依赖项注入(DI)。
控制反转是一个过程,在此过程中,对象仅通过 构造函数参数,工厂方法的参数或在构造或从工厂方法返回后在对象实例上设置的属性来定义其依赖项(即,与它们一起使用的其他对象) 。然后,容器在创建 Bean 时注入那些依赖项。此过程从根本上讲,是通过使用类的直接构造或诸如服务定位器模式之类的控件来控制其依赖项的实例化或位置的 bean 本身的逆过程(因此称为 Control Inversion)。
换言之:在使用对象时,原本由主动 new 产生对象 改为使用由==外部==提供对象,此过程中对象创建控制权由程序转移到==外部==,此思想称为控制反转。
org.springframework.beans
和 org.springframework.context
两个包是 Spring Framework 的 IoC 容器的基础。 BeanFactory接口提供了一种高级配置机制,能够管理任何类型的对象。
ApplicationContext 是 BeanFactory的子接口。它增加了:
- 更容易与 Spring 的 AOP 功能集成
- 消息资源处理(用于国际化)
- 事件发布:Event publication
- 特定于应用程序层的上下文,例如用于 Web 应用程序的
WebApplicationContext
。
简而言之,BeanFactory
提供了配置框架和基本功能,而 ApplicationContext
添加了更多企业特定的功能。 ApplicationContext
是 BeanFactory
的完整超集。
在 Spring 中,构成应用程序主干并由 Spring IoC 容器管理的对象称为 Bean。 Bean 是由 Spring IoC 容器实例化,组装和以其他方式管理的对象。否则,bean 仅仅是应用程序中许多对象之一。 Bean 及其之间的依赖关系反映在容器使用的配置元数据中。
IoC 容器
org.springframework.context.ApplicationContext
接口代表 Spring IoC 容器,并负责实例化,配置和组装 Bean。容器通过读取配置元数据来获取有关要实例化,配置和组装哪些对象的指令。配置元数据以 XML,Java 注解或 Java 代码表示。它使您能够表达组成应用程序的对象以及这些对象之间的丰富相互依赖关系。
Spring 提供了ApplicationContext
接口的几种实现。在独立应用程序中,通常创建ClassPathXmlApplicationContext
或FileSystemXmlApplicationContext
的实例。尽管 XML 是定义配置元数据的传统格式,但是您可以通过提供少量 XML 配置来声明性地启用对这些其他元数据格式的支持,从而指示容器将 Java 注解或代码用作元数据格式。
在大多数应用场景中,不需要实例化用户代码即可实例化一个 Spring IoC 容器的一个或多个实例。例如,在 Web 应用程序场景中,应用程序 web.xml
文件中的大约简单的八行模板 WebDescriptorsXML
通常就足够了。如果使用Spring 工具套件(如基于 Eclipse、IDEA 的开发环境),则只需单击几次鼠标或击键即可创建此配置。
下图显示了 Spring 的工作原理的高级视图。项目中的应用程序类与配置元数据结合在一起,以便在创建和初始化ApplicationContext
之后,获取完全配置且可执行的系统或应用程序。
IoC 入门案例(XML)
一、导入 Spring 坐标
pom.xml
xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.13.RELEASE</version>
</dependency>
二、定义 Spring 管理的类(接口)
Service 接口
java
public interface BookService {
public void save();
}
Service 实现
java
public class BookServiceImpl implements BookService {
private BookDao bookDao = new BookDaoImpl();
public void save() {
bookDao.save();
}
}
三、创建 Spring 配置文件
*resources/applicationContext.xml
- bean 标签表示配置一个 bean
- id 属性表示给 bean 名字
- class 属性表示给 bean 定义类型
bean 定义时 id 属性在同一个上下文中不能重复
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 -->
<bean id="bookDao" class="cn.pangcy.dao.impl.BookDaoImpl" />
<bean id="bookService" class="cn.pangcy.service.impl.BookServiceImpl" />
</beans>
四、初始化 IoC 容器
App 启动类
- 通过 new ClassPathXmlApplicationContext 获取容器对象
- 通过 ctx.getBean("bean Id") 获取对象
通过 getBean 获取的返回值是 Object 对象,需要强制转一下类型
java
public class App {
public static void main(String[] args) {
// 加载配置文件获取上下文对象,也就是容器对象
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取资源
BookService bookServcice = (BookService) ctx.getBean("bookService");
bookService.save();
}
}
一、提供依赖对象对应的 setter 方法
声明依赖对象 BookDao, 并抛出外部赋值方法 setBookDao 提供给 Spring IoC 容器进行依赖注入
java
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void save() {
bookDao.save();
}
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
二、配置 service 与 dao 之间的关系
创建了 bookDao 与 bookService 后,两者之间没有关系,所以 Spring 也不会自动注入依赖。
在 bookService 中添加 property 标签,建立 bookService 下的依赖关系
- property 标签表示配置当前依赖的 bean
- name 是 bookService 中声明的属性名,即抛出的 setter 方法的属性
- ref 是指定了引用哪一个 bean, 这里的值是 bean 的Id, 如下,这里指定的是 bookDao 的 bean Id
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 -->
<bean id="bookDao" class="cn.pangcy.dao.impl.BookDaoImpl" />
<bean id="bookService" class="cn.pangcy.service.impl.BookServiceImpl">
<!-- 配置依赖关系 -->
<property name="bookDao" ref="bookDao"/>
</bean>
</beans>