gddzmr 发表于 2013-2-7 23:01:14

Spring2.5 IOC的简单实现

1、定义一个接口
package com.css.framework.context;public interface MyApplicationContext {/** * 获取bean的实例 * @param beanName * @return */public Object getBean(String beanName);}  2、Bean节点的描述文件
package com.css.framework.beans.factory.config;import java.util.ArrayList;import java.util.List;/** * Spring Bean 的描述文件 ** @author Administrator **/public class BeanDefinition {    //Bean节点中的id属性private String id;//Bean节点中的className属性private String className;/** * Bean节点中的属性描述property节点 */private List<PropertyDefinition> properties= new ArrayList<PropertyDefinition>();public String getId() {return id;}public BeanDefinition(String id, String className) {super();this.id = id;this.className = className;}public void setId(String id) {this.id = id;}public String getClassName() {return className;}public void setClassName(String className) {this.className = className;}    public List<PropertyDefinition> getProperties() {      return properties;    }    public void setProperties(List<PropertyDefinition> properties) {      this.properties = properties;    }} 
package com.css.framework.beans.factory.config;/**** <p>Title: property节点的描述文件 </p>* <p>Description: property节点的描述文件</p>* <p>Copyright: Copyright (c) 2010,CSS</p>* <p>Company: CSS</p>* @author 章殷* @date 2010-6-19* @version 1.0*/public class PropertyDefinition {    private String name;    private String ref;    private String value;    public String getValue() {      return value;    }    public void setValue(String value) {      this.value = value;    }    public PropertyDefinition(String name, String ref,String value) {      super();      this.name = name;      this.ref = ref;      this.value = value;    }    public String getName() {      return name;    }    public void setName(String name) {      this.name = name;    }    public String getRef() {      return ref;    }    public void setRef(String ref) {      this.ref = ref;    }} 
4、关键的实现类
package com.css.framework.context;import java.beans.IntrospectionException;import java.beans.Introspector;import java.beans.PropertyDescriptor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.net.URL;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import org.apache.commons.beanutils.ConvertUtils;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.XPath;import org.dom4j.io.SAXReader;import com.css.framework.annotation.MyResource;import com.css.framework.beans.factory.config.BeanDefinition;import com.css.framework.beans.factory.config.PropertyDefinition;import com.css.inter.IConstructorServiceBean;/**** <p>Title: 加载beans.xml文件 </p>* <p>Description: 加载xml文件,实例化文件中的Bean,并实现IOC</p>* <p>Copyright: Copyright (c) 2010,CSS</p>* <p>Company: CSS</p>* @author 章殷* @date 2010-6-19* @version 1.0*/public class MyClassPathXmlApplicationContext implements MyApplicationContext {    //所有的bean的描述文件列表    private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();    //定义所有的实例化的Bean    private Map<String, Object> sigletons = new HashMap<String, Object>();    public MyClassPathXmlApplicationContext(String filename) {      //加载配置文件      readXml(filename);      //实例化配置文件中的Bean      instanceBeans();      //使用注解方法进行注入      annotationInject();      //给Bean注入对象      injectObject();    }    /**   * <p> 使用注解的方式,将对象注入到实例Bean中。</p>   * @author 章 殷   * @date 2010-6-19   */    private void annotationInject() {      //循环所有实例化的Bean      for (String beanName : sigletons.keySet()) {            //获取Bean            Object bean = sigletons.get(beanName);            if (bean != null) {                try {                  //通过属性注入                  propertyInject(bean);                  //通过字段注入,包括字段的名称                  fieldInject(bean);                } catch (Exception e) {                  // TODO Auto-generated catch block                  e.printStackTrace();                }            }      }    }    /**   * <p> 通过属性名属性类型进行注入。</p>   * @param bean   * @throws IntrospectionException   * @throws IllegalAccessException   * @throws InvocationTargetException   * @author 章 殷   * @date 2010-6-19   */    private void propertyInject(Object bean) throws IntrospectionException, IllegalAccessException,                  InvocationTargetException {      //获取Bean的属性描述信息,通过setter方法进行注入      PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();      for (PropertyDescriptor propertyDesc : ps) {            //获取属性的setter方法            Method setter = propertyDesc.getWriteMethod();            //判断setter方法是否存储,时候存在MyResource注解            if (setter != null && setter.isAnnotationPresent(MyResource.class)) {                //获取属性的注解                MyResource resource = setter.getAnnotation(MyResource.class);                Object value = null;                //判断注解的name值是否为空,是否为空字符                if (resource.name() != null && !"".equals(resource.name())) {                  //从容器中取出name对应的对象                  value = sigletons.get(resource.name());                }                //下面的方法是通过属性名和属性的类型来查找实例Bean                else {                  //通过属性名来查找对应的实体Bean                  value = sigletons.get(propertyDesc.getName());                  if (value == null) {                        //通过属性的类型来查找对应的实体Bean                        for (String key : sigletons.keySet()) {                            // 循环所有的容器Bean,判断属性的类型和容器中的类型是否匹配                            if (propertyDesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())) {                              value = sigletons.get(key);                              break;                            }                        }                  }                }                setter.setAccessible(true);//如果是私有的方法,设置该值为true,就可以调用该setter方法                setter.invoke(bean, value); //把引用注入到Bean中            }      }    }    /**   * <p> 通过字段名进行实例注入。</p>   * @param bean   * @throws IllegalAccessException   * @author 章 殷   * @date 2010-6-19   */    private void fieldInject(Object bean) throws IllegalAccessException {      //获取Bean的所有字段信息      Field[] fields = bean.getClass().getDeclaredFields();      for (Field field : fields) {            //判断字段上是否存在MyResource注解            if (field.isAnnotationPresent(MyResource.class)) {                MyResource resource = field.getAnnotation(MyResource.class);                Object value = null;                //通过注解的Name属性来查询实体Bean                if (resource.name() != null && !"".equals(resource.name())) {                  value = sigletons.get(resource.name());                }                //通过字段的名称和字段类型来查询实例Bean                else {                  value = sigletons.get(field.getName());//通过属性名来查找                  if (value == null) {                        for (String key : sigletons.keySet()) {                            if (field.getType().isAssignableFrom(sigletons.get(key).getClass())) {                              value = sigletons.get(key);                              break;                            }                        }                  }                }                field.setAccessible(true);//设置私有的属性可以进行访问                field.set(bean, value); //将应用注入到属性中            }      }    }    /**   * <p> IOC的Spring的实现,该方法是用的是属性注入,可以注入依赖对象和基本数据类型。</p>   * @author 章 殷   * @date 2010-6-18   */    private void injectObject() {      System.out.println("============开始进行IOC注入==============");      //循环所有的beanDefines      for (BeanDefinition beanDefinition : beanDefines) {            //获取实例化后的bean            Object bean = sigletons.get(beanDefinition.getId());            if (bean != null) {                //获取实例化后的Bean的属性描述西西里                try {                  PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();                  for (PropertyDefinition propertyDefinition : beanDefinition.getProperties()) {                        for (PropertyDescriptor propertyDescriptor : ps) {                            Method setter = null;                            //判断Bean的属性名 与 property节点中的Name值是否相同                            if (propertyDefinition.getName().equals(propertyDescriptor.getName())) {                              setter = propertyDescriptor.getWriteMethod();//获取实例化Bean的set方法                              if (setter != null) {                                    Object value = null;                                    //如果引用存在,注入依赖对象                                    if (propertyDefinition.getRef() != null                                                    && !"".equals(propertyDefinition.getRef().trim())) {                                        value = sigletons.get(propertyDefinition.getRef());//从容器中获取ref的Bean                                    }                                    //注入基本数据类型                                    else {                                        value = ConvertUtils.convert(propertyDefinition.getValue(), propertyDescriptor                                                      .getPropertyType());                                    }                                    setter.setAccessible(true);//如果是私有的方法,设置该值为true,就可以调用该setter方法                                    setter.invoke(bean, value); //把引用注入到Bean中                                    System.out.println("注入[" + beanDefinition.getClassName() + "]的"                                                    + propertyDefinition.getName() + "属性成功");                              }                            }                        }                  }                } catch (Exception e) {                  System.err.println("注入【" + beanDefinition.getClassName() + "】时出错!");                }            }      }      System.out.println("============IOC注入完成==============");      System.out.println("");    }    /**   * <p> 实例化beanDefines中的所有Bean。</p>   * @author 章 殷   * @date 2010-6-18   */    private void instanceBeans() {      System.out.println("============开始实例化Bean==============");      for (BeanDefinition beanDefinition : beanDefines) {            try {                if (beanDefinition.getClassName() != null && !"".equals(beanDefinition.getClassName().trim())) {                  sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());                  System.out.println("实例化[" + beanDefinition.getClassName() + "]成功!");                }            } catch (Exception e) {                System.err.println("实例化[" + beanDefinition.getClassName() + "]时出错!");                e.printStackTrace();            }      }      System.out.println("============实例化Bean完成==============");      System.out.println("");    }    /**   * <p> 读取bean.xml文件,将xml的描述文件转换为java描述文件。</p>   * @param filename   * @author 章 殷   * @date 2010-6-18   */    @SuppressWarnings("unchecked")    private void readXml(String filename) {      System.out.println("============开始加载配置文件" + filename + "==============");      SAXReader saxReader = new SAXReader();      Document document = null;      URL xmlpath = this.getClass().getClassLoader().getResource(filename);      try {            document = saxReader.read(xmlpath);            Map<String, String> nsMap = new HashMap<String, String>();            nsMap.put("ns", "http://www.springframework.org/schema/beans");            //定位到beans/bean节点下            XPath xsub = document.createXPath("//ns:beans//ns:bean");            xsub.setNamespaceURIs(nsMap); //设置命名空间            List<Element> beans = xsub.selectNodes(document); //获取xml中所有的bean节点            for (Element element : beans) {                String id = element.attributeValue("id"); //获取属性id的值                String clazz = element.attributeValue("class");//获取属性class的值                BeanDefinition beanDefinition = new BeanDefinition(id, clazz);                //将Bean.xml文件中的property节点映射到beanDefinition                XPath propertySub = element.createXPath("ns:property"); //创建property的相对路径                propertySub.setNamespaceURIs(nsMap);                List<Element> propertis = propertySub.selectNodes(element);                for (Element property : propertis) {                  String propertyName = property.attributeValue("name");                  String propertyRef = property.attributeValue("ref");                  String propertyValue = property.attributeValue("value");                  beanDefinition.getProperties().add(                                    (new PropertyDefinition(propertyName, propertyRef, propertyValue)));                  System.out.println(">>>>:加载属性[" + clazz + ".(" + propertyRef + ")]成功!");                }                beanDefines.add(beanDefinition);                System.out.println(">>>>:加载类[" + clazz + "]成功!");            }      } catch (DocumentException e) {            System.err.println("加载配置文件<" + xmlpath + ">时出错!");            e.printStackTrace();      }      System.out.println("============配置文件" + filename + "加载完成==============");      System.out.println("");    }    /**   * 获取bean的实例   * @param beanName   * @return   */    public Object getBean(String beanName) {      return sigletons.get(beanName);    }    public static void main(String[] args) {      MyApplicationContext context = new MyClassPathXmlApplicationContext("beans.xml");      //      IPersonServiceBean personService = (IPersonServiceBean) context.getBean("personService");      //      personService.save();      IConstructorServiceBean constructor = (IConstructorServiceBean) context.getBean("constructorServiceBean");      constructor.save();    }} 
页: [1]
查看完整版本: Spring2.5 IOC的简单实现