最近在学 spring IOC 闲来没事 自己模仿写个最基本的



/**
 * 模仿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() ,当需要访问时时 才动态注入。不会像我写的这样 。一开始就全部注入。这样的效率肯定不行。 个人见解。欢迎大家

提出意见。
 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值