一. 简介
对于刚接触Spring的小伙伴肯定对ioc这个名词有很大的困惑。当你在百度搜索什么是ioc的时候,这是百度词条的解释:
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。
那么IOC是个什么鬼?? 它又怎么可以降低代码之间的耦合度呢?
本文就将带你从最基本的案例一步一步的了解IOC是怎么解决此项问题的。
小伙伴请打开idea 来一起尝试下吧!
二. 案例一:耦合度很高的程序
如下图所示,我们在idea中创建了一个工程
此工程的基本逻辑就是表现层调用服务层,服务层调用dao层,dao层来对数据库进行操作。
我们自然而然的会在表现层注入service层的类,service层注入Dao层的类来实现方法的调用。就像这样
表现层:
service层:
但是,此种注入对象的方法会导致一个严重的问题:
表现层依赖于服务层,服务层依赖于Dao层
假如我们把Dao层的类删掉,那么此工程就会报错,连编译都不可能比编译!!
2.1 案例一的解决办法:使用反射为我们创建对象
为了避免耦合度太高的问题,我们将会自己写一个 BeanFactory 来反射创建对象,这样即使对象不存在,在编写代码的时候,也不会报错
public class BeanFactory {
//定义一个Properties对象
private static Properties props;
private static Map<String,Object> beans;
//使用静态代码块为Properties对象赋值
static {
try {
//实例化对象
props = new Properties();
//获取properties文件的流对象
InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
props.load(in);
//实例化容器
beans = new HashMap<String,Object>();
//取出配置文件中所有的Key
Enumeration keys = props.keys();
//遍历枚举
while (keys.hasMoreElements()){
//取出每个Key
String key = keys.nextElement().toString();
//根据key获取value
String beanPath = props.getProperty(key);
//反射创建对象
Object value = Class.forName(beanPath).newInstance();
//把key和value存入容器中
beans.put(key,value);
}
}
catch(Exception e){
throw new ExceptionInInitializerError("初始化properties失败!");
}
}
/**
* 根据Bean的名称获取bean对象
* @param beanName
* @return
*/
public static Object getBean(String beanName) {
return beans.get(beanName);
}
}
2.2 beanFactory 的解释
在我们自己写的beanFactory中 ,我们通过对象的全限定类名反射创建出对象,然后存在map集合中。
当我们需要对象时只需要通过getBean方法传入想要创建对象的名字,然后在事先写好的properties中找到此对象名字所对应的全限定类名。最后反射创建对象。
//.properties文件
accountService=com.eric.service.impl.AccountServiceImpl
accountDao=com.eric.dao.impl.AccountDaoImpl
//反射创建对象
Object value = Class.forName(beanPath).newInstance();
三.案例一的提高:使用beanFactory创建对象
四.总结:
你可以将案例一与案例一的改进进行对比,假如此时你删掉Dao层的代码。 service层,以及表现层是不会报错的
这样不就降低了类与类之间的依赖吗?
实际的spring也是这样做的,即将对象的控制权交给spring的ioc容器,而不需要我们手动 new 对象
我们将对象包装成bean对象交给IOC容器管理,这就是IOC的定义–控制反转