您的位置:首页 > 编程语言 > Java开发

Java代码实现依赖注入

2016-05-25 07:40 615 查看
(转载)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
[align=left]<?xml version="1.0" encoding="UTF-8"?>[/align]
[align=left] [/align]
[align=left]<beans>[/align]
[align=left]    <bean id="me" class="com.zj.ioc.di.imp.Person">[/align]
[align=left]       <property name="name">[/align]
[align=left]           <value>ZJ</value>[/align]
[align=left]       </property>[/align]
[align=left]       <property name="age">[/align]
[align=left]           <value>26</value>[/align]
[align=left]       </property>[/align]
[align=left]       <property name="height">[/align]
[align=left]           <value>1.78</value>[/align]
[align=left]       </property>[/align]
[align=left]    </bean>[/align]
[align=left]    <bean id="you" class="com.zj.ioc.di.imp.Person">[/align]
[align=left]       <property name="name">[/align]
[align=left]           <value>Mary</value>[/align]
[align=left]       </property>[/align]
[align=left]       <property name="age">[/align]
[align=left]           <value>27</value>[/align]
[align=left]       </property>[/align]
[align=left]       <property name="height">[/align]
[align=left]           <value>1.66</value>[/align]
[align=left]       </property>[/align]
[align=left]    </bean>[/align]
[align=left]    <bean id="myList" class="com.zj.ioc.di.imp.ListOne">[/align]
[align=left]       <property name="msg">[/align]
[align=left]           <list>[/align]
[align=left]              <value>java</value>[/align]
[align=left]              <value>c</value>[/align]
[align=left]              <value>windows</value>[/align]
[align=left]           </list>[/align]
[align=left]       </property>[/align]
[align=left]    </bean>[/align]
[align=left]    <bean id="mySet" class="com.zj.ioc.di.imp.SetOne">[/align]
[align=left]       <property name="msg">[/align]
[align=left]           <set>[/align]
[align=left]              <value>tom</value>[/align]
[align=left]              <value>cat</value>[/align]
[align=left]              <value>dog</value>[/align]
[align=left]           </set>[/align]
[align=left]       </property>[/align]
[align=left]    </bean>[/align]
[align=left]    <bean id="myMap" class="com.zj.ioc.di.imp.MapOne">[/align]
[align=left]       <property name="msg">[/align]
[align=left]           <map>[/align]
[align=left]              <entry key="c">[/align]
[align=left]                  <value>CHINA</value>[/align]
[align=left]              </entry>[/align]
[align=left]              <entry key="j">[/align]
[align=left]                  <value>JAPAN</value>[/align]
[align=left]              </entry>[/align]
[align=left]              <entry key="k">[/align]
[align=left]                  <value>KOREA</value>[/align]
[align=left]              </entry>[/align]
[align=left]           </map>[/align]
[align=left]       </property>[/align]
[align=left]    </bean>[/align]
[align=left]    <bean id="us" class="com.zj.ioc.di.imp.Persons">[/align]
[align=left]       <property name="i">[/align]
[align=left]           <ref bean="me" />[/align]
[align=left]       </property>[/align]
[align=left]       <property name="u">[/align]
[align=left]           <ref bean="you" />[/align]
[align=left]       </property>[/align]
[align=left]    </bean>[/align]
</beans>
 
依据setting.xml,这里将构建两个Person类的实例me和you:
Person.java
[align=left]package com.zj.ioc.di.imp;[/align]
[align=left] [/align]
[align=left]public class Person {[/align]
[align=left]    private String name;[/align]
[align=left]    private int age;[/align]
[align=left]    private float height;[/align]
[align=left] [/align]
[align=left]    public String getName() {return name;}[/align]
    public void setName(String
name) {this.name = name;}
[align=left]    public int getAge() {return age;}[/align]
    public void setAge(int age)
{this.age = age;}
[align=left]    public float getHeight() {return height;}[/align]
    public void setHeight(float height)
{this.height = height;}
[align=left]}[/align]
紧接着,构建一个ListOne的实例myList:
ListOne.java
[align=left]package com.zj.ioc.di.imp;[/align]
[align=left]import java.util.List;[/align]
[align=left] [/align]
[align=left]public class ListOne {[/align]
[align=left]    private List<String> msg;[/align]
[align=left] [/align]
[align=left]    public List<String> getMsg() {return msg;}[/align]
    public void setMsg(List<String>
msg) {this.msg = msg;}
[align=left]}[/align]
紧接着,构建一个SetOne的实例mySet:
SetOne.java
[align=left]package com.zj.ioc.di.imp;[/align]
[align=left]import java.util.Set;[/align]
[align=left] [/align]
[align=left]public class SetOne {[/align]
[align=left]    private Set<String> msg;[/align]
[align=left] [/align]
[align=left]    public Set<String> getMsg() {return msg;}[/align]
    public void setMsg(Set<String>
msg) {this.msg = msg;}
}
紧接着,构建一个MapOne的实例myMap:
MapOne.java
[align=left]package com.zj.ioc.di.imp;[/align]
[align=left]import java.util.Map;[/align]
[align=left] [/align]
[align=left]public class MapOne {[/align]
[align=left]    private Map<String,String> msg;[/align]
[align=left] [/align]
[align=left]    public Map<String, String> getMsg() {return msg;}[/align]
    public void setMsg(Map<String,
String> msg) {this.msg = msg;}
}
最后构建一个Persons类的实例us,其中包含me和you两个已经构建好的对象:
Persons.java
[align=left]package com.zj.ioc.di.imp;[/align]
[align=left] [/align]
[align=left]public class Persons {[/align]
[align=left]    private Person i;[/align]
[align=left]    private Person u;[/align]
[align=left]   [/align]
[align=left]    public Person getI() {return i;}[/align]
    public void setI(Person i)
{this.i = i;}
[align=left]    public Person getU() {return u;}[/align]
    public void setU(Person u)
{this.u = u;}
[align=left]}[/align]
 
主要的实现机制是(代码BeanFactory.java以及工程见附件),
1.通过一个HashMap保存构造好的对象,key就是bean的id属性,value就是这个对象;
private Map<String, Object> beanMap = new HashMap<String,
Object>();
……
[align=left]public Object getBean(String beanId) {[/align]
[align=left]    Object obj = beanMap.get(beanId);[/align]
[align=left]    return obj;[/align]
}
查询时
[align=left]BeanFactory factory = new BeanFactory();[/align]
[align=left]factory.init("setting.xml");[/align]
Person p1 = (Person) factory.getBean("me");
 
2.init方法读入配置文件setting.xml,并直接定位到beans下的bean元素,并实例化一个ElementHandler对其处理。
public void init(String xmlUri) throws Exception
{
[align=left]    SAXReader saxReader = new SAXReader();[/align]
[align=left]    File file = new File(xmlUri);[/align]
[align=left]    try {[/align]
[align=left]       saxReader.addHandler("/beans/bean", new BeanHandler());[/align]
[align=left]       saxReader.read(file);[/align]
[align=left]    } catch (DocumentException e) {[/align]
[align=left]       System.out.println(e.getMessage());[/align]
[align=left]    }[/align]
}
 
3.ElementHandler,dom4j的ElementHandler接口有两个方法,一个是onStart(),它主要用于处理该元素的属性以及动态增加新的Handler类;另一个是onEnd(),它主要用于获得该元素的Text文本以及删除已添加的Handler。
BeanHandler
private class BeanHandler implements ElementHandler
{
[align=left]    Object obj = null;[/align]
[align=left] [/align]
    public void .Start(ElementPath
path) {
[align=left]       Element beanElement = path.getCurrent();[/align]
[align=left]       Attribute classAttribute = beanElement.attribute("class");[/align]
[align=left] [/align]
[align=left]       Class<?> bean = null;[/align]
[align=left]       try {[/align]
[align=left]           bean = Class.forName(classAttribute.getText());[/align]
[align=left]       } catch (ClassNotFoundException e) {[/align]
[align=left]           e.printStackTrace();[/align]
[align=left]       }[/align]
[align=left]       Field fields[] = bean.getDeclaredFields();[/align]
[align=left]       Map<String, Field> mapField = new HashMap<String, Field>();[/align]
[align=left]       for (Field field : fields)[/align]
[align=left]           mapField.put(field.getName(), field);[/align]
[align=left]       try {[/align]
[align=left]           obj = bean.newInstance();[/align]
[align=left]       } catch (InstantiationException e) {[/align]
[align=left]           e.printStackTrace();[/align]
[align=left]       } catch (IllegalAccessException e) {[/align]
[align=left]           e.printStackTrace();[/align]
[align=left]       }[/align]
[align=left] [/align]
[align=left]       path.addHandler("property", new PropertyHandler(mapField, obj));[/align]
[align=left]    }[/align]
[align=left] [/align]
    public void .End(ElementPath
path) {
[align=left]       Element beanElement = path.getCurrent();[/align]
[align=left]       Attribute idAttribute = beanElement.attribute("id");[/align]
[align=left]       beanMap.put(idAttribute.getText(), obj);[/align]
[align=left]       path.removeHandler("property");[/align]
[align=left]    }[/align]
}
   
PropertyHandler
private class PropertyHandler implements ElementHandler
{
[align=left]    Map<String, Field> mapField;[/align]
[align=left]    Object obj;[/align]
[align=left] [/align]
[align=left]    public PropertyHandler(Map<String, Field> mapField, Object obj) {[/align]
[align=left]       this.mapField = mapField;[/align]
[align=left]       this.obj = obj;[/align]
[align=left]    }[/align]
[align=left] [/align]
    public void .Start(ElementPath
path) {
[align=left]       Element propertyElement = path.getCurrent();[/align]
[align=left]       Attribute nameAttribute = propertyElement.attribute("name");[/align]
[align=left]       path.addHandler("value", new ValueHandler(mapField, obj,[/align]
[align=left]              nameAttribute));[/align]
[align=left]       path.addHandler("list", new ListHandler(mapField, obj,[/align]
[align=left]              nameAttribute));[/align]
[align=left]       path.addHandler("set", new SetHandler(mapField, obj,[/align]
[align=left]              nameAttribute));[/align]
[align=left]       path.addHandler("map", new MapHandler(mapField, obj,[/align]
[align=left]              nameAttribute));[/align]
[align=left]       path.addHandler("ref", new RefHandler(mapField, obj,[/align]
[align=left]              nameAttribute));[/align]
[align=left]    }[/align]
[align=left] [/align]
    public void .End(ElementPath
path) {
[align=left]       path.removeHandler("value");[/align]
[align=left]       path.removeHandler("list");[/align]
[align=left]       path.removeHandler("set");[/align]
[align=left]       path.removeHandler("map");[/align]
[align=left]       path.removeHandler("ref");[/align]
[align=left]    }[/align]
}
 
根据setting.xml,我们可以得到各种注入元素的Handler类处理流程图。



 
4. setFieldValue()基于反射机制和相应的类信息得到Field的类型,并根据setting.xml设置它的值。
private void setFieldValue(Object obj, Field field, String value)
{
[align=left]    String fieldType = field.getType().getSimpleName();[/align]
[align=left]    try {[/align]
[align=left]       if (fieldType.equals("int"))[/align]
[align=left]           field.setInt(obj, new Integer(value));[/align]
[align=left]       else if (fieldType.equals("float"))[/align]
[align=left]           field.setFloat(obj, new Float(value));[/align]
[align=left]       else if (fieldType.equals("boolean"))[/align]
[align=left]           field.setBoolean(obj, new Boolean(value));[/align]
[align=left]       else if (fieldType.equals("char"))[/align]
[align=left]           field.setChar(obj, value.charAt(0));[/align]
[align=left]       else if (fieldType.equals("double"))[/align]
[align=left]           field.setDouble(obj, new Double(value));[/align]
[align=left]       else if (fieldType.equals("long"))[/align]
[align=left]           field.setLong(obj, new Long(value));[/align]
[align=left]       else[/align]
[align=left]           field.set(obj, value);[/align]
[align=left]    } catch (IllegalArgumentException e) {[/align]
[align=left]       e.printStackTrace();[/align]
[align=left]    } catch (IllegalAccessException e) {[/align]
[align=left]       e.printStackTrace();[/align]
[align=left]    }[/align]
[align=left]}[/align]
[align=left] [/align]
private void setFieldValue(Object obj, Field field, List<String>
value) {
[align=left]    try {[/align]
[align=left]       field.set(obj, value);[/align]
[align=left]    } catch (IllegalArgumentException e) {[/align]
[align=left]       e.printStackTrace();[/align]
[align=left]    } catch (IllegalAccessException e) {[/align]
[align=left]       e.printStackTrace();[/align]
[align=left]    }[/align]
}
 
5.测试
public static void main(String[]
args) {
[align=left]    try {[/align]
[align=left]       BeanFactory factory = new BeanFactory();[/align]
[align=left]       factory.init("setting.xml");[/align]
[align=left] [/align]
[align=left]       Person p1 = (Person) factory.getBean("me");[/align]
[align=left]       System.out.print(p1.getName() + " ");[/align]
[align=left]       System.out.print(p1.getAge() + " ");[/align]
[align=left]       System.out.println(p1.getHeight());[/align]
[align=left] [/align]
[align=left]       Person p2 = (Person) factory.getBean("you");[/align]
[align=left]       System.out.print(p2.getName() + " ");[/align]
[align=left]       System.out.print(p2.getAge() + " ");[/align]
[align=left]       System.out.println(p2.getHeight());[/align]
[align=left] [/align]
[align=left]       ListOne list = (ListOne) factory.getBean("myList");[/align]
[align=left]       System.out.println(list.getMsg());[/align]
[align=left] [/align]
[align=left]       SetOne set = (SetOne) factory.getBean("mySet");[/align]
[align=left]       System.out.println(set.getMsg());[/align]
[align=left] [/align]
[align=left]       MapOne map = (MapOne) factory.getBean("myMap");[/align]
[align=left]       System.out.println(map.getMsg());[/align]
[align=left] [/align]
[align=left]       Persons us = (Persons) factory.getBean("us");[/align]
[align=left]       System.out.println(us.getI());[/align]
[align=left]       System.out.println(us.getU());[/align]
[align=left]    } catch (Exception e) {[/align]
[align=left]       e.printStackTrace();[/align]
[align=left]    }[/align]
}
测试结果:
[align=left]ZJ 26 1.78[/align]
[align=left]Mary 27 1.66[/align]
[align=left][java, c, windows][/align]
[align=left][cat, tom, dog][/align]
[align=left]{c=CHINA, j=JAPAN, k=KOREA}[/align]
[align=left]com.zj.ioc.di.imp.Person@1a5ab41[/align]
com.zj.ioc.di.imp.Person@18e3e60

本文出自 “子 孑” 博客,请务必保留此出处http://zhangjunhd.blog.51cto.com/113473/126545
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: