实现一个简单 IoC 容器
定义需要实例化对象的类的全限定类名以及类之间依赖关系的描述。
核心代码
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 测试文件
<?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>