<!--解析xml-->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
public class SimpleIOC {
/*
*
*Map<id,Object>
*/
private Map<String,Object> beans = new HashMap<>();
public SimpleIOC(String path) throws Throwable{
loadBeans(path);
}
public <T>T getBean(String id){
Object bean = beans.get(id);
if(bean== null)
throw new RuntimeException(id+":xml中没有注册该id");
return (T)bean;
}
public <T>T getBean(Class beanClass){
Collection<Object> values = beans.values();
for (Object value : values) {
if(value.getClass().equals(beanClass))return (T)value;
}
throw new NullPointerException(beanClass.getName()+":这个类型没有在xml中注册");
}
/**
* 使用DOM4j来解析xml
*
*
* @param path
* @throws Throwable
*/
private void loadBeans(String path) throws Throwable{
//加载xml
SAXReader reader = new SAXReader();
Document dom = reader.read(path);
Element root = dom.getRootElement();
List<Element> elements = root.elements();
//String,Map<String,String> ->className,Map<fieldName,ref>
Map<String,Map<String,String>> refs = new HashMap<>();
for (Element element : elements) {
String id = element.attributeValue("id");
String className = element.attributeValue("class");
Map<String,String> propertyValue= new HashMap<>();
List<Element> property = element.elements();
Map<String,String> ref = new HashMap<>();
for (Element pro : property) {//获取bean配置的属性值
if(existAttribute(pro,"value"))
propertyValue.put(pro.attributeValue("name"),pro.attributeValue("value"));
else
ref.put(pro.attributeValue("name"),pro.attributeValue("ref"));
}
Class cl = Class.forName(className);
Object bean = cl.newInstance();//无参构造创建bean
if(!ref.isEmpty())
refs.put(className,ref);
if(!propertyValue.isEmpty())//属性值不为空,将属性值装配到bean中
assembleBean(cl,bean,propertyValue);
beans.put(id,bean);
}
refreshBean(refs);
}
/**
*遍历完xml,将所有bean加载到容器中,再给bean中属性值为ref的属性赋值;
*String,Map<String,String> ->className,Map<fieldName,ref>
* @param refs
* @throws NoSuchFieldException
* @throws IllegalAccessException
*/
public void refreshBean(Map<String,Map<String,String>> refs) throws NoSuchFieldException, IllegalAccessException {
if(refs.isEmpty())return;
Iterator<String> iter = refs.keySet().iterator();
while(iter.hasNext()){
String className = iter.next();
Object object = getBean(Class.forName(className));
Map<String, String> refValue = refs.get(className);
Iterator<String> fieldValue = refValue.keySet().iterator();
while(fieldValue.hasNext()){
String fieldName = fieldValue.next();
String id = refValue.get(fieldName);
Object refObject = getBean(id);
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object,refObject);
}
}
}
private boolean existAttribute(Element pro,String attributeName){
return pro.attribute(attributeName) ==null ?false:true;
}
/*
转换类型
*/
private Object ConvertValueType(String type,String value) throws IllegalAccessException {
switch (type){
case "String":
return value;
case "Integer":
return Integer.valueOf(value);
case "int":
return Integer.parseInt(value);
case "Boolean":
return Boolean.valueOf(value);
case "boolean":
return Boolean.parseBoolean(value);
case "Short":
return Short.valueOf(value);
case "short":
return Short.parseShort(value);
case "Long":
return Long.valueOf(value);
case "long":
return Long.parseLong(value);
case "Byte":
return Byte.valueOf(value);
case "byte":
return Byte.parseByte(value);
case "Character":
return Character.valueOf(value.charAt(0));
case "char":
return value.charAt(0);
case "Double":
return Double.valueOf(value);
case "double":
return Double.parseDouble(value);
case "Float":
return Float.valueOf(value);
case "float":
return Float.parseFloat(value);
default:
throw new RuntimeException("不支持");
}
}
/**
*
* 8个基础属性 + 8个包装类+String:用value
*
* 将配置的属性装配到bean中
*
* @param bean
* @param propertyValue 配置的属性值
* @return
*/
private Object assembleBean(Class cl,Object bean,Map<String,String> propertyValue) throws IllegalAccessException {
Field[] fields = cl.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
String fieldName = field.getName();
if(propertyValue.containsKey(fieldName)) {
Object valueObject = ConvertValueType(field.getType().getSimpleName(),propertyValue.get(fieldName));
field.set(bean,valueObject);
}
}
return bean;
}
}
xml配置
<beans>
<bean id="conTest" class="com.myd.springioc.ConTest">
<property name="sex" value="man"/>
<property name="ID" value="QEWQWE"/>
<property name="age" value="123"/>
<property name="people" ref="pp"/>
</bean>
<bean id="pp" class="com.myd.springioc.People">
<property name="name" value="people-number1"/>
<property name="age" value="123"/>
<property name="ID" value="qwer23234"/>
</bean>
</beans>
测试类
public class Test {
public static void main(String[] args)throws Throwable {
SimpleIOC ioc = new SimpleIOC("src/main/resources/ioc.xml");
ConTest conTest = ioc.getBean(ConTest.class);
System.out.println(conTest.toString());
System.out.println(conTest.people.toString());
System.out.println("====================================");
People people = ioc.getBean("pp");
System.out.println(people);
}
}
结果:
ConTest{name='null', sex='man', age=123, ID='QEWQWE'}
People{name='people-number1', age=123, ID='qwer23234'}
====================================
People{name='people-number1', age=123, ID='qwer23234'}
===============================================================
更新:最近重新写了ioc容器,可以在xml中定义一个ComponentScan标签用来扫描注解@Component,使用了@Component的class可以将该class注入到ioc容器中,另外还实现了@Autowried,实现类型自动注入;
Gitee地址:地址