手写spring实例化bean源码,只实现了Object getBean(String beanId)这个方法。
也就是实现:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("xxx");
Object o = applicationContext.getBean("xxx");
// 定义ApplicationContext 接口:
public interface ApplicationContext {
Object getBean(String name);
}
// ClassPathXmlApplicationContext类
/**
* 解析xml文件,读取标签,实例化对象
* @param springPath spring.xml path
*/
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ClassPathXmlApplicationContext implements ApplicationContext{
private final Map<String, Object> beanObjects = new HashMap<>();
public ClassPathXmlApplicationContext(String springPath) {
// 解析spring配置文件,然后实例化Bean,将Bean放到beanObjects中
try {
// 通过路径解析xml文件
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
// 获取类路径下的spring配置文件
InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(springPath);
Document document = db.parse(in);
// 获取所有的Bean标签
NodeList beans = document.getElementsByTagName("bean");
//System.out.println(beans.getLength());
for (int i = 0; i < beans.getLength(); i++) {
// 获取到某一个bean标签的所有属性的name和value存到map集合里
NamedNodeMap attributes = beans.item(i).getAttributes();
// 获取到bean标签里的id
String beanId = attributes.getNamedItem("id").getNodeValue();
// 获取到bean标签里的class
String classValue = attributes.getNamedItem("class").getNodeValue();
//System.out.println(beanId);
//System.out.println(classValue);
// 通过反射机制创建对象,并提前曝光
Class<?> beanClazz = Class.forName(classValue);
// 通过构造方法创建对象
Object beanObject = beanClazz.getConstructor().newInstance();
// 曝光bean
beanObjects.put(beanId, beanObject);
// System.out.println(beanObject);
}
// 再次遍历所有的bean标签,给属性赋值
for (int i = 0; i < beans.getLength(); i++) {
// 获取到某一个bean标签的所有属性的name和value存到map集合里
NamedNodeMap attributes = beans.item(i).getAttributes();
// 获取到bean标签里的id
String beanId = attributes.getNamedItem("id").getNodeValue();
// 获取到bean标签里的class
String classValue = attributes.getNamedItem("class").getNodeValue();
// 获取该bean标签下的所有property标签, 注意这里面包含回车, 需要进行筛选
NodeList childNodes = beans.item(i).getChildNodes();
List<Node> propertyNodes = new ArrayList<>();
for(int j=0; j<childNodes.getLength(); j++){
if (childNodes.item(j).getAttributes() !=null) {
propertyNodes.add(childNodes.item(j));
}
// 如果是回车话,这个会是null
//System.out.println(childNodes.item(j).getAttributes());
}
// 获取property属性的name和value属性 或者name和ref的属性
if (propertyNodes.size() != 0) {
propertyNodes.forEach(propertyNode -> {
// 获取property标签的属性名和属性值map
NamedNodeMap propertyNodeAttributes = propertyNode.getAttributes();
// 获取name属性值
Node nameNode = propertyNodeAttributes.getNamedItem("name");
// 获取value属性值
Node valueNode = propertyNodeAttributes.getNamedItem("value");
// 获取ref属性
Node refNode = propertyNodeAttributes.getNamedItem("ref");
// 给bean标签实例化出来的对象赋值
// 从beanObjects中根据beanId获取到已经创建出来的对象
Object beanObject = beanObjects.get(beanId);
if (nameNode != null && valueNode != null) {
try {
// 拼接set方法
String name = nameNode.getNodeValue();
String value = valueNode.getNodeValue();
String setMethod = "set" + name.toUpperCase().charAt(0) + name.substring(1);
// 通过反射机制调用set方法
Class<?> clazz1 = Class.forName(classValue);
Method method = clazz1.getDeclaredMethod(setMethod, String.class);
method.invoke(beanObject, value);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
if (nameNode != null && refNode != null){
try {
// 拼接set方法
String name = nameNode.getNodeValue();
String ref = refNode.getNodeValue();
String setMethod = "set" + name.toUpperCase().charAt(0) + name.substring(1);
//System.out.println(setMethod);
// 根据ref找到对应beanObject
Object refObject = beanObjects.get(ref);
//System.out.println(refObject.getClass().getName());
// 使用反射机制调用方法
Class.forName(classValue).getDeclaredMethod(setMethod, refObject.getClass()).invoke(beanObject, refObject);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
});
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Object getBean(String name) {
return beanObjects.get(name);
}
}