Maven依赖:
4.0.0
org.myspringframework
myspring
1.0-SNAPSHOT
jar
17
17
UTF-8
dom4j
dom4j
1.1
jaxen
jaxen
1.2.0
junit
junit
4.13.2
test
public interface ApplicationContext {
/**
* 根据bean的名字获取对应的bean对象
* @param beanName myspring配置文件中bean标签的id
* @return 对应的bean对象
*/
T getBean(String beanName,Class type);
Object getBean(String beanName);
}
public class ClassPathXmlApplicationContext implements ApplicationContext{
// 对应一级缓存
private Map singletonObject=new HashMap<>();
/**
* 解析myspring的配置文件,然后初始化所有的bean对象。
* @param configLocation Spring配置文件的路径,注意,使用ClassPathXmlApplicationContext,配置文件应放在类路径中
*/
public ClassPathXmlApplicationContext(String configLocation) {
// 解析myspring.xml配置文件,实例化bean,把bean放到集合中
try {
// 获取一个解析器对象
SAXReader saxReader=new SAXReader();
// 获取所要读取的文件的输入流
URL resource = ClassLoader.getSystemClassLoader().getResource(configLocation);
// 获取文档对象
Document document = saxReader.read(resource);
// 获取指定标签 //bean 表示获得多个bean标签
List beans = document.selectNodes("//bean");
// 遍历所有的bean并放到集合中
beans.forEach(new Consumer() {
@Override
public void accept(Object o) {
//向下转型,拥有更丰富的方法
Element element= (Element) o;
//获取bean后,再获取属性值id和class 注:class是全类名
String id = element.attributeValue("id");
String className = element.attributeValue("class");
try {
//有了类名后,直接反射创建对象
Class clazz= Class.forName(className);
//获取无参构造方法
Constructor declaredConstructor = clazz.getDeclaredConstructor();
//创建对象并放到map中 进行曝光
Object bean = declaredConstructor.newInstance();
singletonObject.put(id,bean);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
});
// 进行set注入,为属性赋值
//首先得获得 标签,获取其中的属性name和value 或是 name和ref
beans.forEach(new Consumer() {
@Override
public void accept(Object o) {
try {
//获取bean的id和className
Element element= (Element) o;
String className=element.attributeValue("class");
String id=element.attributeValue("id");
//获取 中的所有标签
List properties = element.elements();
//遍历该bean所有标签
properties.forEach(new Consumer() {
@Override
public void accept(Object o) {
Element property= (Element) o;
String fieldName = property.attributeValue("name");
String propertyValue = property.attributeValue("value");
String ref = property.attributeValue("ref");
try {
//利用反射
Object bean=singletonObject.get(id);
//获取set()方法
String setMethodName="set"+fieldName.toUpperCase().charAt(0)+fieldName.substring(1);
//获取全限定类型名
Class propertyType= bean.getClass().getDeclaredField(fieldName).getType();
//如果所获取的方法有参数的话,需要加上参数类型
Method setMethod = bean.getClass().getDeclaredMethod(setMethodName,propertyType);
//获取bean的set方法
if(propertyValue!=null){
Object propertyVal=null;
//对于基本数据类型,如果想要调用相应的set方法,必须知道类型是什么
String propertyTypeSimpleName=propertyType.getSimpleName();
switch (propertyTypeSimpleName) {
case "byte": case "Byte":
propertyVal = Byte.valueOf(propertyValue);
break;
case "short": case "Short":
propertyVal = Short.valueOf(propertyValue);
break;
case "int": case "Integer":
propertyVal = Integer.valueOf(propertyValue);
break;
case "long": case "Long":
propertyVal = Long.valueOf(propertyValue);
break;
case "float": case "Float":
propertyVal = Float.valueOf(propertyValue);
break;
case "double": case "Double":
propertyVal = Double.valueOf(propertyValue);
break;
case "boolean": case "Boolean":
propertyVal = Boolean.valueOf(propertyValue);
break;
case "char": case "Character":
propertyVal = propertyValue.charAt(0);
break;
case "String":
propertyVal = propertyValue;
break;
}
setMethod.invoke(singletonObject.get(id), propertyVal);
}else if(ref!=null){
//这个简单,直接把所需要的曝光后的对象赋值给它就行。
setMethod.invoke(bean,singletonObject.get(ref));
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}catch (Exception e){
e.printStackTrace();
}
}
// 加个泛型
@Override
public T getBean(String beanName,Class type) {
return (T)singletonObject.get(beanName);
}
@Override
public Object getBean(String beanName) {
return singletonObject.get(beanName);
}
}