package glut.spring;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
public class ClassPathXMLApplicationContext {
/**
* 用于存放<bean/>
*/
private Map<String, Object> beans = new HashMap<>();
/**
* 用于存放<property/>
*/
private Map<String, List<Element>> properties = new HashMap<>();
/**
* 将xml文件转为输入流,作为参数传入.
* @param is
* @throws Exception
*/
public ClassPathXMLApplicationContext(InputStream is) throws Exception {
// TODO Auto-generated constructor stub
autoWired(is);
}
/**
* 模拟DI
* @param is
* @throws Exception
*/
private void autoWired(InputStream is) throws Exception {
SAXBuilder sb = new SAXBuilder();
Document doc = sb.build(is);
Element rootElement = doc.getRootElement();
List<Element> elementOfBeans = rootElement.getChildren("bean");
//遍历xml中所有的<bean/>
for (Element e : elementOfBeans) {
String beanId = e.getAttributeValue("id");
String beanClz = e.getAttributeValue("class");
Object beanInstance = Class.forName(beanClz).newInstance();
//将beanId和bean的实例存入map
beans.put(beanId, beanInstance);
//把所有的property先存着,等bean初始化完毕再初始化property,否则可能会导致某些property无法初始化
properties.put(beanId, e.getChildren("property"));
}
//Dependency Injection Simulation
for (Entry<String, List<Element>> entry : properties.entrySet()) {
for (Element e : entry.getValue()) {
String propertyName = e.getAttributeValue("name");
String propertyRef = e.getAttributeValue("ref");
//通过set方法注入
String methodName = "set"
+ propertyName.substring(0, 1).toUpperCase()
+ propertyName.substring(1);
//通过beanId获得对应的bean
Object beanInstance = beans.get(entry.getKey());
//通过ref的值去寻找对应的bean,如果没有对应的bean,在下面用到getClass的时候会抛出异常.
Object refBeanInstance = beans.get(propertyRef);
Method setterMethod = beanInstance.getClass().getMethod(
methodName,//呵呵,功能有点简陋,默认只支持refBean实现的第一个接口.
refBeanInstance.getClass().getInterfaces()[0]);
//调用对应的setter方法,将ref的bean注入到指定的bean中.
setterMethod.invoke(beanInstance, refBeanInstance);
}
}
}
/**
* 根据beanName获得bean
*/
public Object getBean(String beanName) {
// TODO Auto-generated method stub
return beans.get(beanName);
}
}