程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java代碼實現依賴注入

Java代碼實現依賴注入

編輯:關於JAVA

這裡將模仿Spring實現一種基於xml配置文件的依賴注入機制。文件中將實現3中注入,一是單值注入 ,包括int,float,double,char等,也包括String注入;二是Java容器注入,包括List,Set,Map三種 容器的注入,最後一種是java bean對象注入。

實現的機制是,使用Dom4j對xml配置文件進行解析,這裡使用dom4j的Element Handler機制,一種類 似與責任鏈模式的實現機制;對於java對象的構建使用反射機制,這裡主要是針對得到的類的Field進行 set賦值。我試圖通過調用Method的invoke方法調用類本身的setter方法,但是由於通過xml解析得到的值 都是String,如果將這些String動態的轉換為相應的確定類型是個難點,Method的invoke方法,如果形參 是int,而傳入java.lang.Integer,它不會認,所以嘗試失敗,只能通過Field的set方法傳入特定值。

配置文件setting.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
   <bean id="me" class="com.zj.ioc.di.imp.Person">
    <property name="name">
      <value>ZJ</value>
    </property>
    <property name="age">
      <value>26</value>
    </property>
    <property name="height">
      <value>1.78</value>
    </property>
   </bean>
   <bean id="you" class="com.zj.ioc.di.imp.Person">
    <property name="name">
      <value>Mary</value>
    </property>
    <property name="age">
      <value>27</value>
    </property>
    <property name="height">
      <value>1.66</value>
    </property>
   </bean>
   <bean id="myList" class="com.zj.ioc.di.imp.ListOne">
    <property name="msg">
      <list>
        <value>java</value>
        <value>c</value>
        <value>windows</value>
      </list>
    </property>
   </bean>
   <bean id="mySet" class="com.zj.ioc.di.imp.SetOne">
    <property name="msg">
      <set>
        <value>tom</value>
        <value>cat</value>
        <value>dog</value>
      </set>
    </property>
   </bean>
   <bean id="myMap" class="com.zj.ioc.di.imp.MapOne">
    <property name="msg">
      <map>
        <entry key="c">
          <value>CHINA</value>
        </entry>
        <entry key="j">
          <value>JAPAN</value>
        </entry>
        <entry key="k">
          <value>KOREA</value>
        </entry>
      </map>
    </property>
   </bean>
   <bean id="us" class="com.zj.ioc.di.imp.Persons">
    <property name="i">
      <ref bean="me" />
    </property>
    <property name="u">
      <ref bean="you" />
    </property>
   </bean>
</beans>

依據setting.xml,這裡將構建兩個Person類的實例me和you:

Person.java

package com.zj.ioc.di.imp;
public class Person {
   private String name;
   private int age;
   private float height;
   public String getName() {return name;}
   public void setName(String name) {this.name = name;}
   public int getAge() {return age;}
   public void setAge(int age) {this.age = age;}
   public float getHeight() {return height;}
   public void setHeight(float height) {this.height = height;}
}

緊接著,構建一個ListOne的實例myList:

ListOne.java

package com.zj.ioc.di.imp;
import java.util.List;
public class ListOne {
   private List<String> msg;
   public List<String> getMsg() {return msg;}
   public void setMsg(List<String> msg) {this.msg = msg;}
}

緊接著,構建一個SetOne的實例mySet:

SetOne.java

package com.zj.ioc.di.imp;
import java.util.Set;
public class SetOne {
   private Set<String> msg;
   public Set<String> getMsg() {return msg;}
   public void setMsg(Set<String> msg) {this.msg = msg;}
}

緊接著,構建一個MapOne的實例myMap:

MapOne.java

package com.zj.ioc.di.imp;
import java.util.Map;
public class MapOne {
   private Map<String,String> msg;
   public Map<String, String> getMsg() {return msg;}
   public void setMsg(Map<String, String> msg) {this.msg = msg;}
}

最後構建一個Persons類的實例us,其中包含me和you兩個已經構建好的對象:

Persons.java

package com.zj.ioc.di.imp;
public class Persons {
   private Person i;
   private Person u;
   public Person getI() {return i;}
   public void setI(Person i) {this.i = i;}
   public Person getU() {return u;}
   public void setU(Person u) {this.u = u;}
}

主要的實現機制是(代碼BeanFactory.java以及工程見附件),

1.通過一個HashMap保存構造好的對象,key就是bean的id屬性,value就是這個對象;

private Map<String, Object> beanMap = new HashMap<String, Object> ();
……
public Object getBean(String beanId) {
   Object obj = beanMap.get(beanId);
   return obj;
}

查詢時

BeanFactory factory = new BeanFactory();
factory.init("setting.xml");
Person p1 = (Person) factory.getBean("me");

2.init方法讀入配置文件setting.xml,並直接定位到beans下的bean元素,並實例化一個 ElementHandler對其處理。

public void init(String xmlUri) throws Exception {
   SAXReader saxReader = new SAXReader();
   File file = new File(xmlUri);
   try {
    saxReader.addHandler("/beans/bean", new BeanHandler());
    saxReader.read(file);
   } catch (DocumentException e) {
    System.out.println(e.getMessage());
   }
}

3.ElementHandler,dom4j的ElementHandler接口有兩個方法,一個是onStart(),它主要用於處理該 元素的屬性以及動態增加新的Handler類;另一個是onEnd(),它主要用於獲得該元素的Text文本以及刪除 已添加的Handler。

BeanHandler

private class BeanHandler implements ElementHandler {
   Object obj = null;
   public void .Start(ElementPath path) {
    Element beanElement = path.getCurrent();
    Attribute classAttribute = beanElement.attribute("class");
    Class<?> bean = null;
    try {
      bean = Class.forName(classAttribute.getText());
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
    Field fields[] = bean.getDeclaredFields();
    Map<String, Field> mapField = new HashMap<String, Field>();
    for (Field field : fields)
      mapField.put(field.getName(), field);
    try {
      obj = bean.newInstance();
    } catch (InstantiationException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    }
    path.addHandler("property", new PropertyHandler(mapField, obj));
   }
   public void .End(ElementPath path) {
    Element beanElement = path.getCurrent();
    Attribute idAttribute = beanElement.attribute("id");
    beanMap.put(idAttribute.getText(), obj);
    path.removeHandler("property");
   }
}

PropertyHandler

private class PropertyHandler implements ElementHandler {
   Map<String, Field> mapField;
   Object obj;
   public PropertyHandler(Map<String, Field> mapField, Object obj) {
    this.mapField = mapField;
    this.obj = obj;
   }
   public void .Start(ElementPath path) {
    Element propertyElement = path.getCurrent();
    Attribute nameAttribute = propertyElement.attribute("name");
    path.addHandler("value", new ValueHandler(mapField, obj,
        nameAttribute));
    path.addHandler("list", new ListHandler(mapField, obj,
        nameAttribute));
    path.addHandler("set", new SetHandler(mapField, obj,
        nameAttribute));
    path.addHandler("map", new MapHandler(mapField, obj,
        nameAttribute));
    path.addHandler("ref", new RefHandler(mapField, obj,
        nameAttribute));
   }
   public void .End(ElementPath path) {
    path.removeHandler("value");
    path.removeHandler("list");
    path.removeHandler("set");
    path.removeHandler("map");
    path.removeHandler("ref");
   }
}

根據setting.xml,我們可以得到各種注入元素的Handler類處理流程圖。

4. setFieldValue()基於反射機制和相應的類信息得到Field的類型,並根據setting.xml設置它的值 。

private void setFieldValue(Object obj, Field field, String value) {
   String fieldType = field.getType().getSimpleName();
   try {
    if (fieldType.equals("int"))
      field.setInt(obj, new Integer(value));
    else if (fieldType.equals("float"))
      field.setFloat(obj, new Float(value));
    else if (fieldType.equals("boolean"))
      field.setBoolean(obj, new Boolean(value));
    else if (fieldType.equals("char"))
      field.setChar(obj, value.charAt(0));
    else if (fieldType.equals("double"))
      field.setDouble(obj, new Double(value));
    else if (fieldType.equals("long"))
      field.setLong(obj, new Long(value));
    else
      field.set(obj, value);
   } catch (IllegalArgumentException e) {
    e.printStackTrace();
   } catch (IllegalAccessException e) {
    e.printStackTrace();
   }
}
private void setFieldValue(Object obj, Field field, List<String> value) {
   try {
    field.set(obj, value);
   } catch (IllegalArgumentException e) {
    e.printStackTrace();
   } catch (IllegalAccessException e) {
    e.printStackTrace();
   }
}

5.測試

public static void main(String[] args) {
   try {
    BeanFactory factory = new BeanFactory();
    factory.init("setting.xml");
    Person p1 = (Person) factory.getBean("me");
    System.out.print(p1.getName() + " ");
    System.out.print(p1.getAge() + " ");
    System.out.println(p1.getHeight());
    Person p2 = (Person) factory.getBean("you");
    System.out.print(p2.getName() + " ");
    System.out.print(p2.getAge() + " ");
    System.out.println(p2.getHeight());
    ListOne list = (ListOne) factory.getBean("myList");
    System.out.println(list.getMsg());
    SetOne set = (SetOne) factory.getBean("mySet");
    System.out.println(set.getMsg());
    MapOne map = (MapOne) factory.getBean("myMap");
    System.out.println(map.getMsg());
    Persons us = (Persons) factory.getBean("us");
    System.out.println(us.getI());
    System.out.println(us.getU());
   } catch (Exception e) {
    e.printStackTrace();
   }
}

測試結果:

ZJ 26 1.78

Mary 27 1.66

[java, c, windows]

[cat, tom, dog]

{c=CHINA, j=JAPAN, k=KOREA}

com.zj.ioc.di.imp.Person@1a5ab41

com.zj.ioc.di.imp.Person@18e3e60

本文出自 “子 孑” 博客,請務必保留此出處 http://zhangjunhd.blog.51cto.com/113473/126545

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved