Java代码实现依赖注入

http://zhangjunhd.blog.51cto.com/113473/126545java

 

这里将模仿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
相关文章
相关标签/搜索