spring ioc 模擬

 本文主要的內容就是用本身的代碼實現spring下面的代碼功能:java

    InputStream is = new FileInputStream("bean.xml"); 
    XmlBeanFactory factory = new XmlBeanFactory(is); 
    Action action = (Action) factory.getBean("TheAction");
具體流程以下圖:
 

 

 1. 肯定有兩個類,一個是Course,一個是Student,Course由名稱、學分、描述組成。Student由學號、名字、課程組成。如今要先建一個Course而後把這個類做爲Student的Course屬性。git

  
  
  
  
  1. //Course.java: 
  2. package entity; 
  3. public class Course { 
  4.     private String name; 
  5.     private long credit; 
  6.     private String desc; 
  7.      public Course() { 
  8.         super(); 
  9.     } 
  10.     public String getName() { 
  11.         return name; 
  12.     } 
  13.     public void setName(String name) { 
  14.         this.name = name; 
  15.     } 
  16.     public long getCredit() { 
  17.         return credit; 
  18.     } 
  19.     public void setCredit(long credit) { 
  20.         this.credit = credit; 
  21.     } 
  22.     public String getDesc() { 
  23.         return desc; 
  24.     } 
  25.     public void setDesc(String desc) { 
  26.         this.desc = desc; 
  27.     } 
  28.      
  29. }  

 

  
  
  
  
  1. //Student.java: 
  2. package entity; 
  3. public class Student { 
  4.     private String NO; 
  5.     private String name; 
  6.     private Course course; 
  7.     public String getNO() { 
  8.         return NO; 
  9.     } 
  10.     public void setNO(String nO) { 
  11.         NO = nO; 
  12.     } 
  13.     public String getName() { 
  14.         return name; 
  15.     } 
  16.     public void setName(String name) { 
  17.         this.name = name; 
  18.     } 
  19.     public Course getCourse() { 
  20.         return course; 
  21.     } 
  22.     public void setCourse(Course course) { 
  23.         this.course = course; 
  24.     } 
  25.      
  26. }  

 

2 在bean.xml中寫上bean的信息,我改了一下xml的名字,如今是conf.xml,name和class都是必要的,而children節點的property就是這個bean的一些屬性。property中的param指這個屬性的名字,text的部分是value。
 
  
  
  
  
  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans> 
  3. <bean id="mathCourse" class="entity.Course"> 
  4.     <property param="name">math</property> 
  5.     <property param="credit">5</property> 
  6.     <property param="desc"> 
  7.         數學 
  8.     </property> 
  9. </bean> 
  10. <bean id="stud0" class="entity.Student"> 
  11.     <property param="NO">000</property> 
  12.     <property param="name">stud0</property> 
  13.     <property param="course" ref="mathCourse">mathCourse</property> 
  14. </bean> 
  15. </beans>  
xml裏面的信息要和上面的類的屬性相互對應,在property上寫有ref的節點說明是根據上上面已經定義的bean注入進來的。
 

 

 

3.用一個Property類做爲存放每一個<property/>節點的信息,由於比較的簡單,因此這個類只有幾個屬性
 
  
  
  
  
  1. package entity; 
  2. public class Property { 
  3.     private String name; 
  4.     private boolean ref; 
  5.     private String value; 
  6.     public String getName() { 
  7.         return name; 
  8.     } 
  9.     public void setName(String name) { 
  10.         this.name = name; 
  11.     } 
  12.     public boolean isRef() { 
  13.         return ref; 
  14.     } 
  15.     public void setRef(boolean ref) { 
  16.         this.ref = ref; 
  17.     } 
  18.     public String getValue() { 
  19.         return value; 
  20.     } 
  21.     public void setValue(String value) { 
  22.         this.value = value; 
  23.     } 

 

 

4.經過解析這個xml得到寫在裏面的信息。這裏使用dom4j
 
  
  
  
  
  1. public static Map<String, Property> getBeanParams(Element bean) { 
  2.         Map<String, Property> map = new HashMap<String, Property>(); 
  3.         for (Iterator<Element> beanIt = bean.elementIterator(); beanIt 
  4.                 .hasNext();) { 
  5.             Element property = beanIt.next(); 
  6.             Property p = new Property(); 
  7.             p.setName(property.attribute("param").getStringValue()); 
  8.             p.setRef(property.attribute("ref") == null ? false : true); 
  9.             p.setValue(property.getTextTrim()); 
  10.             map.put(property.attribute("param").getStringValue(), p); 
  11.         } 
  12.         return map; 
  13.     }  

 

 

5.使用java的反射對對象的屬性進行賦值。能夠經過兩種方法,一種是直接經過訪問屬性,另外一種就是使用方法就是setXXX(value),固然也能夠用構造函數,用起來不是通常的麻煩。
 
  
  
  
  
  1. package reflect; 
  2. import java.lang.reflect.Constructor; 
  3. import java.lang.reflect.Field; 
  4. import java.lang.reflect.InvocationTargetException; 
  5. import java.lang.reflect.Method; 
  6. import java.util.HashMap; 
  7. import java.util.Map;  
  8. public class ClassHelper { 
  9.     // 經過類方法獲取屬性值 
  10.      
  11. public static Map<String, Object> getMethods(Object obj) 
  12.             throws IllegalAccessException, IllegalArgumentException, 
  13.             InvocationTargetException { 
  14.         Map<String, Object> map = new HashMap<String, Object>(); 
  15.         Method[] method = obj.getClass().getDeclaredMethods(); 
  16.         for (int i = 0; i < method.length; i++) { 
  17.             String methodName = method[i].getName().toString(); 
  18.             if (methodName.startsWith("get")) { 
  19.                 map.put(method[i].getName().toString(), 
  20.                         method[i].invoke(obj, null)); 
  21.             } 
  22.         } 
  23.         return map; 
  24.     } 
  25.     // 經過類方法對屬性賦值 
  26.     public static String[] setMethods(Object obj, 
  27.             Map<String, Property> propertyMap, Map<String, Object> objMap) 
  28.             throws NumberFormatException, IllegalAccessException, 
  29.             IllegalArgumentException, InvocationTargetException { 
  30.         Method[] method = obj.getClass().getDeclaredMethods(); 
  31.         String[] methods = new String[method.length]; 
  32.         for (int i = 0; i < method.length; i++) { 
  33.             String methodName = method[i].getName().toString(); 
  34.             if (methodName.startsWith("set")) { 
  35.                 for (Class<?> c : method[i].getParameterTypes()) { 
  36.                     String paramType = c.getSimpleName().toString();// 獲取方法中變量的類型 
  37.                     String name = method[i].getName().toString() 
  38.                             .substring(3, methodName.length()).toLowerCase();// 記得要轉換爲小寫,截取後獲得的string開頭字母是大寫 
  39.                     // System.out.println(name); 
  40.                     Property property = propertyMap.get(name); 
  41.                     String val = property.getValue(); 
  42.                     if (property.isRef()) { 
  43.                         Object o = objMap.get(val); 
  44.                         method[i].invoke(obj, o); 
  45.                     } else if (paramType.toLowerCase().equals("long")) { 
  46.                         method[i].invoke(obj, Long.parseLong(val)); 
  47.                     } else if (paramType.toLowerCase().equals("int"
  48.                             || paramType.equals("Integer")) { 
  49.                         method[i].invoke(obj, Integer.valueOf(val)); 
  50.                     } else if (paramType.toLowerCase().equals("float")) { 
  51.                         method[i].invoke(obj, Float.valueOf(val)); 
  52.                     } else if (paramType.toLowerCase().equals("short")) { 
  53.                         method[i].invoke(obj, Short.valueOf(val)); 
  54.                     } else if (paramType.toLowerCase().equals("double")) { 
  55.                         method[i].invoke(obj, Double.valueOf(val)); 
  56.                     } else if (paramType.toLowerCase().equals("char")) { 
  57.                         method[i].invoke(obj, val.charAt(0)); 
  58.                     } else if (paramType.toLowerCase().equals("boolean")) { 
  59.                         method[i].invoke(obj, Boolean.valueOf(val)); 
  60.                     } else if (paramType.toLowerCase().equals("byte")) { 
  61.                         method[i].invoke(obj, val.getBytes()[0]); 
  62.                     } else { 
  63.                             method[i].invoke(obj, val); 
  64.                     } 
  65.                 } 
  66.             } 
  67.         } 
  68.         return methods; 
  69.     } 
  70.     // 獲取類屬性的值 
  71.     public static Map<String, Object> getFieldsValues(Object obj) 
  72.             throws IllegalArgumentException, IllegalAccessException { 
  73.         Field[] field = obj.getClass().getDeclaredFields(); 
  74.         Map<String, Object> map = new HashMap<String, Object>(); 
  75.         for (int i = 0; i < field.length; i++) { 
  76.             field[i].setAccessible(true); // 容許訪問私有屬性 
  77.             map.put(field[i].getName(), field[i].get(obj));// 使用屬性的名稱做爲key 
  78.                                                             // ,屬性的值做爲value 
  79.         } 
  80.         return map; 
  81.     } 
  82.     // 經過屬性直接賦值 
  83.     public static String[] setFields(Object obj, 
  84.             Map<String, Property> propertyMap, Map<String, Object> objMap) 
  85.             throws NumberFormatException, IllegalArgumentException, 
  86.             IllegalAccessException { 
  87.         Field[] field = obj.getClass().getDeclaredFields(); 
  88.         String[] fields = new String[field.length]; 
  89.         for (int i = 0; i < field.length; i++) { 
  90.             field[i].setAccessible(true); // 容許訪問私有屬性 
  91.             String name = field[i].getName(); 
  92.             fields[i] = name; 
  93.             String type = field[i].getType().getSimpleName(); 
  94.             // System.out.println("name:" + name + "   type:" + type); 
  95.             Property property = propertyMap.get(name); 
  96.             String val = property.getValue(); 
  97.             if (property.isRef()) { 
  98.                 Object o = objMap.get(val); 
  99.                 field[i].set(obj, o); 
  100.             } else if (type.toLowerCase().equals("long")) { 
  101.                 field[i].setLong(obj, Long.parseLong(val)); 
  102.             } else if (type.toLowerCase().equals("int"
  103.                     || type.equals("Integer")) { 
  104.                 field[i].setInt(obj, Integer.valueOf(val)); 
  105.             } else if (type.toLowerCase().equals("float")) { 
  106.                 field[i].setFloat(obj, Float.valueOf(val)); 
  107.             } else if (type.toLowerCase().equals("short")) { 
  108.                 field[i].setShort(obj, Short.valueOf(val)); 
  109.             } else if (type.toLowerCase().equals("double")) { 
  110.                 field[i].setDouble(obj, Double.valueOf(val)); 
  111.             } else if (type.toLowerCase().equals("char")) { 
  112.                 field[i].setChar(obj, val.charAt(0)); 
  113.             } else if (type.toLowerCase().equals("boolean")) { 
  114.                 field[i].setBoolean(obj, Boolean.valueOf(val)); 
  115.             } else if (type.toLowerCase().equals("byte")) { 
  116.                 field[i].setByte(obj, val.getBytes()[0]); 
  117.             } else { 
  118.                 // System.out.println(val); 
  119.                 field[i].set(obj, val); 
  120.             } 
  121.         } 
  122.         return fields; 
  123.     }  
  124.     /** 
  125.      * @param args 
  126.      */ 
  127.     public static void main(String[] args) { 
  128.         // TODO Auto-generated method stub 
  129.     } 
  130. }  

 

 

5.利用上面的方法構建BeanFactory;
 
  
  
  
  
  1. public class BeanFactory { 
  2.     /** 
  3.      * @param args 
  4.      */ 
  5.     private String path; 
  6.     public static Map<String, Object> map; 
  7.     public BeanFactory() { 
  8.         this("src/bean.xml"); 
  9.     } 
  10.     public BeanFactory(String path) { 
  11.         super(); 
  12.         this.path = path; 
  13.         init(); 
  14.     } 
  15.     private void init() { 
  16.         Document doc = null
  17.         map = new HashMap<String, Object>(); 
  18.         SAXReader reader = new SAXReader(); 
  19.         try { 
  20.             doc = reader.read(new File(path)); 
  21.             Element root = doc.getRootElement(); 
  22.             for (Iterator<Element> beans = root.elementIterator(); beans 
  23.                     .hasNext();) { 
  24.                 Element bean = beans.next(); 
  25.                 Map<String, String> beanParams = XmlHelper.getBeanParams(bean); 
  26.                 Class cla = Class.forName(bean.attributeValue("class")); 
  27.                 Object obj = cla.newInstance(); 
  28.                 // set value 
  29.                 ClassHelper.setFields(obj, beanParams, map); 
  30.                 // ClassHelper.setMethods(obj, beanParams, map); 
  31.                 map.put(bean.attributeValue("name"), obj); 
  32.             } 
  33.         } catch (Exception e) { 
  34.             // TODO Auto-generated catch block 
  35.             e.printStackTrace(); 
  36.         } 
  37.         // System.out.println(System.getProperty("user.dir")); 
  38.     } 
  39.     public static <T> T getBean(String key, Class<T> classOf) { 
  40.         return (T) map.get(key); 
  41.     } 
  42.    
  43.     public String getPath() { 
  44.         return path; 
  45.     } 
  46.     public void setPath(String path) { 
  47.         this.path = path; 
  48.     }  

 

 

本次實現是經過直接訪問類的屬性進行賦值的。
6.寫個main函數做爲測試;
 
  
  
  
  
  1. public class Main { 
  2.     /** 
  3.      * @param args 
  4.      * @throws InvocationTargetException 
  5.      * @throws IllegalArgumentException 
  6.      * @throws IllegalAccessException 
  7.      */ 
  8.     public static void main(String[] args) throws IllegalAccessException, 
  9.             IllegalArgumentException, InvocationTargetException { 
  10.         // TODO Auto-generated method stub 
  11.         BeanFactory beanFactory = new BeanFactory("src/conf.xml"); 
  12.         Student stud0 = BeanFactory.getBean("stud0", Student.class); 
  13.         Course mathCourse = BeanFactory.getBean("mathCourse", Course.class); 
  14.         System.out.println("stud name:" + stud0.getName()); 
  15.         System.out.println("stud NO.:" + stud0.getNO()); 
  16.         Course testMathCourse = stud0.getCourse(); 
  17.         System.out.println("the same ?:" 
  18.                 + (mathCourse == testMathCourse ? true : false)); 
  19.         System.out.println("math name:" + mathCourse.getName()); 
  20.         System.out.println("math credit:" + mathCourse.getCredit()); 
  21.         System.out.println("math desc:" + mathCourse.getDesc()); 
  22.         Map<String, Object> vals = ClassHelper.getMethods(stud0); 
  23.         for (Iterator<String> it = vals.keySet().iterator(); it.hasNext();) { 
  24.             String key=it.next(); 
  25.             System.out.println(key+":"+vals.get(key)); 
  26.         } 
  27.     } 
  28. }  

 

 

7.運行結果;
stud name:stud0
stud NO.:000
the same ?:true
math name:math
math credit:5
math desc:數學
getNO:000
getCourse:entity.Course@db95a1
getName:stud0
經過第三行的輸出能夠看出來,stud0的Course和從BeanFactory拿出來的是同一個對象。其餘的值和xml設置的值是一個樣的。
 InputStream is = new FileInputStream("bean.xml"); 
    XmlBeanFactory factory = new XmlBeanFactory(is); 
BeanFactory beanFactory = new BeanFactory("src/conf.xml");此句和上面的兩句功能同樣
Action action = (Action) factory.getBean("TheAction");
Student stud0 = BeanFactory.getBean("stud0", Student.class);此 句和上一句功能同樣。
在此目的達成。
done.

 

source code url:github

https://github.com/scalaview/reflectionspring

相關文章
相關標籤/搜索