Java代码实现依赖注入

java

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

这里将模仿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

以上是 Java代码实现依赖注入 的全部内容, 来源链接: utcz.com/z/393696.html

回到顶部