实现一个简单 IoC 容器

定义需要实例化对象的类的全限定类名以及类之间依赖关系的描述。

核心代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public class BeanFactory {

private final static Map<String, Object> map = new HashMap<>();

static {
InputStream resource = Resource.getResourceAsStream("beans.xml");
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read(resource);
Element rootElement = document.getRootElement();

List<Element> beanList = rootElement.selectNodes("//bean");
for (Element element : beanList) {
String id = element.attributeValue("id");
String clazz = element.attributeValue("class");

Object object = newInstance(clazz);
map.put(id, object);
}

List<Element> properties = rootElement.selectNodes("//property");
for (Element property : properties) {
String name = property.attributeValue("name");
String ref = property.attributeValue("ref");

//父元素
Element parent = property.getParent();
String id = parent.attributeValue("id");
Object parentBean = getBean(id);
Method[] methods = parentBean.getClass().getDeclaredMethods();
for (Method method : methods) {
if (("set" + name).equalsIgnoreCase(method.getName())) {
//给父元素的成员变量赋值
Object bean = getBean(ref);
method.invoke(parentBean, bean);
break;
}
}
map.put(id, parentBean);
}

} catch (DocumentException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException |
InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}

private static Object newInstance(String clazz) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
Class<?> aClass = Class.forName(clazz);
Constructor<?> constructor = aClass.getDeclaredConstructor();
return constructor.newInstance();
}

public static <T> T getBean(String id) {
return (T) map.get(id);
}
}

XML 测试文件

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8" ?>

<beans>
<bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcAccountDaoImpl"></bean>
<bean id="transferService" class="com.lagou.edu.service.impl.TransferServiceImpl">
<!--set+name找到set方法,传入参数ref-->
<property name="AccountDao" ref="accountDao"></property>
</bean>
</beans>