先大致说一下思路:以流的形式读取一个配置文件,并将流中的信息解析并封装到一个map1<String,BeanDefinition>中,BeanDefinition包含了配置文件的属性信息,构建一个工厂,利用反射将构建的bean对象存入另一个map2<String,Object>中,方便从工厂直接获取对象.其中map1作为工厂的原料(需要从配置文件中获取),map2作为工厂产品(有工厂为我们创建的bean对象).
先定义实体类User.class
package com.spring;
/**
* 实体类
* @author wan_ys
*
*/
public class User {
private Integer id;
private String name;
}
Order.class
package com.spring;
/**
* 实体类
* @author wan_ys
*
*/
public class Order {
private Integer id;
private String item;
}
这里写一个简单的配置文件spring-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="user" class="com.spring.User"></bean>
<bean id="order" class="com.spring.Order"></bean>
</beans>
定义一个存放配置文件信息的类(属性与配置文件中的属性对应)
package com.spring;
/**
* 包装配置文件中bean的配置信息
* @author wan_ys
*
*/
public class BeanDefinition {
private String id;
private String claString;//对应配置文件中的class属性
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClaString() {
return claString;
}
public void setClaString(String claString) {
this.claString = claString;
}
@Override
public String toString() {
return "BeanDefinition [id=" + id + ", claString=" + claString + "]";
}
}
模仿Spring写一个DefaultBeanFactory工厂
package com.spring;
/**
* Bean工厂
* @author wan_ys
*
*/
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class DefaultBeanFactory {
// 存储bean的信息(原料)
Map<String, BeanDefinition> beanMap = new ConcurrentHashMap<String, BeanDefinition>();
// 存储示例对象(产品)
Map<String, Object> instanceMap = new ConcurrentHashMap<String, Object>();
public DefaultBeanFactory(String configFilePath) {
// 获取文件对应的流对象
InputStream inputStream = ClassLoader.getSystemResourceAsStream(configFilePath);
// 处理流对象
handleStream(inputStream);
// 处理Document对象
// 处理Node对象,将数据封装到BeanDefinition对象中
}
/*
* 处理读取的配置文件流
*/
private void handleStream(InputStream inputStream) {
try {
//构建解析器对象
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
//将流解析为Document对象
Document document = builder.parse(inputStream);
//处理Document对象
handleDocument(document);
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* 处理Document对象
*/
private void handleDocument(Document document) {
// 获取所有bean元素
NodeList nodeList = document.getElementsByTagName("bean");
// 迭代所有的bean元素,先获取一个Node节点,将节点转成BeanDefinition对象之后存入beanMap(原料)
for (int i = 0; i < nodeList.getLength(); i++) {
// 获取第i个元素
Node node = nodeList.item(i);
// 处理Node对象,并将返回的BeanDefinition对象存入beanMap
BeanDefinition beanDefinition = handleNode(node);
beanMap.put(beanDefinition.getId(), beanDefinition);
}
}
/*
* 处理Node,转成BeanDefinition
*/
private BeanDefinition handleNode(Node node) {
//构建BeanDefinition对象,存储Node信息
BeanDefinition beanDefinition=new BeanDefinition();
//获取节点相关属性值
NamedNodeMap nodeMap = node.getAttributes();
String id = nodeMap.getNamedItem("id").getNodeValue();
String claString = nodeMap.getNamedItem("class").getNodeValue();
//将节点值存入BeanDefinition对象
beanDefinition.setId(id);
beanDefinition.setClaString(claString);
return beanDefinition;
}
/*
* 创建对象
*/
private Object createInstance(Class<?> class1) {
try {
Constructor<?> constructor = class1.getDeclaredConstructor();
return constructor.newInstance();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public <T>T getBean(String id,Class<T> class1){
//对传入的id和class1进行校验
if (!beanMap.containsKey(id)) {
throw new RuntimeException("没有该id的bean对象");
}
BeanDefinition definition = beanMap.get(id);
if (!class1.getName().equals(definition.getClaString())) {//User.class的getName与definition对象中获取的class属性是否相同
throw new RuntimeException("没有对应类的bean对象");
}
//从instanceMap中获取对象
Object object = instanceMap.get(id);
if (object==null) {
object=createInstance(class1);
instanceMap.put(id, object);
}
return (T) object;
}
}
下面做一个测试
package com.spring;
public class Test {
public static void main(String[] args) {
DefaultBeanFactory defaultBeanFactory=new DefaultBeanFactory("spring-config.xml");
User bean = defaultBeanFactory.getBean("user", User.class);
User bean2 = defaultBeanFactory.getBean("user", User.class);
System.out.println(bean); //com.spring.User@4e25154f
System.out.println(bean==bean2); //true
}
}