模拟Spring的属性装配

尊重原创。。谢谢大家

思想:
  1:正常加载所有类。如果发现有prop引用,则去cache(map)中去查询这个bean是否存在如果不存在则再去读取xml中的配置实例化这个信息。
  2:可以使用递归实现。



package cn.core;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class MyApplication {
   private Map<String, Object> cache = new HashMap<String, Object>();
   public MyApplication(String config) {
   try {
   //得到真实路径
   URL url = MyApplication.class.getClassLoader().getResource(config);
   File file = new File(url.getPath());
   SAXReader sax = new SAXReader();
   Document dom = sax.read(file);
   parseXml(dom, "//bean");
  } catch (Exception e) {
   throw new RuntimeException(e);
  }
 }
 // 开发一个方法用于解析xml文件
 // 接收两个参数第一个参数,是dom,第二个参数是查询哪些元素
 public void parseXml(Document dom, String xpath) throws Exception {
  List<Element> list = dom.selectNodes(xpath);
  for (Element e : list) {
   String id = e.attributeValue("id");
   if (cache.containsKey(id)) {//如果在缓存中已经包含了这个id
    continue;
   }
   String cls = e.attributeValue("cls");
   Object obj = Class.forName(cls).newInstance();
   cache.put(id, obj);
   List<Element> props = e.elements();
   for (Element p : props) {
    String name = p.attributeValue("name");//
    Object val = p.attributeValue("value");// 1:先读取value这个属性
    if (val == null) {// 2:如果没有value这个属性,则就去读取ref这个属性
     val = p.attributeValue("ref");
     if (val != null) {
      if (!cache.containsKey(val)) {// 这个bean还没有实例化呢//
       // 直接根据id先去加载这个类
       String xpath2 = "//bean[@id='" + val + "']";
       parseXml(dom, xpath2);
      }
      val = cache.get(val);// 上面解析完成以后,在cache缓存中一定是存在这个id元素的
     }
    }
    PropertyDescriptor pd = new PropertyDescriptor(name,
      obj.getClass());
    if (pd.getPropertyType() == Integer.class
      || pd.getPropertyType() == int.class) {
     pd.getWriteMethod().invoke(obj, Integer.parseInt("" + val));
    } else {
     pd.getWriteMethod().invoke(obj, val);
    }
   }
  }
 }
 public <T> T getBean(String id, Class<T> class1) {
  Object obj = cache.get(id);// 根据id从map中获取值
  return (T) obj;
 }
}
实体类
package cn.demo;
import org.junit.Test;
import cn.core.MyApplication;
import cn.domain.Person;
public class Demo01 {
 @Test
 public void test1() {
  MyApplication app = new MyApplication("cn/demo/mybeans.xml");
  Person p1 = app.getBean("person",Person.class);
  System.err.println(p1);
 }
}
自定义配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans>
 <bean id="aa" cls="cn.domain.Address">
  <prop name="zip" value="10085" />
  <prop name="tel" value="198393843" />
 </bean>
 <bean id="person" cls="cn.domain.Person">
  <prop name="name" value="Jack" />
  <prop name="age" value="33" />
  <prop name="addr" ref="aa"/>
 </bean>
</beans>

你可能感兴趣的:(模拟Spring的属性装配)