1. 程式人生 > >Java反射、泛型和註解實戰之Spring核心注入IOC的實現

Java反射、泛型和註解實戰之Spring核心注入IOC的實現

一.前言
通過前兩篇文章的學習,我們已經對Java中這三個模組的知識有了初步的瞭解。為了將鞏固之前的知識,今天我們將綜合運用這三個模組的知識,來實現一個類似Spring中注入的案例。
二.專案結構
簡單的描繪了一下專案流程圖,如下
這裡寫圖片描述
流程說明:Ipraser是一個介面,其中定義了一個praserBeans(),返回的是List<Bean>集合,兩種資料來源分別為XML和註解,對應的是AnnotationPraser和XmlPraser兩個解析註解和XML的類,兩個類都實現了Ipraser介面,與AnnotationPraser關聯的是解析註解相關的輔助類,包括代表各種資料型別的各種註解定義類,還有一個是ClassUtil類用來獲取指定包下的Java類。解析資料必須的類有Exception用於定義解析中出現的各種異常,Generator定義了生成類名和方法名稱的介面,有兩個實現類,Constant用於定義各種常量,Property代表一個bean中定義的所有屬性,CollectionProperty是其中的一個變數,代表Java類中的集合屬性,BaseProperty繼承自CollectionProperty,定義了List、Map和Set中共有的屬性,ListProperty、MapProperty和SetProperty繼承自BaseProperty分別定義了List、Map和Set中特有的屬性。
Config等類使用Builder方式定義了外界的一些配置資訊,其中IConfigBuilder是抽象建造,定義了建造流程,Config是最終組裝的資訊類,其中的內部類ConfigBuilder是具體的構建類,所有資訊最終被封裝在ConfigEntry中。Method中是ConfigEntry的一個屬性,通過列舉形式定義了XML和annotation兩種注入方式。
PraserFactory是一個解析器的工廠類,使用策略方式通過引數Method返回不同的具體解析類。
ObjectFactory通過引數List<Bean>作為資料來源生成各種物件,類的出口是將生成的物件放入ObjectPool物件池中,該物件實現Ipool介面定義了存取物件的規範,ObjectManager是外界訪問的類,可以設定載入引數,然後呼叫各個PraserFactory、ObjectFactory完成物件的生成,還定義了訪問物件的方法,通過訪問物件Pool獲取物件,然後返回。
三.具體實現


(1).XML讀取
首先來看XML解析部分,對應的是XmlPraser,返回的是List<Bean>資料型別。我們這裡使用Dom4j這個包來進行XML的解析,XML是和Spring中使用的XML基本一致,下面是縮略的xml。

<bean id="Family" class="com.sunjinxi.spring.test.Family">
        <property name="number" value="4" />
        <property name="familySalary" value="258.6" />
<!--set和List完全相同 set代表set結合,List代表List集合--> <property name="employs"> <list> <!--驗證List中存放字串 可以指定所有基本型別的值 --> <value>張三丰</value> <value>李白</value> </list
>
</property> <!-- List巢狀bean List存放的是引用型別--> <property name="employs2"> <list> <bean></bean> <bean></bean> </list> </property> <!-- List巢狀引用,List存放的是引用--> <property name="employs3"> <list> <ref></ref> <ref></ref> </list> </property> <!-- List巢狀List或者Set或者Map,List中存放的是List,Set或者Map--> <property name="employs3"> <list> <List></List> <set></set> <map><entry> <key></key> <value></value></entry></map> </list> <!--map標籤對應HashMap--> <property name="map"> <map> <!--entry標籤對應HashMap中的一個對映,key代表鍵,Value代表值--> <entry><key>123</key><value>100</value></entry> <!--Map中的Key可以為引用型別,對應<value-ref>和<value-bean>標籤--> <entry><key>address1</key> <value_ref>user1</value_ref></entry> <value_bean><bean></bean></value_bean> </property> <!-- set標籤代表無序集合,支援基本型別,引用型別,List,Set,Map型別,配置和List標籤完全相同---> <set></set>

我們的注入在XML中支援基本型別的值,List集合,Set集合,Map型別,List巢狀List,Set和Map,引用型別,Set巢狀List,Set和Map,Map的key和value分別支援基本型別和引用型別,不支援和其他集合型別的巢狀。
首先是入口方法

@Override
    public List<Bean> praserBeans(String param) {
        // TODO Auto-generated method stub
        File file=file=new File(param);
        SAXReader saxReader=new SAXReader();
        Document document=null;
        Element rootElement=null;
        try {
            document=saxReader.read(file);
            rootElement=document.getRootElement();
        } catch (DocumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return inflateAll(rootElement);
    }

首先根據xml的位置引數,建立File物件,使用SaxReader物件讀取xml,生成Document文件物件,獲取根節點,即RootElement,呼叫inflateAll方法遍歷所有的元素節點。

    private List<Bean> inflateAll(Element rootElement) {
        List<Bean> beans=null;
        beans=new ArrayList<Bean>();
        Iterator<Element> beanIterator=rootElement.elementIterator();
        while (beanIterator.hasNext()) {
            Element beanElement=beanIterator.next();
            Bean bean=inflateSingleBean(beanElement);
            beans.add(bean);
        }
        return beans;
    }
這段程式碼拿到所有的bean節點對應的Element物件,呼叫inflateSingleBean方法把返回的bean屬性物件新增到集合中。
private Bean inflateSingleBean(Element beanElement) {
        Bean bean=new Bean();
        //首先解析各種各樣的屬性
        String objectId=beanElement.attributeValue(Constant.XmlKey.ElementBean.KEY_ATTRIBUTE_ID);
        String className=beanElement.attributeValue(Constant.XmlKey.ElementBean.KEY_ATTRIBUTE_CLASS);
        String initMethod=beanElement.attributeValue(Constant.XmlKey.ElementBean.KEY_ATTRIBUTE_METHOD_INIT);
        String initDestory=beanElement.attributeValue(Constant.XmlKey.ElementBean.KEY_ATTRIBUTE_METHOD_DESTORY);        
//初始化屬性集合
        List<Property> properties=new ArrayList<Property>();
        bean.setClassAddress(className);
        bean.setDestoryMethod(initDestory);
        bean.setInitMethod(initMethod);
        bean.setId(objectId);
        bean.setProperties(properties);
        //拿到子元素,變數子元素
        Iterator<Element> propertyIterator=beanElement.elementIterator();
        while (propertyIterator.hasNext()) {
            //遍歷每一個屬性
            Element propertyElement=propertyIterator.next();                //初始化Property屬性 
            Property property=new Property();
            List<Element> elements=propertyElement.elements();
            Element collectionElement=null;
            //設定屬性的名稱
            String propertyName=propertyElement.attributeValue(Constant.XmlKey.ElementProperty.KEY_ATTRIBUTE_NAME);
            property.setName(propertyName);
    //判斷Property是否有子節點,有代表是一個集合屬性,否則是普通屬性       
            if (elements!=null&&elements.size()!=0) {
                //屬性值為集合,獲取集合節點
                collectionElement=elements.get(0);
                CollectionProperty collectionValue=null;
                String collectionName=collectionElement.getName();
                if (collectionName.equals(Constant.XmlKey.ElementCollection.KEY_ELEMENT_LIST)) {
                    //處理List集合
                    collectionValue=inflatePropertyListAndSet(collectionElement,new ListProperty());
                    property.setType(Constant.Property.TYPE_LIST);
                }else if (collectionName.equals(Constant.XmlKey.ElementCollection.KEY_ELEMENT_SET)) {
                    //處理set集合
                    collectionValue=inflatePropertyListAndSet(collectionElement,new SetProperty());
                    property.setType(Constant.Property.TYPE_SET);
                }else if (collectionName.equals(Constant.XmlKey.ElementCollection.KEY_ELEMETN_MAP)) {
                    //處理Map集合
                    collectionValue=inflatePropertyMap(collectionElement);
                    property.setType(Constant.Property.TYPE_MAP);
                }

                property.setCollectionValue(collectionValue);
                properties.add(property);
                continue;
            }
            //如果屬性值為引用值或者基本資料型別
            String propertyValue=propertyElement.attributeValue(Constant.XmlKey.ElementProperty.KEY_ATTRIBUTE_VALUE);
            String propertyRef=propertyElement.attributeValue(Constant.XmlKey.ElementProperty.KEY_ATTRIBUTE_REF);
            property.setValue(propertyValue);
            property.setRef(propertyRef);
            if (propertyRef==null) {
                property.setType(Constant.Property.TYPE_VALUE);
            }else {
                property.setType(Constant.Property.TYPE_REF);
            }
            properties.add(property);   
            //取出list
        }
        return bean;
    }

這段程式碼首先從Element物件中獲取相應的屬性,包括id,class,init-method和destroy-method,這些常量都被封裝在Constant類中方便查詢和更改,然後初始化List<Property>,準備將所有的屬性放入該集合中。之後取出屬性節點,判斷屬性節點下是否存在子節點,如果存在則說明屬性的值是Set,List或者Map型別,如果是List或者Set則呼叫inflatePropertyListAndSet,是Map則呼叫inflatePropertyMap方法,返回的是一個CollectionProperty上轉型物件。如果是基本型別的數值的話,則直接取出屬性中的值,設定到Property物件中即可。
再來看解析List和Set標籤屬性的方法inflatePropertyListAndSet

private CollectionProperty inflatePropertyListAndSet(Element element,BaseProperty result) {
        // TODO Auto-generated method stub
        Iterator<Element> iterator=element.elementIterator();
        List<String> valueList=null;
        List<String> refList=null;
        List<Bean>   beans=null;
        List<CollectionProperty> collectionProperties=null;
        while (iterator.hasNext()) {
            Element childElement=iterator.next();
            String childElementName=childElement.getName();
            String value=childElement.getText();
            int type=getCollectinValueType(childElementName);
            result.setType(type);
            switch (type) {
            case Constant.Property.TYPE_VALUE:
                if (valueList==null) {
                    valueList=new ArrayList<String>();
                }
                valueList.add(value);
                result.setValueList(valueList);
                break;
            case Constant.Property.TYPE_REF:
                if (refList==null) {
                    refList=new ArrayList<String>();
                }
                refList.add(value);
                result.setRefList(refList);
                break;
            case Constant.Property.TYPE_BEAN:
                if (beans==null) {
                    beans=new ArrayList<Bean>();
                }
                Bean bean=inflateSingleBean(childElement);
                beans.add(bean);
                result.setBeans(beans);
                break;
            case Constant.Property.TYPE_SET:
                if (collectionProperties==null) {
                    collectionProperties=new ArrayList<CollectionProperty>();
                }

                CollectionProperty setProperty=inflatePropertyListAndSet(childElement,new SetProperty());
                collectionProperties.add(setProperty);
                result.setCollectionProperties(collectionProperties);
                break;
            case Constant.Property.TYPE_LIST:
                if (collectionProperties==null) {
                    collectionProperties=new ArrayList<CollectionProperty>();
                }
                CollectionProperty listProperty=inflatePropertyListAndSet(childElement,new ListProperty());
                collectionProperties.add(listProperty);
                result.setCollectionProperties(collectionProperties);
                break;
            case Constant.Property.TYPE_MAP:
                if (collectionProperties==null) {
                    collectionProperties=new ArrayList<CollectionProperty>();
                }
                CollectionProperty mapProperty=inflatePropertyMap(childElement);
                collectionProperties.add(mapProperty);
                result.setCollectionProperties(collectionProperties);
                break;
            default:
                break;
            }
        }
        return result;
    }

這段程式碼首先遍歷list或者set標籤下的元素,list或者set標籤支援基本資料型別value標籤,引用資料型別ref標籤和bean標籤,以及set,list或者map標籤,在這裡是呼叫getCollectinValueType獲取標籤的型別,其實就是為每個標籤對應了相應的數值常量,方便我們使用switch語句分類討論,如果是value標籤,我們則將對應的值放到valueList集合中,ref標籤則放到refList中,bean標籤則放到beans集合中,set或list標籤我們會遞迴呼叫inflatePropertyListAndSet方法,然後把對應的屬性放到collectionProperties集合中,map標籤也是一樣,只不過呼叫的是inflatePropertyMap方法。接著來看inflatePropertyMap方法的實現。

private CollectionProperty inflatePropertyMap(Element element) {
        // TODO Auto-generated method stub
        Iterator<Element> iterator=element.elementIterator();
        MapProperty mapProperty=new MapProperty();
        List<MapEntryProperty> mapEntryProperties=new ArrayList<MapEntryProperty>();
        mapProperty.setEntrys(mapEntryProperties);
        while (iterator.hasNext()) {
            Element childElement=iterator.next();
            Iterator<Element> entryIterator=childElement.elementIterator();
            MapEntryProperty mapEntryProperty=null;
            //解析Entry物件中的key,value 
            Element keyElement=entryIterator.next();                
            Element valueElement=entryIterator.next();
            String keyName=keyElement.getName();
            String valueName=valueElement.getName();
            int keyType=getMapValueType(keyName);
            int valueType=getMapValueType(valueName);
            if (keyType==Constant.Property.TYPE_BEAN&&valueType==Constant.Property.TYPE_BEAN) {
                mapEntryProperty=new MapEntryProperty<Bean, Bean>();
            }else if (keyType==Constant.Property.TYPE_BEAN) {
                mapEntryProperty=new MapEntryProperty<Bean, String>();
            }else if (valueType==Constant.Property.TYPE_BEAN) {
                mapEntryProperty=new MapEntryProperty<String, Bean>();
            }else {
                mapEntryProperty=new MapEntryProperty<String, String>();
            }
            switch (keyType) {
            case Constant.Property.TYPE_VALUE:
                mapEntryProperty.setKeyType(MapEntryType.value);
                mapEntryProperty.setKey(keyElement.getText());
                break;
            case Constant.Property.TYPE_REF:
                mapEntryProperty.setKey(keyElement.getText());
                mapEntryProperty.setKeyType(MapEntryType.ref);
                break;
            case Constant.Property.TYPE_BEAN:
                Bean bean=inflateSingleBean(keyElement.element(Constant.XmlKey.ElementBean.KEY_ELEMENT_NAME));
                mapEntryProperty.setKey(bean);
                mapEntryProperty.setKeyType(MapEntryType.bean);
                break;
            default:
                break;
            }
            switch (valueType) {
            case Constant.Property.TYPE_VALUE:
                mapEntryProperty.setValueType(MapEntryType.value);
                mapEntryProperty.setValue(valueElement.getText());
                break;
            case Constant.Property.TYPE_REF:
                mapEntryProperty.setValueType(MapEntryType.ref);
                mapEntryProperty.setValue(valueElement.getText());
                break;
            case Constant.Property.TYPE_BEAN:
                Bean bean=inflateSingleBean(valueElement.element(Constant.XmlKey.ElementBean.KEY_ELEMENT_NAME));
                mapEntryProperty.setValue(bean);
                mapEntryProperty.setValueType(MapEntryType.bean);
                break;
            default:
                break;
            }
            System.out.println(mapEntryProperty.toString());
            mapEntryProperties.add(mapEntryProperty);
        }
        return mapProperty;
    }

這段程式碼首先遍歷map下的所有entry元素,之後取出entry下的key和value鍵值對,在這裡key和value支援三種標籤,key,value代表的是基礎資料型別,value_bean和value_ref代表值是引用型別,key_ref和key_bean代表鍵是引用型別。每一個entry標籤對應的是一個MapEntryProperty物件,首先看看MapEntryProperty物件。

//代表一個map屬性
public class MapProperty extends CollectionProperty{
    private List<MapEntryProperty> entrys;
    public List<MapEntryProperty> getEntrys() {
        return entrys;
    }

    public void setEntrys(List<MapEntryProperty> entrys) {
        this.entrys = entrys;
    }


    public static class Support{
        public static Class<?>[] TYPE_SUPPORT={HashMap.class,LinkedHashMap.class};
        public static Class<?> TYPE_SUPPORT_INTERFACE=Map.class;
    }

    @Override
    public String toString() {
        return "MapProperty [entrys=" + entrys + "]";
    }


    /**
     * @author Administrator
     *代表鍵和值都是基本型別
     */
    public static class MapEntryProperty<k,v>{
        @Override
        public String toString() {
            return "MapEntryProperty [keyType=" + keyType + ", valueType="
                    + valueType + ", key=" + key + ", value=" + value + "]";
        }
        private MapEntryType keyType;
        private MapEntryType valueType;
        private k key;
        private v value;


        public MapEntryType getValueType() {
            return valueType;
        }
        public void setValueType(MapEntryType valueType) {
            this.valueType = valueType;
        }
        public MapEntryType getKeyType() {
            return keyType;
        }
        public void setKeyType(MapEntryType keyType) {
            this.keyType = keyType;
        }
        public k getKey() {
            return key;
        }
        public void setKey(k key) {
            this.key = key;
        }
        public v getValue() {
            return value;
        }
        public void setValue(v value) {
            this.value = value;
        }


    }

    /**鍵和值的兩種型別
     * @author Administrator
     *
     */
    public enum MapEntryType{
          value,
          ref,
          bean
    }



}

MapProperty類代表的是map標籤,成員變數entrys存放的是entry鍵值對的集合,靜態內部類MapEntryProperty代表的是一個entry標籤,內部有keyType和valueType兩個屬性,分別代表鍵和值的型別,MapEntryType是一個列舉類,有ref,value和bean三種類型,由於在初始化物件的時候,三種類型的處理是不同的所以這裡分割開來。key和value代表的是真實值,因為型別不同則型別可能是字串型別也可能是bean型別,所以使用泛型引數來代替。Support內部類代表支援的集合型別的位元組碼物件,我們這裡支援JavaBean宣告的型別可以是HashMap或者LinkedHashMap,也可以支援Map介面宣告,會預設以HashMap型別來處理。
回到inflatePropertyMap中,我們會根據key和value型別的不同來在初始化MapEntryProperty傳入不同的泛型實參,之後對key和value分別分類討論,根據不同的型別,mapEntryProperty物件設定不同的MapEntryType和value,key值。基本型別則呼叫Element物件的getText()方法取值,引用型別則遞迴呼叫inflateSingleBean方法獲得Bena物件。
到這裡,xml的解析工作已經做完了,最終返回的是List<Bean>物件,所有的屬性都放在這裡。
(2).Annotation讀取
接著來看註解讀取的部分,這裡主要使用註解和反射的知識來完成。

@Override
    public List<Bean> praserBeans(String param) {
        // TODO Auto-generated method stub
        List<Bean> beans=new ArrayList<Bean>();
        List<Class<?>> clazzs=ClassUtil.getClasses(param);
        for (int i = 0; i < clazzs.size(); i++) {
            Class clazz=clazzs.get(i);
            Bean bean=getBeanByClass(clazz);
            if (bean!=null) {
                beans.add(bean);
            }
        }

        return beans;
    }

首先根據包,獲取指定包下的所有類的Class位元組碼物件,然後呼叫getBeanByClass方法獲取指定類的Bean物件。

private Bean getBeanByClass(Class<?> clazz){
        Annotation clazzAnnotation=clazz.getAnnotation(BeanType.class);
        if (clazzAnnotation==null) {
            return null;
        }
        Bean bean=new Bean();
        BeanType beanType=(BeanType) clazzAnnotation;
        String beanId=beanType.id();
        bean.setId(beanId);
        bean.setClassAddress(clazz.getPackage().getName()+"."+clazz.getSimpleName());
        System.out.println(bean.getClassAddress());
        Field[] declaredFields = clazz.getDeclaredFields();
        List<Property> properties=new ArrayList<Property>();
        bean.setProperties(properties);
        for (int j = 0; j < declaredFields.length; j++) {
            Field field=declaredFields[j];
            Annotation[] annotations=field.getAnnotations();
            if (annotations.length==0) {
                continue;
            }
            Property property=new Property();
            properties.add(property);
            String fieldName=field.getName();
            property.setName(fieldName);
            for (int k = 0; k < annotations.length; k++) {
                Annotation annotation=annotations[k];
                if (field.isAnnotationPresent(BasicType.class)) {
                    BasicType basicType=(BasicType) annotation;     
                    String value=getBasicProperty(basicType);               
                    property.setValue(value);
                     property.setType(Constant.Property.TYPE_VALUE);
                }else if (field.isAnnotationPresent(ListType.class)) {
                    ListType listType=(ListType) annotation;
                    ListProperty listProperty=getListProperty(listType);
                    property.setCollectionValue(listProperty);
                    property.setType(Constant.Property.TYPE_LIST);
                }else if (field.isAnnotationPresent(SetType.class)) {
                    SetType setType=(SetType) annotation;
                    SetProperty setProperty=getSetProperty(setType);
                    property.setCollectionValue(setProperty);
                    property.setType(Constant.Property.TYPE_SET);
                }else if (field.isAnnotationPresent(MapType.class)) {
                    MapType mapType=(MapType) annotation;
                    MapProperty mapProperty=getMapProperty(mapType);
                    property.setCollectionValue(mapProperty);
                    property.setType(Constant.Property.TYPE_MAP);
                }else if (field.isAnnotationPresent(RefType.class)) {
                    RefType refType=(RefType) annotation;
                    String ref=getRefProperty(refType);
                    property.setRef(ref);
                    property.setType(Constant.Property.TYPE_REF);
                }
            }
        }

        return bean;
    }

可以看到註解的解析相對簡單,因為註解的侷限性,暫時無法注入集合巢狀集合這種型別的資料型別,因為註解的值不能是註解元素本身,所以無法完成遞迴呼叫。這段程式碼首先獲取BeanType註解,只有新增這個註解的才會被我們注入,如果沒有這個註解則註解返回。之後呼叫getDeclaredFields方法獲取該類的所有屬性,然後遍歷所有的屬性。獲取屬性上作用的所有Annotation,遍歷所有的Annotation,呼叫Filed的isAnnotationPresent方法判斷是否有指定的註解作用在Field上。型別分別是BasicType,ListType,SetType,MapType,RefType,分別呼叫對應的讀取註解的方法,然後給Property設定獲取的註解值。
獲取引用型別

private String getRefProperty(RefType refType){
           return refType.id();
}

獲取基本資料型別

private String getBasicProperty(BasicType basicType){

              return basicType.value();
    }

獲取list型別

private ListProperty getListProperty(ListType listType){
        ListProperty listProperty=new ListProperty(); 
        listProperty.setType(Constant.Property.TYPE_VALUE);
        String[] values = listType.value();
        List<String> valueList=new ArrayList<String>();
        for (int i = 0; i < values.length; i++) {
            String value=values[i];
            valueList.add(value);
        }
        listProperty.setValueList(valueList);
        return listProperty;
    }

獲取set型別

private SetProperty getSetProperty(SetType setType){
        SetProperty setProperty=new SetProperty(); 
        setProperty.setType(Constant.Property.TYPE_VALUE);
        String[] values = setType.value();
        List<String> valueList=new ArrayList<String>();
        for (int i = 0; i < values.length; i++) {
            String value=values[i];
            valueList.add(value);
        }
        setProperty.setValueList(valueList);
        return setProperty;
    }

獲取map型別

 private MapProperty getMapProperty(MapType mapType){
         MapProperty mapProperty=new MapProperty(); 

         List<MapEntryProperty> mapEntryProperties=new ArrayList<MapProperty.MapEntryProperty>();
         MapEntry[] mapEntries=mapType.entry();
         for (int i = 0; i < mapEntries.length; i++) {
             MapEntryProperty<String, String> mapEntryProperty=new MapEntryProperty<String, String>();
             mapEntryProperty.setKeyType(MapEntryType.value);
             mapEntryProperty.setValueType(MapEntryType.value);
             MapEntry mapEntry=mapEntries[i];
             String key=mapEntry.key();
             String value=mapEntry.value();
             mapEntryProperty.setKey(key);
             mapEntryProperty.setValue(value);
             mapEntryProperties.add(mapEntryProperty);
         }
         mapProperty.setEntrys(mapEntryProperties);
         return mapProperty;
     }

到這裡,我們的註解讀取的工作也完成了。
(3).反射注入
接著是最核心的工作,所有的反射注入工作都在ObjectFactory類中完成。
首先看構造方法

    public ObjectFactory(List<Bean> beans) {
        // TODO Auto-generated constructor stub
        classMap=new HashMap<String, Class<Object>>();
        this.mBeans=beans;
        this.mObjectManager=ObjectManager.getInstance();
        this.mWrapClasses=new Class[]{Integer.class,Double.class,Float.class,
                Short.class,Long.class,Byte.class,Boolean.class,Character.class};
        this.mBasiClasses=new Class[]{int.class,double.class,float.class,
                short.class,long.class,byte.class,boolean.class,char.class};
    }
 classMap是用來快取Class位元組碼物件的,獲取Class物件時首先會去快取中查詢如果沒有再去呼叫方法載入。mWrapClasses和mBasiClasses是兩個陣列,前者放的是基礎資料型別的包裝類物件,後者是基礎資料型別的Class物件。因為int.class和Integer.class不是一個物件,為了方便我們從字串中解析出對應的資料型別值,我們需要將其轉換成對應的包裝型別,然後通過反射呼叫包裝型別的靜態方法valueOf方法獲取真實的資料。
 入口方法
public Object loadObject(Bean bean) throws ReferenceException, FieldTypeException{
        String classAddress=bean.getClassAddress();
        Class<Object> clazz=classMap.get(classAddress);
        Object object=null;
        if (clazz==null) {
            ClassLoader classLoader=ObjectFactory.class.getClassLoader();
            try {
                //不進行類的初始化
                //clazz=(Class<Object>) Class.forName(classAddress);
                clazz=(Class<Object>) classLoader.loadClass(classAddress);
                classMap.put(classAddress, clazz);
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return null;
            }
        }
        //首先建立物件
        try {
            object = clazz.newInstance();
        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } 
        List<Property> properties=bean.getProperties();
        for (int i = 0; i < properties.size(); i++) {
            Property property=properties.get(i);
            int type=property.getType();
            String fieldName=property.getName();
            Field field=null;
            Class rawType=null;

            try {
                field = clazz.getDeclaredField(fieldName);
                rawType=field.getType();
            } catch (Exception e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } 
            switch (type) {
            case Constant.Property.TYPE_SET:
                //注入set集合
                Type setType=field.getGenericType();
                SetProperty setProperty=(SetProperty) property.getCollectionValue();
                Collection setResult=getListAndSet(setType,setProperty,SetProperty.Support.TYPE_SUPPORT_CLASS,SetProperty.Support.TYPE_SUPPORT_INTERFACE);
                inject(clazz, object, fieldName, rawType, setResult);
                break;
            case Constant.Property.TYPE_LIST:
                //注入List集合
                Type listType=field.getGenericType();
                ListProperty listProperty=(ListProperty) property.getCollectionValue();
                Collection listResult=getListAndSet(listType,listProperty,
                        ListProperty.Support.TYPE_SUPPORT_CLASS,ListProperty.Support.TYPE_SUPPORT_INTERFACE);
                inject(clazz, object, fieldName, rawType, listResult);
                break;
            case Constant.Property.TYPE_MAP:
                //注入Map集合
                //key key-ref key可以使基本資料型別,也可以是引用型別
                //value 基本資料型別  value-ref配置 中的引用型別
                //1.首先判斷對應的變數型別是不是map,並確定targetClass
                //2.判斷泛型引數的型別與xml檔案中是否一致
                //3.填充資料
                //1
                Type mapType=field.getGenericType();
                MapProperty mapProperty=(MapProperty) property.getCollectionValue();

                Map map = getMap(mapProperty,mapType);

                inject(clazz, object, fieldName, rawType, map);
                break;
            case Constant.Property.TYPE_REF:
                //value是引用值
                Object refObject=getRefObject(property.getRef());
                try {
                    System.out.println(fieldName);
                    Class fieldClazz=field.getType();
                    inject(clazz, object, fieldName, fieldClazz, refObject);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } 
                break;
            case Constant.Property.TYPE_VALUE:
                //Vlaue是基本型別的值
                System.out.println("rawType:"+rawType);
                Object objectBasic=pareseBasicValue(getWrapFromBasic(rawType), property.getValue());
                inject(clazz, object, fieldName, rawType, objectBasic);
            }

        }
        return object;

    }

首先根據指定的全類名從快取Map中查詢對應的Class位元組碼物件,如果為空則去載入Class物件,然後放到快取map中。首先創建出物件,之後遍歷List<Property>屬性集合 ,開始注入各種值。然後取出屬性的名稱,呼叫getDeclaredField方法,根據屬性的名稱獲取Field物件,呼叫Field物件的getType方法獲取屬性的資料型別,這裡獲取的是一個原始資料型別。
接下來呼叫Property的getType方法獲取屬性的型別,然後分類討論。
首先討論set集合,如果是set集合,則必須獲取泛型引數的型別,這裡是呼叫的Field的getGenericType方法,然後呼叫getListAndSet方法,該方法返回的是一個Collection上轉型物件,這個物件便是根據屬性型別創建出來的物件,其中已經設定好了值,然後進行注入。List集合的處理和Set集合基本相同。我們重點來看getListAndSet方法。

private Collection<?> getListAndSet(Type paramType,
            BaseProperty listProperty,Class[] supportClasses,Class supportInterface)
                    throws FieldTypeException, ReferenceException {
        //首先進行型別校驗和Class選取
        //第一步進行校驗
        ParameterizedType parameterizedType=null;
        if (!(paramType instanceof ParameterizedType)) {
            //不是List或set介面的子類,或者沒有指定要注入的型別形參
            throw new FieldTypeException(Constant.Exeception.EXECEPTION_FIELDTYPE);
        } else {
            parameterizedType=(ParameterizedType) paramType;
        }
        Class paramClazz=(Class) parameterizedType.getRawType();

        //第二步 確定集合的Class物件
        Type[] types=parameterizedType.getActualTypeArguments();
        Type genericParamType= types[0];
        Collection resultCollection=null;
        //型別錯誤丟擲異常
        //注入集合型別的值
        //集合中的資料型別  基本資料型別<value></value>、集合型別 List Map set、引用型別<ref></ref> 、bean
        //獲取泛型資料型別
        //獲取修飾符
        //如果Class是一個List介面,預設建立ArrayList建立資料
        //否則分為ArrayList和LinkeList來處理
        //如果指定變數不是一個List集合型別則丟擲異常
        //為了保持資料的原有型別,在初始化物件的時候分別採用ArrayList和LinkeList的位元組碼來初始化
        //但是尋找方法的時候依舊採用原始型別
        //只處理ArrayList和LinkList,其他全部丟擲異常
        //注入前首先判斷變數型別是否是集合型別

        Class<?> targetClass=null;

        //支援ArrayList和LinkedList,其餘型別丟擲異常
        for (int i = 0; i < supportClasses.length; i++) {
            Class<?> support= supportClasses[i];
            if (support.isAssignableFrom(paramClazz)) {
                targetClass=support;
                break;
            }
        }
        if (targetClass==null) {
            if (supportInterface.isAssignableFrom(paramClazz)) {
                targetClass=supportClasses[0];
            }else {
                throw new FieldTypeException(Constant.Exeception.EXECEPTION_FIELDTYPE);
            }
        }
        //根據不同型別的值開始建立物件
        int listValueType=listProperty.getType();
        switch (listValueType) {
        case Constant.Property.TYPE_VALUE:
            //集合中是基本型別的值
            try {
                List<String> valueList=listProper