长篇大论
需求
xml的ioc容器,单例,set注入。
简单类型的转换,
引用类型的套娃。
实现思路
- 核心对象:Map
- 创建容器:
扫描配置文件,转为BeanInfo数组
遍历BeanInfo,创建各个对象,注入简单类型。
遍历BeanInfo,注入引用类型。 - 获取对象:Map.get(xxx)
用到的API
- 反射
- xml解析
效果展示
实体类
public class Student {
private String name;
private Integer age;
private Student bestFriend;
//空参构造,各种getset,toString
}
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="s1" class="base.ioc.test.entity.Student">
<property name="name" value="张三"/>
<property name="age" value="23"/>
<property name="bestFriend" ref="s2"/>
</bean>
<bean id="s2" class="base.ioc.test.entity.Student">
<property name="name" value="李四"/>
<property name="age" value="32"/>
</bean>
</beans>
测试类
@Test
public void fun3() {
XMLContainer container = new XMLContainer("beans.xml");
System.out.println(container.getBean("s1"));
System.out.println(container.getBean("s2"));
}
测试结果
核心容器
一个简单的接口
public interface Container {
Object getBean(String id);
}
一个简单的实现
public class XMLContainer implements Container {
private static final Map<String, Object> data = new ConcurrentHashMap<>();
public XMLContainer(String xmlPath) {
//解析xml
List<BeanInfo> beanInfos = XmlUtil.parse(xmlPath);
//创建对象,注入简单类型
for (BeanInfo info : beanInfos) {
data.put(info.getName(), ReflectUtil.createObj(info));
}
//注入引用类型
for (BeanInfo info : beanInfos) {
ReflectUtil.initRefs(info, data);
}
}
@Override
public Object getBean(String id) {
return data.get(id);
}
}
BeanInfo的结构
public class BeanInfo {
private String name;
private Class targetClass;
private Map<String, String> values = new ConcurrentHashMap<>();
private Map<String, String> refs = new ConcurrentHashMap<>();
//空参构造,各种setget,toString
}