gdufo

           

          java的反射和代理實現IOC模式 模擬spring

          IOC(Inverse of Control)可翻譯為“控制反轉”,但大多數人都習慣將它稱為“依賴注入”。在Spring中,通過IOC可以將實現類、參數信息等配置在其對應的配置文件中,那么當需要更改實現類或參數信息時,只需要修改配置文件即可,這種方法在上例的基礎上更進一步的降低了類與類之間的耦合。我們還可以對某對象所需要的其它對象進行注入,這種注入都是在配置文件中做的,Spring的IOC的實現原理利用的就是Java的反射機制, Spring還充當了工廠的角色,我們不需要自己建立工廠類。Spring的工廠類會幫我們完成配置文件的讀取、利用反射機制注入對象等工作,我們可以通過bean的名稱獲取對應的對象。
          下面讓我們看看如下的模擬Spring的bean工廠類:
          package org.amigo.reflection;
          import java.io.InputStream;
          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;
          /**
          * bean工廠類.   
          * @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
          * Creation date: 2007-10-6 - 上午10:04:41
          */
          public class BeanFactory {
                 private Map<String, Object> beanMap = new HashMap<String, Object>();
                 /**
                 * bean工廠的初始化.
                 * @param xml xml配置文件
                 */
                 public void init(String xml) {
                        try {
                               //讀取指定的配置文件
                               SAXReader reader = new SAXReader();
                               ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
                               //從class目錄下獲取指定的xml文件
                               InputStream ins = classLoader.getResourceAsStream(xml);
                               Document doc = reader.read(ins);
                               Element root = doc.getRootElement();  
                               Element foo;
                              
                               //遍歷bean
                               for (Iterator i = root.elementIterator("bean"); i.hasNext();) {  
                                      foo = (Element) i.next();
                                      //獲取bean的屬性id和class
                                      Attribute id = foo.attribute("id");  
                                      Attribute cls = foo.attribute("class");
                                     
                                      //利用Java反射機制,通過class的名稱獲取Class對象
                                      Class bean = Class.forName(cls.getText());
                                     
                                      //獲取對應class的信息
                                      java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(bean);
                                      //獲取其屬性描述
                                      java.beans.PropertyDescriptor pd[] = info.getPropertyDescriptors();
                                      //設置值的方法
                                      Method mSet = null;
                                      //創建一個對象
                                      Object obj = bean.newInstance();
                                     
                                      //遍歷該bean的property屬性
                                      for (Iterator ite = foo.elementIterator("property"); ite.hasNext();) {  
                                             Element foo2 = (Element) ite.next();
                                             //獲取該property的name屬性
                                             Attribute name = foo2.attribute("name");
                                             String value = null;
                                            
                                             //獲取該property的子元素value的值
                                             for(Iterator ite1 = foo2.elementIterator("value"); ite1.hasNext();) {
                                                    Element node = (Element) ite1.next();
                                                    value = node.getText();
                                                    break;
                                             }
                                            
                                             for (int k = 0; k < pd.length; k++) {
                                                    if (pd[k].getName().equalsIgnoreCase(name.getText())) {
                                                           mSet = pd[k].getWriteMethod();
                                                           //利用Java的反射極致調用對象的某個set方法,并將值設置進去
                                                           mSet.invoke(obj, value);
                                                    }
                                             }
                                      }
                                     
                                      //將對象放入beanMap中,其中key為id值,value為對象
                                      beanMap.put(id.getText(), obj);
                               }
                        } catch (Exception e) {
                               System.out.println(e.toString());
                        }
                 }
                
                 /**
                 * 通過bean的id獲取bean的對象.
                 * @param beanName bean的id
                 * @return 返回對應對象
                 */
                 public Object getBean(String beanName) {
                        Object obj = beanMap.get(beanName);
                        return obj;
                 }
                
                 /**
                 * 測試方法.
                 * @param args
                 * @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
                 * Creation date: 2007-10-6 - 上午11:21:14
                 */
                 public static void main(String[] args) {
                        BeanFactory factory = new BeanFactory();
                        factory.init("config.xml");
                        JavaBean javaBean = (JavaBean) factory.getBean("javaBean");
                        System.out.println("userName=" + javaBean.getUserName());
                        System.out.println("password=" + javaBean.getPassword());
                 }
          }
                 該類的init(xml)方法,通過指定的xml來給對象注入屬性,為了對該類進行測試,我還需要新建一個JavaBean和在src目錄下新建一個名為config.xml的配置文件。JavaBean的內容如下:
          package org.amigo.reflection;
          /**
          *
          * 簡單的bean,用于測試  
          * @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
          * Creation date: 2007-10-6 - 上午11:24:30
          */
          public class JavaBean {
                 private String userName;
                 private String password;
                
              public String getPassword() {
                        return password;
                 }
                 public String getUserName() {
                        return userName;
                 }
                 public void setUserName(String userName) {
                        this.userName = userName;
                 }
                 public void setPassword(String password) {
                        this.password = password;
                 }
          }
          這個簡單bean對象中有兩個屬性,分別為userName和password,下面我們在配置文件config.xml中對其屬性注入對應的屬性值。配置文件內容如下:
          <?xml version="1.0" encoding="UTF-8"?>
          <beans>
              <bean id="javaBean" class="org.amigo.reflection.JavaBean">
                 <property name="userName">
                     <value>阿蜜果</value>
                 </property>
                 <property name="password">
                     <value>12345678</value>
                 </property>
              </bean>
          </beans>
          類與配置文件都完成后,可以運行BeanFactory.java文件,控制臺顯示內容為:
          userName=阿蜜果
          password=12345678
          可以看到,雖然在main()方法中沒有對屬性賦值,但屬性值已經被注入,在BeanFactory類中的Class bean = Class.forName(cls.getText());通過類名來獲取對應的類,mSet.invoke(obj, value);通過invoke方法來調用特定對象的特定方法,實現的原理都是基于Java的反射機制,在此我們有一次見證了Java反射機制的強大。
          當然,這只是對IOC的一個簡單演示,在Spring中,情況要復雜得多,例如,可以一個bean引用另一個bean,還可以有多個配置文件、通過多種方式載入配置文件等等。不過原理還是采用Java的反射機制來實現IOC的。
          四. 總結
          在本文中,筆者通過講述Java反射機制概述與初探、IOC使用的背景、IOC粉墨登場等內容,演示了Java反射機制API的強大功能,并通過編寫自己的簡單的IOC框架,讓讀者更好的理解了IOC的實現原理。
          本文通過IOC的一個簡要實現實例,模擬了Spring中IOC的實現,雖然只是完成了Spring中依賴注入的一小部分工作,但是很好的展現了Java反射機制在Spring中的應用,能使我們能更好的從原理上了解IOC的實現,也能為我們實現自己的準Spring框架提供

          轉自網絡 

          posted on 2008-08-19 08:17 gdufo 閱讀(1017) 評論(0)  編輯  收藏 所屬分類: Spring

          導航

          統計

          常用鏈接

          留言簿(6)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          收藏夾

          Hibernate

          友情鏈接

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 阳谷县| 保山市| 邮箱| 北流市| 龙里县| 县级市| 阿克苏市| 双辽市| 灯塔市| 靖州| 修文县| 资源县| 清流县| 彩票| 蓬溪县| 宜黄县| 洪泽县| 礼泉县| 莱西市| 大关县| 宝应县| 九寨沟县| 通化市| 崇左市| 凤庆县| 平顺县| 柘荣县| 从化市| 鲁甸县| 河北省| 棋牌| 栾城县| 新巴尔虎右旗| 阿鲁科尔沁旗| 凭祥市| 长宁县| 安陆市| 兰考县| 许昌县| 清徐县| 贵南县|