/**
* 模仿spring 的注入功能 利用dom4j解析 xml
* @author Administrator
*
*/
public class SpringUtil {
SAXReader reader = new SAXReader();
Document document;
Map<String,Object> context ; //假设的spring容器
public void IOC()
{
context = new HashMap<String, Object>();
try {
document = reader.read(Thread.currentThread().getContextClassLoader().getResource("").getPath().substring(1) + "beans.xml");
Element rootElm = document.getRootElement();
//System.out.println(rootElm.elements().get(0));
List<Element> beanElms = (List<Element>)rootElm.elements();
for(Element element:beanElms) //遍历所有的bean
{
String beanId = element.attributeValue("id");
if(!context.containsKey(beanId))
context.put(beanId, getOneBean(element));
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
private Object getOneBean(Element beanElement) //初始化bean
{
Object obj = null;
try {
String beanId = beanElement.attributeValue("id");
obj = Class.forName(beanElement.attributeValue("class")).newInstance();
context.put(beanId,obj ); //将obj放入context中
List<Element> childBeanList = beanElement.elements("property");
if(childBeanList.size()>0) //说明存在<property>标签
{
Class<? extends Object> currentBeanClass = obj.getClass(); //当前bean的Class对象
for(Element childElement :childBeanList ) //遍历所有的子标签
{
String propertyName = childElement.attributeValue("name"); //得到<property>的标签 name
Field proppertyField = currentBeanClass.getDeclaredField(propertyName);
String setMethodName= "set" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1); //拼接 set方法
Object propertyObj ; //要注入的对象bean
String propertyBeanId =childElement.attributeValue("ref"); //<property ref 依赖的bean对象Id
if(context.containsKey(propertyBeanId))
propertyObj = context.get(propertyBeanId);
else propertyObj = getOneBean(getBeanElement(propertyBeanId)); //<property > ref对应的类的对象
Method method = currentBeanClass.getDeclaredMethod(setMethodName, new Class[]{proppertyField.getType()}); //根据
method.invoke(obj, new Object[]{propertyObj});
}
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
System.out.println("getDeclaredMethod()参数有问题, 没有发现该方法");
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
System.out.println("getDeclaredField()有问题,没有发现这个方法");
}
return obj;
}
private Element getBeanElement(String beanId){ //通过beanId找到bean对象
Element rootElm = document.getRootElement();
List<Element> beanElms = rootElm.elements();
for(Element element:beanElms) //遍历所有的bean
{
if(beanId.equals(element.attributeValue("id")))
return element;
}
return null; // 该beanId 没有匹配的项
}
public static void main(String[] args) {
SpringUtil su = new SpringUtil();
su.IOC();
}
}
bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id = "adminDao" class = "com.sunzheng.team.dao.impl.AdminDAOImpl"></bean>
<bean id = "teamService" class = "com.sunzheng.team.service.impl.TeamServiceImpl">
<property name = "teamDao" ref = "teamDao"></property>
</bean>
<bean id = "studentService" class = "com.sunzheng.team.service.impl.StudentServiceImpl">
<property name = "studentDao" ref = "studentDao"></property>
</bean>
<bean id = "adminService" class = "com.sunzheng.team.service.impl.AdminServiceImpl">
<property name = "adminDao" ref = "adminDao"></property>
</bean>
<bean id = "teamDao" class = "com.sunzheng.team.dao.impl.TeamDAOImpl"></bean>
<bean id = "studentDao" class = "com.sunzheng.team.dao.impl.StudentDAOImpl"></bean>
</beans>
以上代码 只是单纯为了实现类似spring的ioc功能。其实 spring的注入分为 值注入和 构造函数注入。值注入就是传统的
setXXX() ,当需要访问时时 才动态注入。不会像我写的这样 。一开始就全部注入。这样的效率肯定不行。 个人见解。欢迎大家
提出意见。