zoukankan      html  css  js  c++  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
  • 相关阅读:
    使用Cmake生成makefile
    c++模板类(一)理解编译器的编译模板过程
    C++ 模板
    c++/c 获取cpp文件行号跟文件名
    java获取代码调用位置信息
    android获取手机ip
    Cocos2d-html5游戏开发,常用工具集合
    cocos2d-html5基础
    Cocos2d-x-html5之HelloWorld深入分析与调试
    基于ndk_r7_windows编译实现ndk项目,不需要cygwin
  • 原文地址:https://www.cnblogs.com/leaven/p/3554826.html
Copyright © 2011-2022 走看看