一、通过工厂+反射+配置文件创建对象
简单的说就是以后我们不用自己new对象了,对象的实例化都交给工厂来完成,我们需要对象的时候直接问工厂拿一个就行,一会我们会来看一个例子。在这里有一点要说明,spring IOC与工厂模式并不是完全相同的,最大的不同在于普通的工厂模式内部还是使用new来创建对象,但是spring IOC是用反射来创建对象,这么做有什么好处呢?
/**
* @author wangl
* @date 2023/5/31
* 容器工厂
*/
public class ContainerFactory {
/**
* 容器
*/
private static Map<String, Object> container = new HashMap<>();
/**
* 在静态代码块中初始化整个容器工厂,解析properties文件中配置的对象,
* 创建实例放入到Map集合中
*/
static {
//加载配置文件
//1、创建Propertise对象
Properties prop = new Properties();
//根据Properties文件的位置创建一个输入流,给Properties对象进行操作
//InputStream 输入流-用完就关闭
//getClassLoader:类加载器
//getResourceAsStream 找到项目的src目录
try (InputStream input = ContainerFactory.class.getClassLoader().getResourceAsStream("Bean.properties")){
//加载并读取properties文件的内容
prop.load(input);
//循环遍历prop对象得到每一个properties
//把创建好的实例Map集合中key
//map.put(key,input)
prop.forEach((key,value) -> {
//key.toString(),newInstance()))
Object instance = newInstance(value.toString());
container.put(key.toString(),instance);
});
//
} catch (Exception e) {
throw new RuntimeException("解析失败",e);
}
}
private static Object newInstance(String className) {
try {
//通过完成整类名加载class对象
Class<?>clazz = Class.forName(className);
return clazz.getConstructor().newInstance();
}catch (Exception e){
throw new RuntimeException("解释失败");
}
}
/**
* 容器工厂方法
*/
public static <T> T getBean(String name) {
return (T)container.get(name);
}
}
配置文件如下
iphone = edu.nf.product.IPhone
miphone = edu.nf.product.MiPhone
spring IOC的思想与工厂模式基本是一样的,只是创建对象的方式从“new”变成了反射,这就带来了很大的灵活性。不过,现在阅读spring源码还为时过早,于是我自己写了一个简单的例子来模拟spring IOC的基本原理。
首先,如果我们要用反射创建对象,全类名是必不可少的(反射不太记得的朋友请好好复习一下反射),然后我们还需要一个类名,用来告诉工厂我们需要哪个对象(就像上面getShape方法传入的参数shapeType一样),这个名字可以随便取,但是不能重复。这样我们就有了创建对象的两个要素,然后我们需要一个key-value对把这两个关联起来。然后就形成了这样一个模式:我们传入类名,工厂去查询key-value对,找到对应的全类名,然后通过全类名利用反射创建对象,再返回给我们。是不是很简单呢?