自定义框架技术基础

自定义框架技术基础之一——自己实现一个Spring的IOC(控制反转)BeanFactory

 
一、 创建一个辅助类
实体类 Student

二、 创建一个 xml 文件
Src/com/jisong/ioc/Zjsioc.Xml 文件内容
<?xml version="1.0" encoding="UTF-8"?>

<beans>
    <bean id="student" class="com.jisong.ioc.entity.Student">
           <property name="no" type="java.lang.String">
                  <value>1</value>
           </property>
       <property name="name" type="java.lang.String">
           <value> 石头 </value>
       </property>
    </bean>
    <bean id="student2" class="com.jisong.ioc.entity.Student">
           <property name="no" type="java.lang.String">
                  <value>44</value>
           </property>
       <property name="name" type="java.lang.String">
           <value> 范跑跑 </value>
       </property>
    </bean>
</beans>

三、 创建一个 BeanFactoryByReflect 类,并在 Main 方法中测试

package com.jisong.ioc;

import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.jisong.ioc.entity.Student;

/**
* Bean 工厂类。根据指定格式的 xml 文件,通过反射包 (java.lang.reflect) 创建对象并给属性赋值
* @author 周继松 2008-6-30
*/
public class BeanFactoryByReflect {

       /**
        * beanMap, 用来存放所有根据 xml 配置文件实例化的对象
        */
       private Map<String, Object> beanMap = new HashMap<String, Object>();

       /**
        * 初始化。在 class 路径下查找指定的 xml 文件,并初始化 bean 工厂
        * @param xmlUri xml 文件在 classpath 的相对路径。例如: /com/jisong/ioc/zjsioc.xml
        */
       public void init(String xmlUri) throws Exception{
              try {

                     //1. 根据根据 xml 的相对路径,读取 xml 文件,并获得 xml 文件的根元素
                     //1.1 根据 xml 的相对路径,获得一个输入流
                     SAXReader reader = new SAXReader();// 创建一个解析器对象
//                   ClassLoader classLoader = Thread.currentThread()
//                                 .getContextClassLoader();// 获得当前线程的类加载器
//                   InputStream in = classLoader.getResourceAsStream(xml);// 通过类加载器,获得指定相对路径下文件的输入流

                     InputStream in=this.getClass().getResourceAsStream(xmlUri);// 通过当前 Class 对象,获得指定相对路径下文件的输入流

                     //1.2. 从输入流获得 document 对象
                     Document doc = reader.read(in);// 通过解析器对象,读取输入流并转换为一个 Document 对象

                     //1.3. document 对象,获得 xml 文件的根元素
                     Element root = doc.getRootElement();// 获得根元素
                     Element elBean = null;// 定义 bean 元素变量

                     // 2. 遍历 bean 元素,实例化所有 bean 并初始化其属性值,然后保存在 beanMap
                     for (Iterator iteBean = root.elementIterator("bean"); iteBean
                                   .hasNext();) {
                            elBean = (Element) iteBean.next();// 获得 bean 元素

                            // 2.1 获得 bean 的属性 id class
                            Attribute atrId = elBean.attribute("id");
                            Attribute atrClass = elBean.attribute("class");

                            // 2.2 通过 Java 反射机制,通过 class 的名称获取 Class 对象
                            Class clsBean = Class.forName(atrClass.getText());

                            // 2.3 获得指定 class 的所有属性描述,以初始化其所有属性

                            // 获取其属性描述数组
                            Field pds[] = clsBean.getDeclaredFields();

                            // 将属性描述数组转换为 HashMap, 这样下一步在设置属性的值的时候,速度更快
                            Map<String, Field> mapProp = new HashMap<String, Field>();
                            for (Field pd : pds) {
                                   mapProp.put(pd.getName(), pd);
                            }

                            // 2.4 创建指定 class 的实例 obj
                            Object obj = clsBean.newInstance();
                            Method mSet = null;// 定义 set 方法变量

                            // 2.5 遍历该 bean property 属性,并通过 Java 反射调用其 set 方法,设置 obj 的所有属性的值
                            for (Iterator iteProp = elBean.elementIterator("property"); iteProp
                                          .hasNext();) {
                                   // 2.5.1 获得属性元素
                                   Element elProp = (Element) iteProp.next();

                                   // 2.5.2 获取该 property name 属性
                                   Attribute atrName = elProp.attribute("name");
                                   Attribute atrType= elProp.attribute("type");

                                   Class clsType=Class.forName(atrType.getText());

                                   // 2.5.3 获取该 property 的子元素 value 的值
                                   String strValue = null;
                                   // 正常情况下, name 元素只能有一个 value 属性
                                   for (Iterator iteValue = elProp.elementIterator("value"); iteValue
                                                 .hasNext();) {
                                          Element elValue = (Element) iteValue.next();
                                          strValue = elValue.getText();
                                          break;
                                   }

                                   // 2.5.4 调用对象属性名的 set 方法,该指定的属性赋值
                                   Field tmpPd=mapProp.get(atrName.getValue());
                                   if(tmpPd!=null){
                                          String fieldName=tmpPd.getName();
                                          String methodName="set"+ fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
                                          mSet=clsBean.getMethod(methodName, clsType);// 取得指定的 set 方法
                                          mSet.invoke(obj, strValue);// 通过 Java 反射,调用指定对象的方法并传参(即调用指定的 set 方法)
                                   }
                            }
                            // 将对象放入 beanMap 中,其中 key id 值, value obj 对象
                            beanMap.put(atrId.getText(), obj);
                     }
              } catch (Exception e) {
                     throw e;
              }
       }

       /**
        * 通过 id 获取 bean 的对象 .
        *
        * @param beanId
        *            xml 文件中 bean 元素的 id 属性值
        * @return 返回对应对象
        */
       public Object getBean(String beanId) {
              Object obj = beanMap.get(beanId);
              return obj;
       }

       /**
        * 测试方法 .
        */
       public static void main(String[] args) {
              try {
                     BeanFactoryByReflect factory = new BeanFactoryByReflect();
                     factory.init("/com/jisong/ioc/zjsioc.xml");
                     Student stud = (Student) factory.getBean("student");
                     System.out.println("mso-tab-count: 3">                     System.out.println("mso-tab-count: 3">                     System.out.println("mso-tab-count: 3">
                     stud=(Student)factory.getBean("student2");

自定义框架技术基础之一——自己实现一个Spring的IOC(控制反转)BeanFactory

-    发表于2008年11月29日 20:31 阅读(80) 评论( 7) 分类: Java技术
举报举报
一、 创建一个辅助类
实体类 Student

二、 创建一个 xml 文件
Src/com/jisong/ioc/Zjsioc.Xml 文件内容
<?xml version="1.0" encoding="UTF-8"?>

<beans>
    <bean id="student" class="com.jisong.ioc.entity.Student">
           <property name="no" type="java.lang.String">
                  <value>1</value>
           </property>
       <property name="name" type="java.lang.String">
           <value> 石头 </value>
       </property>
    </bean>
    <bean id="student2" class="com.jisong.ioc.entity.Student">
           <property name="no" type="java.lang.String">
                  <value>44</value>
           </property>
       <property name="name" type="java.lang.String">
           <value> 范跑跑 </value>
       </property>
    </bean>
</beans>

三、 创建一个 BeanFactoryByReflect 类,并在 Main 方法中测试

package com.jisong.ioc;

import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.jisong.ioc.entity.Student;

/**
* Bean 工厂类。根据指定格式的 xml 文件,通过反射包 (java.lang.reflect) 创建对象并给属性赋值
* @author 周继松 2008-6-30
*/
public class BeanFactoryByReflect {

       /**
        * beanMap, 用来存放所有根据 xml 配置文件实例化的对象
        */
       private Map<String, Object> beanMap = new HashMap<String, Object>();

       /**
        * 初始化。在 class 路径下查找指定的 xml 文件,并初始化 bean 工厂
        * @param xmlUri xml 文件在 classpath 的相对路径。例如: /com/jisong/ioc/zjsioc.xml
        */
       public void init(String xmlUri) throws Exception{
              try {

                     //1. 根据根据 xml 的相对路径,读取 xml 文件,并获得 xml 文件的根元素
                     //1.1 根据 xml 的相对路径,获得一个输入流
                     SAXReader reader = new SAXReader();// 创建一个解析器对象
//                   ClassLoader classLoader = Thread.currentThread()
//                                 .getContextClassLoader();// 获得当前线程的类加载器
//                   InputStream in = classLoader.getResourceAsStream(xml);// 通过类加载器,获得指定相对路径下文件的输入流

                     InputStream in=this.getClass().getResourceAsStream(xmlUri);// 通过当前 Class 对象,获得指定相对路径下文件的输入流

                     //1.2. 从输入流获得 document 对象
                     Document doc = reader.read(in);// 通过解析器对象,读取输入流并转换为一个 Document 对象

                     //1.3. document 对象,获得 xml 文件的根元素
                     Element root = doc.getRootElement();// 获得根元素
                     Element elBean = null;// 定义 bean 元素变量

                     // 2. 遍历 bean 元素,实例化所有 bean 并初始化其属性值,然后保存在 beanMap
                     for (Iterator iteBean = root.elementIterator("bean"); iteBean
                                   .hasNext();) {
                            elBean = (Element) iteBean.next();// 获得 bean 元素

                            // 2.1 获得 bean 的属性 id class
                            Attribute atrId = elBean.attribute("id");
                            Attribute atrClass = elBean.attribute("class");

                            // 2.2 通过 Java 反射机制,通过 class 的名称获取 Class 对象
                            Class clsBean = Class.forName(atrClass.getText());

                            // 2.3 获得指定 class 的所有属性描述,以初始化其所有属性

                            // 获取其属性描述数组
                            Field pds[] = clsBean.getDeclaredFields();

                            // 将属性描述数组转换为 HashMap, 这样下一步在设置属性的值的时候,速度更快
                            Map<String, Field> mapProp = new HashMap<String, Field>();
                            for (Field pd : pds) {
                                   mapProp.put(pd.getName(), pd);
                            }

                            // 2.4 创建指定 class 的实例 obj
                            Object obj = clsBean.newInstance();
                            Method mSet = null;// 定义 set 方法变量

                            // 2.5 遍历该 bean property 属性,并通过 Java 反射调用其 set 方法,设置 obj 的所有属性的值
                            for (Iterator iteProp = elBean.elementIterator("property"); iteProp
                                          .hasNext();) {
                                   // 2.5.1 获得属性元素
                                   Element elProp = (Element) iteProp.next();

                                   // 2.5.2 获取该 property name 属性
                                   Attribute atrName = elProp.attribute("name");
                                   Attribute atrType= elProp.attribute("type");

                                   Class clsType=Class.forName(atrType.getText());

                                   // 2.5.3 获取该 property 的子元素 value 的值
                                   String strValue = null;
                                   // 正常情况下, name 元素只能有一个 value 属性
                                   for (Iterator iteValue = elProp.elementIterator("value"); iteValue
                                                 .hasNext();) {
                                          Element elValue = (Element) iteValue.next();
                                          strValue = elValue.getText();
                                          break;
                                   }

                                   // 2.5.4 调用对象属性名的 set 方法,该指定的属性赋值
                                   Field tmpPd=mapProp.get(atrName.getValue());
                                   if(tmpPd!=null){
                                          String fieldName=tmpPd.getName();
                                          String methodName="set"+ fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
                                          mSet=clsBean.getMethod(methodName, clsType);// 取得指定的 set 方法
                                          mSet.invoke(obj, strValue);// 通过 Java 反射,调用指定对象的方法并传参(即调用指定的 set 方法)
                                   }
                            }
                            // 将对象放入 beanMap 中,其中 key id 值, value obj 对象
                            beanMap.put(atrId.getText(), obj);
                     }
              } catch (Exception e) {
                     throw e;
              }
       }

       /**
        * 通过 id 获取 bean 的对象 .
        *
        * @param beanId
        *            xml 文件中 bean 元素的 id 属性值
        * @return 返回对应对象
        */
       public Object getBean(String beanId) {
              Object obj = beanMap.get(beanId);
              return obj;
       }

       /**
        * 测试方法 .
        */
       public static void main(String[] args) {
              try {
                     BeanFactoryByReflect factory = new BeanFactoryByReflect();
                     factory.init("/com/jisong/ioc/zjsioc.xml");
                     Student stud = (Student) factory.getBean("student");
                     System.out.println("mso-tab-count: 3">                     System.out.println("mso-tab-count: 3">                     System.out.println("mso-tab-count: 3">
                     stud=(Student)factory.getBean("student2");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值