IoC(Inversion of Control) 控制反转

在之前MVC开发架构的学习中,业务层实现需要调用数据层接口实现类,如果想改变实现方式,需要更改业务层代码,这就导致代码耦合度偏高。

为了解决这个问题,就有了IoC设计思想。

IoC思想,也就是在使用对象时,在程序中不主动使用new产生对象,改为外部提供对象。对象的创建控制权由程序转移到外部,这就是控制反转思想。

Spring实现了IoC思想,提供了一个容器,称为IoC容器,充当IoC思想的“外部”,被管理的对象称作Bean。

DI(Dependency Injection)依赖注入

IoC思想的合理实现方法就是DI。

在Spring的IoC容器中如果两个对象间有依赖关系,则容器会帮助建立关系,称为依赖注入。

例如Service对象依赖Dao对象,那么我们只需要在Spring xml文件中配置好关系,使用对象时不仅会帮助获取到Bean,还会自动绑定所有关系。

IoC案例

导包

1
2
3
4
5
6
7
8
<!--导入Spring的坐标-->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>

在resources中创建Spring Config XML文件并配置bean

1
2
3
<!--id为bean的名字,class表示bean的定义类-->
<bean id="bookDao" class="dao.impl.BookDaoImpl"/>
<bean id="bookService" class="service.impl.BookServiceImpl"/>

初始化IoC容器,通过容器获取Bean

1
2
3
4
5
//        获取IoC容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取Bean 需要转型
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
BookService bookService = (BookService) ctx.getBean("bookService");

DI案例

为了解耦,Service中不应再有new出来的Dao对象,我们需要一个描述Service与Dao之间关系的方法,即set方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class BookServiceImpl implements BookService {
// 删除new出来的Dao对象
// private BookDao bookDao = new BookDaoImpl();
private BookDao bookDao;
@Override
public void save() {
System.out.println("book service save...");
bookDao.save();
}

// 提供对应的set方法
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}

再在XML文件中配置Bean,需要注意的是,ref属性指的是参照哪一个Bean,name属性表示配置进当前Bean对象中的属性。

1
2
3
4
5
6
7
8
9
<!--id为bean的名字,class表示bean的定义类-->
<bean id="bookDao" class="dao.impl.BookDaoImpl"/>

<bean id="bookService" class="service.impl.BookServiceImpl">
<!--property标签表示配置当前bean的属性
name属性表示配置哪一个具体的属性
ref属性表示参照哪一个bean-->
<property name="bookDao" ref="bookDao"></property>
</bean>

之后在App中即可直接调用Service完成功能实现。

1
2
3
4
5
6
7
8
9
10
public class App {
public static void main(String[] args) {
// 获取IoC容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取Bean 需要转型
BookService bookService = (BookService) ctx.getBean("bookService");

bookService.save();
}
}