Spring 学习总结笔记【二、IoC-控制反转】

往期文章:

Spring 学习总结笔记【一、快速入门】

一、IoC是什么

Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。

  • 谁控制谁,控制什么
    传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建;谁控制谁?当然是IoC
    容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。

  • 为何是反转,哪些方面反转了
    有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

二、IoC案例引入

① 我们先写一个UserDao接口

public interface UserDao {
	public void getUser();
}

② 再写UserDao的实现类-UserDaoImpl

public class UserDaoImpl implements UserDao {
	@Override
	public void getUser() {
		System.out.println("获取用户数据...");
	}
}

③ 写一个UserService接口

public interface UserService {
	public void getUser();
}

④ 最后写一个UserService的实现类-UserServiceImpl

public class UserServiceImpl implements UserService {
	private UserDao userDao = new UserDaoImpl();
	@Override
	public void getUser() {
		userDao.getUser();
	}
}

⑤ 现在来获取用户数据吧

@Test
public void testGetUser(){
	UserService userService = new UserServiceImpl();
	userService .getUser();
}

这也是大家惯用的方式,现在我们对其做出一些修改。
将UserDao的实现类增加一个

public class UserDaoMySqlImpl implements UserDao {
	@Override
	public void getUser() {
		System.out.println("MySql获取用户数据...");
	}
}

紧接着我们要去使用MySql的话 , 我们就需要去service实现类里面修改对应的实

public class UserServiceImpl implements UserService {
	private UserDao userDao = new UserDaoMySqlImpl();
	@Override
	public void getUser() {
		userDao.getUser();
	}
}

如果我们再增加一个UserDao的实现类,使用oracle存储数据,那么我们又要去UserService
类里更改对应实例的获取。在开发中,这种需求是非常大的 ,因此我们惯用的方式有点不适用了, 甚至反人类。 每次变动 , 都需要修改大量代码 , 这种设计的耦合性太高, 牵一发而动全身 。

解决方案
我们可以在需要用到某个实例的地方 , 不去实现它 , 而是留出一个接口 , 利用set , 我们去代码里修改下 。

public class UserServiceImpl implements UserService {
	private UserDao userDao;
	
	// 利用set实现
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
	
	@Override
	public void getUser() {
		userDao.getUser();
	}
}

这样一来,他们已经发生了根本性的变化,很多地方都不一样了。仔细去思考一下,以前所有东西都是由程序去进行控制创建, 而现在是由我们自行控制创建对象,把主动权交给了调用者。 程序不用去管怎么创建,怎么实现了。它只负责提供一个接口。

这种思想, 从本质上解决了问题,我们程序员不再去管理对象的创建了, 更多的去关注业务的实现。耦合性大大降低。这也就是IOC的原型 !

三、IoC与DI

控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,耦合性极高。但控制反转后将对象的创建转移给第三方,降低了程序间的耦合性,在我看来,控制反转就是获得依赖对象的方式反转了。
IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,以及可以基于Java配置类实现完全脱离xml配置文件实现IoC。

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(DependencyInjection,DI)。

四、 Spring中的IoC与DI

回到上述案例,我们最终用setter方法解决了程序的耦合性,在Spring中,我们只需在Spring核心配置文件中使用<bean>标签注册每一个类,标签里添加对应属性,就可以实现对象的创建。

<?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="mysqlUserDao" class="com.tyt.dao.impl.UserDaoMySqlImpl"/>
   <bean id="oracleUserDao" class="com.tyt.dao.impl.UserDaoOracleImpl"/>

   <bean id="userService" class="com.tyt.service.impl.UserServiceImpl">
       <!--引用 UserDaoMySqlImpl-->
       <property name="userDao" ref="mysqlUserDao"/>
       <!--如果想引用 UserDaoOracleImpl,只需将代码改为这一句-->
       <!--
       <property name="userDao" ref="oracleUserDao"/>
       -->
   </bean>
</beans>

测试:

public void test(){
	ApplicationContext app= new ClassPathXmlApplicationContext("applicationContext.xml");
	UserService userService = (UserService )app.getBean("userService");
	userService.getUser();
}
  • UserService 对象是谁创建的 ?
    UserService 对象是由Spring创建的

  • UserService 对象的属性是怎么设置的 ?
    UserService 对象的属性是由Spring容器设置的

对象已经转交给Spring控制了,这就叫控制反转;属性的设置也交给Spring设置了,这就是依赖注入

  • 控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 ;使用Spring后 , 对象是由Spring来创建的

  • 反转 : 程序本身不创建对象 , 而变成被动的接收对象 .

  • 依赖注入 : 就是利用set方法来进行注入的.

下期文章:

Spring 学习总结笔记【三、注解开发】

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值