Spring IoC的实现方案
- 1. IoC的定义
- 2. IoC的作用
- 3. 实现IOC的思路
- 4. 实现代码
- 4.1 代码层级
- 4.2 工厂的实现 - BeanFactory
- 4.3 配置文件 - beans.yml
- 4.4 测试类
- 4.5 其他补充
- 5. 总结
1. IoC的定义
inversion of control,控制反转,是一种思想。控制反转思想的两种实现类型:依赖注入(Depedency Injection)和依赖查找(Dependency Lookup)。
2. IoC的作用
消减计算机程序的耦合程度。
3. 实现IOC的思路
使用反射+配置文件,确定最终的实现类。
使用工厂模式,降低程序耦合度。
4. 实现代码
4.1 代码层级
4.2 工厂的实现 - BeanFactory
package com.fftest.spring;
import com.esotericsoftware.yamlbeans.YamlException;
import com.esotericsoftware.yamlbeans.YamlReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Set;
public class BeanFactory {
private static HashMap<String, Object> beanMap = new HashMap<String, Object>();
static {
try {
// 获取yml配置文件
YamlReader beansYaml = new YamlReader(new FileReader(System.getProperty("beanspath") + "beans.yml"));
// 读取yml配置文件的内容并转换成Map
HashMap<String, String> beansMap = (HashMap<String, String>) beansYaml.read();
// 遍历Map的内容并反射创建对象,将创建好的对象存入全局变量beanMap中
Set<String> keys = beansMap.keySet();
for (String key : keys) {
String clazz = beansMap.get(key);
Object newInstance = Class.forName(clazz).newInstance();
beanMap.put(key, newInstance);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (YamlException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
public static Object getBeanImplName(String bean) {
return beanMap.get(bean);
}
}
4.3 配置文件 - beans.yml
Car:
com.fftest.spring.impl.BMW
Customer:
com.fftest.spring.impl.RichMan
4.4 测试类
package com.fftest.spring.testcase;
import com.fftest.spring.BeanFactory;
import com.fftest.spring.Car;
import com.fftest.spring.Customer;
import org.junit.Test;
public class BeanFactoryTest {
@Test
public void getBeanImplNameTest() {
System.setProperty("beanspath", "/Users/faye/IdeaProjects/hello-spring/target/classes/");
Car car = (Car) BeanFactory.getBeanImplName("Car");
Customer customer = (Customer) BeanFactory.getBeanImplName("Customer");
System.out.println("Car model: " + car.getModel());
System.out.println("Car price: " + car.getPrice());
System.out.println("Customer name: " + customer.getName());
System.out.println("Customer is VIP: " + customer.isVIP());
}
}
打印结果
Car model: BMW
Car price: 520000
Customer name: Mr Lee
Customer is VIP: true
4.5 其他补充
引入依赖
<dependency>
<groupId>com.esotericsoftware.yamlbeans</groupId>
<artifactId>yamlbeans</artifactId>
<version>1.08</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
BMW的实现
package com.fftest.spring.impl;
import com.fftest.spring.Car;
public class BMW implements Car {
public String getModel() {
return this.getClass().getSimpleName();
}
public int getPrice() {
return 520000;
}
}
RichMan的实现
package com.fftest.spring.impl;
import com.fftest.spring.Customer;
public class RichMan implements Customer {
public String getName() {
return "Mr Lee";
}
public boolean isVIP() {
return true;
}
}
5. 总结
IoC的作用是解耦,解耦的思路有 2 个问题需要解决:
- bean存在哪里?
分析:由于我们一个项目中有很多对象,肯定要找个集合来存。这时候有 Map 和 List 供选择。到底选 Map 还是 List 就看我们有没有查找需求。有查找需求(因为Map是key-value结构,可以很方便通过key来获取值,也就是方便查找),选 Map。所以我们的答案就是在应用加载时,创建一个 Map,用于存放对象。我们把这个 map 称之为容器。
- 怎么去获取对象?
需要提供一个方法,根据不同的内容创建对象,考虑用工厂模式。
工厂就是负责给我们从容器中获取指定对象的类。这时候我们获取对象的方式发生了改变。
原来:我们在获取对象时,都是采用 new 的方式。 是主动的。
现在:我们获取对象时,同时跟工厂要,有工厂为我们查找或者创建对象。 是被动的。
以这种被动接收的方式获取对象的思想就是控制反转。