日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

java的動(dòng)態(tài)性編程(二)——引入Reflection

系統(tǒng) 2026 0
使用反射不同于常規(guī)的Java編程,其中它與 元數(shù)據(jù)--描述其它數(shù)據(jù)的數(shù)據(jù)協(xié)作。Java語(yǔ)言反射接入的特殊類型的原數(shù)據(jù)是JVM中類和對(duì)象的描述。反射使您能夠運(yùn)行時(shí)接入廣泛的類信息。它甚至使您能夠讀寫字段,調(diào)用運(yùn)行時(shí)選擇的類的方法。
反射是一種強(qiáng)大的工具。它使您能夠創(chuàng)建靈活的代碼,這些代碼可以在運(yùn)行時(shí)裝配,無(wú)需在組件之間進(jìn)行源代表鏈接。但反射的某些方面存在一些疑問(wèn)。在本文中,我將深入討論為什么您可能 不希望在程序中使用反射,以及您應(yīng)該這樣做的理由。在了解了權(quán)衡性分析之后,您可以自行決定是否利大于弊。
初學(xué)者的類
使用反射的啟點(diǎn)總是 java.lang.Class 實(shí)例。如果您希望與預(yù)先定義的類協(xié)作,那么Java語(yǔ)言提供一種直接獲得 Class 實(shí)例的簡(jiǎn)便快捷方式:
    Class clas = MyClass.class;
  

當(dāng)您使用這一項(xiàng)技術(shù)時(shí),裝入類涉及的所有工作在幕后進(jìn)行。但是,如果您需要在運(yùn)行時(shí)從某些外部源讀取類名,這種方法并不適合。實(shí)際上,您需要使用一個(gè)類裝入器來(lái)查找類信息。以下介紹一種方法:
    // "name" is the class name to load
Class clas = null;
try {
  clas = Class.forName(name);
} catch (ClassNotFoundException ex) {
  // handle exception case
}
// use the loaded class
  

如果已經(jīng)裝入了類,您將得到現(xiàn)有的 Class 信息。如果類未被裝入,類裝入器將現(xiàn)在裝入并返回新創(chuàng)建的類實(shí)例。
    基于類的反射
  

Class 對(duì)象為您提供接入類元數(shù)據(jù)的反射的所有基本hook。這類元數(shù)據(jù)包括關(guān)于類自身的信息,如包和類的父類,以及該類實(shí)施的接口。它還包括該類定義的構(gòu)造函數(shù)、字段和方法的詳細(xì)信息。這些最后的項(xiàng)目都是編程中最經(jīng)常使用的項(xiàng)目, 因此我將在本小節(jié)的稍后部分給出一些與它們協(xié)作的實(shí)例。
對(duì)于以下三類組件中的任何一類來(lái)說(shuō) -- 構(gòu)造函數(shù)、字段和方法 -- java.lang.Class 提供四種獨(dú)立的反射調(diào)用,以不同的方式來(lái)獲得信息。調(diào)用都遵循一種標(biāo)準(zhǔn)格式。以下是用于查找構(gòu)造函數(shù)的一組反射調(diào)用:
Constructor getConstructor(Class[] params) -- 獲得使用特殊的參數(shù)類型的公共構(gòu)造函數(shù),
Constructor[] getConstructors() -- 獲得類的所有公共構(gòu)造函數(shù)
Constructor getDeclaredConstructor(Class[] params) -- 獲得使用特定參數(shù)類型的構(gòu)造函數(shù)(與接入級(jí)別無(wú)關(guān))
Constructor[] getDeclaredConstructors() -- 獲得類的所有構(gòu)造函數(shù)(與接入級(jí)別無(wú)關(guān))
每類這些調(diào)用都返回一個(gè)或多個(gè) java.lang.reflect.Constructor 函數(shù)。這種 Constructor 類定義 newInstance 方法,它采用一組對(duì)象作為其唯一的參數(shù),然后返回新創(chuàng)建的原始類實(shí)例。該組對(duì)象是用于構(gòu)造函數(shù)調(diào)用的參數(shù)值。作為解釋這一工作流程的實(shí)例,假設(shè)您有一個(gè) TwoString 類和一個(gè)使用一對(duì) String s的構(gòu)造函數(shù),如清單1所示:
    public class TwoString {
    private String m_s1, m_s2;
    public TwoString(String s1, String s2) {
        m_s1 = s1;
        m_s2 = s2;
    }
}
  

清單2中的代碼獲得構(gòu)造函數(shù)并使用它來(lái)創(chuàng)建使用 String s "a" 和 "b" 的 TwoString 類的一個(gè)實(shí)例:
    Class[] types = new Class[] { String.class, String.class };
    Constructor cons = TwoString.class.getConstructor(types);
    Object[] args = new Object[] { "a", "b" };
    TwoString ts = cons.newInstance(args);
  

清單2中的代碼忽略了不同反射方法拋出的多種可能選中的例外類型。例外在 Javadoc API 描述中詳細(xì)記錄,因此為了簡(jiǎn)明起見(jiàn),我將在所有程序?qū)嵗泻雎运鼈儭?
盡管我在討論構(gòu)造函數(shù)主題,Java編程語(yǔ)言還定義了一種您可以用來(lái)使用 無(wú)參數(shù)(或缺省)構(gòu)造函數(shù)創(chuàng)建類的一個(gè)實(shí)例的特殊快捷方式。這種快捷方式嵌入到 Class 定義中,如下:
Object newInstance() -- 使用缺省函數(shù)創(chuàng)建新的實(shí)例
即使這種方法只允許您使用一種特殊的構(gòu)造函數(shù),如果這正是您需要的,那么它將提供一種非常方便的快捷方式。當(dāng)與JavaBeans協(xié)作時(shí)這項(xiàng)技術(shù)尤其有用,JavaBeans需要定義公共、無(wú)參數(shù)構(gòu)造函數(shù)。
    通過(guò)反射增加字段
  

獲得字段信息的 Class 反射調(diào)用不同于那些用于接入構(gòu)造函數(shù)的調(diào)用,在參數(shù)類型數(shù)組中使用了字段名:
Field getField(String name) -- 獲得命名的公共字段
Field[] getFields() -- 獲得類的所有公共字段
Field getDeclaredField(String name) -- 獲得類聲明的命名的字段
Field[] getDeclaredFields() -- 獲得類聲明的所有字段
盡管與構(gòu)造函數(shù)調(diào)用類似,在字段方面仍存在一個(gè)重要的區(qū)別:前兩個(gè)變量返回可以通過(guò)類接入的公共字段的信息 -- 即使它們來(lái)自于祖先類。后兩個(gè)變量返回類直接聲明的字段的信息 -- 與字段的接入類型無(wú)關(guān)。
調(diào)用返回的 java.lang.reflect.Field 實(shí)例定義所有主類型的 getXXX 和 setXXX 方法,以及與對(duì)象引用協(xié)作的通用 get 和 set 方法。您可以根據(jù)實(shí)際的字段類型自行選擇一種適當(dāng)?shù)姆椒ǎ?getXXX 方法將自動(dòng)處理擴(kuò)展轉(zhuǎn)換(如使用 getInt 方法來(lái)檢索一個(gè)字節(jié)值)。
清單3顯示使用字段反射方法的一個(gè)實(shí)例,以方法的格式根據(jù)名稱增加對(duì)象的 int 字段 :
    public int incrementField(String name, Object obj) throws... {
    Field field = obj.getClass().getDeclaredField(name);
    int value = field.getInt(obj) + 1;
    field.setInt(obj, value);
    return value;
}
  

這種方法開(kāi)始展示了反射帶來(lái)的某些靈活性。與特定的類協(xié)作不同, incrementField 使用傳 入的對(duì)象的 getClass 方法來(lái)查找類信息,然后直接在該類中查找命名的字段。
    通過(guò)反射增加方法
  

獲得方法信息的 Class 反射調(diào)用與用于構(gòu)造函數(shù)和字段的調(diào)用非常類似:
Method getMethod(String name, Class[] params) -- 使用特定的參數(shù)類型,獲得命名的公共方法
Method[] getMethods() -- 獲得類的所有公共方法
Method getDeclaredMethod(String name, Class[] params) -- 使用特寫的參數(shù)類型,獲得類聲明的命名的方法
Method[] getDeclaredMethods() -- 獲得類聲明的所有方法
與字段調(diào)用一樣,前兩個(gè)變量返回可以通過(guò)類接入的公共方法的信息 -- 即使它們來(lái)自于祖先類。后兩個(gè)變量返回類聲明的方法的信息,與方法的接入類型無(wú)關(guān)。
調(diào)用返回的 java.lang.reflect.Method 實(shí)例定義一種 invoke 方法,您可以用來(lái)在正在定義的類的一個(gè)實(shí)例上調(diào)用方法。這種 invoke 方法使用兩個(gè)參數(shù),為調(diào)用提供類實(shí)例和參數(shù)值數(shù)組。
清單4進(jìn)一步闡述字段實(shí)例,顯示反射正在運(yùn)行的方法的一個(gè)實(shí)例。這種方法增加一個(gè)定義有 get 和 set 方法的 int JavaBean屬性。例如,如果對(duì)象為一個(gè)整數(shù) count 值定義了 getCount 和 setCount 方法,您可以在一次調(diào)用中向該方法傳遞“count”作為 name 參數(shù),以增加該值。
    public int incrementProperty(String name, Object obj) {
    String prop = Character.toUpperCase(name.charAt(0)) +
        name.substring(1);
    String mname = "get" + prop;
    Class[] types = new Class[] {};
    Method method = obj.getClass().getMethod(mname, types);
    Object result = method.invoke(obj, new Object[0]);
    int value = ((Integer)result).intValue() + 1;
    mname = "set" + prop;
    types = new Class[] { int.class };
    method = obj.getClass().getMethod(mname, types);
    method.invoke(obj, new Object[] { new Integer(value) });
    return value;
}
  

為了遵循JavaBeans慣例,我把屬性名的首字母改為大寫,然后預(yù)先考慮 get 來(lái)創(chuàng)建讀方法名, set 來(lái)創(chuàng)建寫方法名。JavaBeans讀方法僅返回值,而寫方法使用值作為唯一的參數(shù),因此我規(guī)定方法的參數(shù)類型以進(jìn)行匹配。最后,該慣例要求方法為公共,因此我使用查找格式,查找類上可調(diào)用的公共方法。
這一實(shí)例是第一個(gè)我使用反射傳遞主值的實(shí)例,因此現(xiàn)在我們來(lái)看看它是如何工作的。基本原理很簡(jiǎn)單:無(wú)論什么時(shí)候您需要傳遞主值,只需用相應(yīng)封裝類的一個(gè)實(shí)例(在 java.lang 包中定義)來(lái)替換該類主值。這可以應(yīng)用于調(diào)用和返回。因此,當(dāng)我在實(shí)例中調(diào)用 get 方法時(shí),我預(yù)計(jì)結(jié)果為實(shí)際 int 屬性值的 java.lang.Integer 封裝。
    反射數(shù)組
  

數(shù)組是Java編程語(yǔ)言中的對(duì)象。與所有對(duì)象一樣,它們都有類。如果您有一個(gè)數(shù)組,使用標(biāo)準(zhǔn) getClass 方法,您可以獲得該數(shù)組的類,就象任何其它對(duì)象一樣。但是, 不通過(guò)現(xiàn)有的實(shí)例來(lái)獲得類不同于其它類型的對(duì)象。即使您有一個(gè)數(shù)組類,您也不能直接對(duì)它進(jìn)行太多的操作 -- 反射為標(biāo)準(zhǔn)類提供的構(gòu)造函數(shù)接入不能用于數(shù)組,而且數(shù)組沒(méi)有任何可接入的字段,只有基本的 java.lang.Object 方法定義用于數(shù)組對(duì)象。
數(shù)組的特殊處理使用 java.lang.reflect.Array 類提供的靜態(tài)方法的集合。該類中的方法使您能夠創(chuàng)建新數(shù)組,獲得數(shù)組對(duì)象的長(zhǎng)度,讀和寫數(shù)組對(duì)象的索引值。
清單5顯示了一種重新調(diào)整現(xiàn)有數(shù)組大小的有效方法。它使用反射來(lái)創(chuàng)建相同類型的新數(shù)組,然后在返回新數(shù)組之前,在老數(shù)組中復(fù)制所有數(shù)據(jù)。
    public Object growArray(Object array, int size) {
    Class type = array.getClass().getComponentType();
    Object grown = Array.newInstance(type, size);
    System.arraycopy(array, 0, grown, 0,
        Math.min(Array.getLength(array), size));
    return grown;
}
  

    安全性和反射
  

在處理反射時(shí)安全性是一個(gè)較復(fù)雜的問(wèn)題。反射經(jīng)常由框架型代碼使用,由于這一點(diǎn),您可能希望框架能夠全面接入您的代碼,無(wú)需考慮常規(guī)的接入限制。但是,在其它情況下,不受控制的接入會(huì)帶來(lái)嚴(yán)重的安全性風(fēng)險(xiǎn),如當(dāng)代碼在不值得信任的代碼共享的環(huán)境中運(yùn)行時(shí)。
由于這些互相矛盾的需求,Java編程語(yǔ)言定義一種多級(jí)別方法來(lái)處理反射的安全性。基本模式是對(duì)反射實(shí)施與應(yīng)用于源代碼接入相同的的限制:
從任意位置到類公共組件的接入
類自身外部無(wú)任何到私有組件的接入
受保護(hù)和打包(缺省接入)組件的有限接入
不過(guò)-至少某些時(shí)候,圍繞這些限制有一種簡(jiǎn)單的方法。我在前面實(shí)例中使用的 Constructor 、 Field 和 Method 類都擴(kuò)展了一個(gè)普通的基本類--&#160 java.lang.reflect.AccessibleObject 類。該類定義一種 setAccessible 方法,使您能夠啟動(dòng)或關(guān)閉對(duì)這些類中其中一個(gè)類的實(shí)例的接入檢測(cè)。唯一的問(wèn)題在于如果使用了安全性管理器,它將檢測(cè)正在關(guān)閉接入檢測(cè)的代碼是否許可了這樣做。如果未許可,安全性管理器拋出一個(gè)例外。
清單6展示了一個(gè)程序,在 清單 1 TwoString 類的一個(gè)實(shí)例上使用反射來(lái)顯示安全性正在運(yùn)行:
    public class ReflectSecurity {
    public static void main(String[] args) {
        try {
            TwoString ts = new TwoString("a", "b");
            Field field = clas.getDeclaredField("m_s1");
//          field.setAccessible(true);
            System.out.println("Retrieved value is " +
                field.get(inst));
        } catch (Exception ex) {
            ex.printStackTrace(System.out);
        }
    }
}
  

如果您編譯了這一程序,不使用任何特定參數(shù)直接從命令行運(yùn)行,它將在 field.get(inst) 調(diào)用中拋出一個(gè) IllegalAccessException 。如果您未注釋 field.setAccessible(true) 代碼行,那么重新編譯并重新運(yùn)行該代碼,它將取得成功。最后,如果您在命令行添加了JVM參數(shù) -Djava.security.manager 以實(shí)現(xiàn)安全性管理器,它將再次失敗,除非您定義了 ReflectSecurity 類的許可權(quán)限。
反射性能
反射是一種強(qiáng)大的工具,但也存在一些不足。一個(gè)主要的缺點(diǎn)是對(duì)性能有影響。使用反射基本上是一種解釋操作,您可以告訴JVM您希望做什么并且它滿足您的要求。這類操作總是慢于只直接執(zhí)行相同的操作。為了闡述使用反射的性能成本,我為本文準(zhǔn)備了一組基準(zhǔn)程序(見(jiàn) 參考資料,完整代碼鏈接)。
清單7是字段接入性能測(cè)試的一個(gè)摘用,包括基本的測(cè)試方法。每種方法測(cè)試字段接入的一種形式 -- accessSame 與同一對(duì)象的成員字段協(xié)作, accessOther 使用可直接接入的另一對(duì)象的字段, accessReflection 使用可通過(guò)反射接入的另一對(duì)象的字段。在每種情況下,方法執(zhí)行相同的計(jì)算 -- 循環(huán)中簡(jiǎn)單的加/乘順序。
    public int accessSame(int loops) {
    m_value = 0;
    for (int index = 0; index < loops; index++) {
        m_value = (m_value + ADDITIVE_VALUE) *
            MULTIPLIER_VALUE;
    }
    return m_value;
}
public int accessReference(int loops) {
    TimingClass timing = new TimingClass();
    for (int index = 0; index < loops; index++) {
        timing.m_value = (timing.m_value + ADDITIVE_VALUE) *
            MULTIPLIER_VALUE;
    }
    return timing.m_value;
}
public int accessReflection(int loops) throws Exception {
    TimingClass timing = new TimingClass();
    try {
        Field field = TimingClass.class.
            getDeclaredField("m_value");
        for (int index = 0; index < loops; index++) {
            int value = (field.getInt(timing) +
                ADDITIVE_VALUE) * MULTIPLIER_VALUE;
            field.setInt(timing, value);
        }
        return timing.m_value;
    } catch (Exception ex) {
        System.out.println("Error using reflection");
        throw ex;
    }
}
  

測(cè)試程序重復(fù)調(diào)用每種方法,使用一個(gè)大循環(huán)數(shù),從而平均多次調(diào)用的時(shí)間衡量結(jié)果。平均值中不包括每種方法第一次調(diào)用的時(shí)間,因此初始化時(shí)間不是結(jié)果中的一個(gè)因素。在為本文進(jìn)行的測(cè)試中, 每次調(diào)用時(shí)我使用1000萬(wàn)的循環(huán)數(shù),在1GHz PIIIm系統(tǒng)上運(yùn)行。三個(gè)不同Linux JVM的計(jì)時(shí)結(jié)果如圖1所示。所有測(cè)試使用每個(gè)JVM的缺省設(shè)置。

java的動(dòng)態(tài)性編程(二)——引入Reflection
上表的對(duì)數(shù)尺度可以顯示所有時(shí)間,但減少了差異看得見(jiàn)的影響。在前兩副圖中(Sun JVM),使用反射的執(zhí)行時(shí)間超過(guò)使用直接接入的1000倍以上。通過(guò)比較,IBM JVM可能稍好一些,但反射方法仍舊需要比其它方法長(zhǎng)700倍以上的時(shí)間。任何JVM上其它兩種方法之間時(shí)間方面無(wú)任何顯著差異,但I(xiàn)BM JVM幾乎比Sun JVM快一倍。最有可能的是這種差異反映了Sun Hot Spot JVM的專業(yè)優(yōu)化,它在簡(jiǎn)單基準(zhǔn)方面表現(xiàn)得很糟糕。
除了字段接入時(shí)間測(cè)試之外,我還進(jìn)行了相同的方法調(diào)用時(shí)間測(cè)試。在方法調(diào)用中,我試用了與字段接入相同的三種接入變量,并增加了使用無(wú)參數(shù)方法變量,而不是在方法調(diào)用中傳遞和返回一個(gè)值。清單8顯示了用于測(cè)試調(diào)用傳遞和返回值形式的三種方法的代碼。
    public int callDirectArgs(int loops) {
    int value = 0;
    for (int index = 0; index < loops; index++) {
        value = step(value);
    }
    return value;
}
public int callReferenceArgs(int loops) {
    TimingClass timing = new TimingClass();
    int value = 0;
    for (int index = 0; index < loops; index++) {
        value = timing.step(value);
    }
    return value;
}
public int callReflectArgs(int loops) throws Exception {
    TimingClass timing = new TimingClass();
    try {
        Method method = TimingClass.class.getMethod
            ("step", new Class [] { int.class });
        Object[] args = new Object[1];
        Object value = new Integer(0);
        for (int index = 0; index < loops; index++) {
            args[0] = value;
            value = method.invoke(timing, args);
        }
        return ((Integer)value).intValue();
    } catch (Exception ex) {
        System.out.println("Error using reflection");
        throw ex;
    }
}
  

圖 2顯示了我從方法調(diào)用中獲得的計(jì)時(shí)結(jié)果。反射遠(yuǎn)慢于直接接入。差異不象字段接入那么大,但是,在不使用參數(shù)的情況下,范圍從Sun 1.3.1 JVM的數(shù)百倍到IBM JVM的不到30倍。在所有JVM上,使用參數(shù)的反射方法調(diào)用的測(cè)試性能慢于不使用參數(shù)的調(diào)用。由于傳遞和返回 int 值需要的 java.lang.Integer 封裝,這可能是局部的。由于 Integer s是不可變的,每種方法返回提出了一種新的需求,它將增加大量的開(kāi)銷。

java的動(dòng)態(tài)性編程(二)——引入Reflection
反射性能是Sun開(kāi)發(fā)1.4 JVM時(shí)關(guān)注的一個(gè)方面,它在反射方法調(diào)用結(jié)果中顯示。在這類操作的性能方面,Sun 1.4.1 JVM顯示了比1.3.1版本很大的改進(jìn),在我的測(cè)試中運(yùn)行速度大約是1.3.1版本的開(kāi)部。在這類簡(jiǎn)單的測(cè)試中,IBM 1.4.0 JVM再次獲得了更好的成績(jī),但是只比Sun 1.4.1 JVM快兩到三倍。
我還為創(chuàng)建使用反射的對(duì)象編寫了類似的計(jì)時(shí)測(cè)試程序,但這種情況下的差異不象字段和方法調(diào)用情況下那么顯著。使用 newInstance() 調(diào)用創(chuàng)建一個(gè)簡(jiǎn)單的 java.lang.Object 實(shí)例耗用的時(shí)間大約是在Sun 1.3.1 JVM上使用 new Object() 的12倍,是在IBM 1.4.0 JVM的四倍,只是Sun 1.4.1 JVM上的兩部。使用 Array.newInstance(type, size) 創(chuàng)建一個(gè)數(shù)組耗用的時(shí)間是任何測(cè)試的JVM上使用 new type[size] 的兩倍,隨著數(shù)組大小的增加,差異逐步縮小。
小結(jié)
Java語(yǔ)言反射提供一種動(dòng)態(tài)鏈接程序組件的多功能方法。它允許程序創(chuàng)建和控制任何類的對(duì)象(根據(jù)安全性限制),無(wú)需提前硬編碼目標(biāo)類。這些特性使得反射特別適用于創(chuàng)建以非常普通的方式與對(duì)象協(xié)作的庫(kù)。例如,反射經(jīng)常在持續(xù)存儲(chǔ)對(duì)象為數(shù)據(jù)庫(kù)、XML或其它外部格式的框架中使用。
反射有兩個(gè)缺點(diǎn)。第一個(gè)是性能問(wèn)題。當(dāng)用于字段和方法接入時(shí)反射要遠(yuǎn)慢于直接代碼。性能問(wèn)題的程度取決于程序中是如何使用反射的。如果它作為程序運(yùn)行中相對(duì)很少涉及的部分,緩慢的性能將不會(huì)是一個(gè)問(wèn)題。即使測(cè)試中最壞情況下的計(jì)時(shí)圖顯示的反射操作只耗用幾微秒。僅反射在性能關(guān)鍵的應(yīng)用的核心邏輯中使用時(shí)性能問(wèn)題才變得至關(guān)重要。
許多應(yīng)用更嚴(yán)重的一個(gè)缺點(diǎn)是使用反射會(huì)模糊程序內(nèi)部實(shí)際要發(fā)生的事情。程序人員希望在源代碼中看到程序的邏輯,反射等繞過(guò)了源代碼的技術(shù)會(huì)帶來(lái)維護(hù)問(wèn)題。反射代碼比相應(yīng)的直接代碼更復(fù)雜,正如性能比較的代碼實(shí)例中看到的一樣。解決這些問(wèn)題的最佳方案是保守地使用反射-- 僅在它可以真正增加靈活性的地方 -- 記錄其在目標(biāo)類中的使用。

java的動(dòng)態(tài)性編程(二)——引入Reflection


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 红安县| 武定县| 合川市| 黄浦区| 呈贡县| 城市| 儋州市| 龙门县| 绥宁县| 姚安县| 界首市| 石狮市| 东乌珠穆沁旗| 商水县| 遂昌县| 长武县| 禄丰县| 专栏| 邵武市| 沧源| 尉氏县| 长顺县| 晋州市| 兴国县| 汉寿县| 株洲市| 甘孜县| 桓仁| 介休市| 临清市| 额济纳旗| 明光市| 湾仔区| 房山区| 麦盖提县| 辛集市| 德钦县| 宝丰县| 定兴县| 永靖县| 济源市|