知識(shí)總結(jié)之 插件化基礎(chǔ) java反射與代理

Java平臺(tái)的反射機(jī)制是代碼動(dòng)態(tài)加載和調(diào)用的基本途徑天揖,在安卓系統(tǒng)源碼中也用到了大量的反射動(dòng)態(tài)加載類。反射也是安卓平臺(tái)插件化實(shí)現(xiàn)的必要掌握的基礎(chǔ)知識(shí)。代理是客戶端靈活操作對(duì)象,間接的低耦合度操作對(duì)象的有效途徑,也是插件化必要掌握知識(shí)激蹲。

安卓插件化基礎(chǔ) java反射與代理

一难裆、反射

java中反射機(jī)理比較常用瓢棒,這里主要以代碼實(shí)例展示其用法口糕。

什么是反射缅阳?

指程序運(yùn)行時(shí) 加載、獲取一個(gè)未知類(已知類名)及類屬性和方法的java技術(shù)機(jī)理景描。加載完成后會(huì)在虛擬機(jī)中產(chǎn)生一個(gè)class對(duì)象,一個(gè)類只有一個(gè)class對(duì)象秀撇,這個(gè)class對(duì)象包含了類的相關(guān)結(jié)構(gòu)信息超棺。
這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為java語(yǔ)言的反射機(jī)制。

Class對(duì)象如何獲群茄唷棠绘?

    1. 運(yùn)用Class.forName(String className)動(dòng)態(tài)加載類;
    1. .class 屬性(輕量級(jí))再扭;
    1. getClass()方法氧苍;

對(duì)象的創(chuàng)建

  • 使用Class對(duì)象的newInstance()方法來(lái)創(chuàng)建該Class對(duì)象對(duì)應(yīng)類的實(shí)例,這種方式要求該Class對(duì)象的對(duì)應(yīng)類有默認(rèn)構(gòu)造器泛范。
  • 先使用Class對(duì)象獲取指定的Constructor對(duì)象, 再調(diào)用Constructor對(duì)象的newInstance()让虐。通過(guò)這種方式可以選擇指定的構(gòu)造器來(lái)創(chuàng)建實(shí)例。
//Class 類 newInstance源碼
  @CallerSensitive
    public T newInstance()
        throws InstantiationException, IllegalAccessException
    {
        if (System.getSecurityManager() != null) {
            checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
        }

        // NOTE: the following code may not be strictly correct under
        // the current Java memory model.

        // Constructor lookup
        if (cachedConstructor == null) {
            if (this == Class.class) {
                throw new IllegalAccessException(
                    "Can not call newInstance() on the Class for java.lang.Class"
                );
            }
            try {
                Class<?>[] empty = {};
                final Constructor<T> c = getConstructor0(empty, Member.DECLARED);//默認(rèn)構(gòu)造器
                // Disable accessibility checks on the constructor
                // since we have to do the security check here anyway
                // (the stack depth is wrong for the Constructor's
                // security check to work)
                java.security.AccessController.doPrivileged(
                    new java.security.PrivilegedAction<Void>() {
                        public Void run() {
                                c.setAccessible(true);
                                return null;
                            }
                        });
                cachedConstructor = c;
            } catch (NoSuchMethodException e) {
                throw (InstantiationException)
                    new InstantiationException(getName()).initCause(e);
            }
        }
        Constructor<T> tmpConstructor = cachedConstructor;
        // Security check (same as in java.lang.reflect.Constructor)
        int modifiers = tmpConstructor.getModifiers();
        if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
            Class<?> caller = Reflection.getCallerClass();
            if (newInstanceCallerCache != caller) {
                Reflection.ensureMemberAccess(caller, this, null, modifiers);
                newInstanceCallerCache = caller;
            }
        }
        // Run constructor
        try {
            return tmpConstructor.newInstance((Object[])null);
        } catch (InvocationTargetException e) {
            Unsafe.getUnsafe().throwException(e.getTargetException());
            // Not reached
            return null;
        }
    }

相關(guān)Api相關(guān)實(shí)例

先定義一個(gè)bean類作為反射對(duì)象

 public class CankingBean extends Canking implements ICanking {
    private String name;
    private int id;

    public CankingBean() {
        //Nothing
    }

    public CankingBean(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String n) {
        this.name = n;
    }

    public int getId() {
        return id;
    }

    public void setId(int i) {
        this.id = i;

    }

    @Override
    public void createApp() {
        //nothing
    }
 }

1.對(duì)象實(shí)例化

     CankingBean bean = null, bean1 = null;

        Class test = null;
        try {
            test = Class.forName("com.canking.CankingBean");
        } catch (Exception e) {
            e.printStackTrace();
        }

        Constructor cons[] = test.getConstructors();
        System.out.println("cons.len:" + cons.length + " name:" + test.getName() + " simpleName:" + test.getSimpleName() + " Canonical:" + test.getCanonicalName() + " type:" + test.getTypeName());


        try {
            bean = (CankingBean) cons[0].newInstance();
            bean1 = (CankingBean) cons[1].newInstance(1, "canking");
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("bean.id:" + bean.getId() + " bean.name:" + bean.getName() + " b1.id:" + bean1.getId() + " b1.name:" + bean1.getName());

2. 獲取實(shí)現(xiàn)接口列表

    Class<?> intes[]=test.getInterfaces();  

3.獲取父類

 Class<?> temp=demo.getSuperclass();  

4.獲取類屬性

  Field[] fields = test.getDeclaredFields();//本類屬性
        for (Field f : fields) {
            int modifier = f.getModifiers();//修飾符
            String modiStr = Modifier.toString(modifier);

            Class type = f.getType();
            System.out.println(f.getName() + " || modifier:" + modiStr + " type:" + type.getName());
        }
        System.out.println("\n");

        Field[] fieldsAll = test.getFields();//接口中屬性
        for (Field f : fieldsAll) {
            int modifier = f.getModifiers();//修飾符
            String modiStr = Modifier.toString(modifier);

            Class type = f.getType();
            System.out.println(f.getName() + " || modifier:" + modiStr + " type:" + type.getName());
        }

想要獲取父類中屬性怎么辦罢荡?getSuperclass()先獲取父類實(shí)例赡突,然后調(diào)用getDeclaredFields()獲取∏裕可以依次遍歷super類惭缰,獲得全部繼承關(guān)系中的屬性。

5.獲取類方法

  Method method[] = test.getMethods(); //獲取類及繼承關(guān)系中的所有類方法
        for(Method m : method){
            Class<?> returnType = m.getReturnType();
            Class<?> para[] = m.getParameterTypes();
            int temp = m.getModifiers();

            System.out.println(m.getName()+" returnType:"+returnType+" modifiers:"+Modifier.toString(temp));
            for(Class c : para){
                System.out.println(" c name:"+c.getName());
            }
        }

6.方法及屬性的操作

       try {
            Method ms = test.getMethod("setName", String.class);
            Method mg = test.getMethod("getName");
            Object obj = test.newInstance();
            ms.invoke(obj, "New name");
            System.out.println("name:" + mg.invoke(obj));

            Field canking = test.getDeclaredField("name");
            canking.setAccessible(true);//禁用權(quán)限檢測(cè)
            canking.set(obj, "Name Modified!");
            System.out.println("name:" + canking.get(obj));
        } catch (Exception e) {
            e.printStackTrace();
        }

二笼才、代理

什么是java代理模式漱受?

代理用到類反射的知識(shí),這里進(jìn)一步單獨(dú)講解加深理解骡送。

對(duì)某個(gè)對(duì)象提供一個(gè)代理對(duì)象昂羡,使得我們可以通過(guò)代理對(duì)象間接的操作原對(duì)象。

靜態(tài)代理:代碼層通過(guò)設(shè)計(jì)類獲得一個(gè)中間層代理各谚,是在編譯時(shí)已經(jīng)實(shí)現(xiàn)好的紧憾,可以說(shuō)是一個(gè)class文件。
動(dòng)態(tài)代理:代理類是在運(yùn)行時(shí)由java機(jī)理產(chǎn)生昌渤。起到動(dòng)態(tài)調(diào)用和操作代碼的目的赴穗。

由于靜態(tài)代理比較簡(jiǎn)單,易于理解,本文主要講解動(dòng)態(tài)代理般眉。

基本概念

InvocationHandler接口
代理類調(diào)用任何方法都會(huì)經(jīng)過(guò)這個(gè)調(diào)用處理器類的invoke方法了赵。

Proxy
主要用于產(chǎn)生代理類,通過(guò) Proxy 類生成的代理類都繼承了 Proxy 類甸赃。newProxyInstance方法封裝了獲取代理對(duì)象柿汛。

newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);方法傳如的參數(shù)可以看出,代理一個(gè)對(duì)象埠对,必須要要滿足這個(gè)對(duì)象實(shí)現(xiàn)一個(gè)接口络断。

動(dòng)態(tài)代理實(shí)現(xiàn)方法

個(gè)人學(xué)習(xí)習(xí)慣,學(xué)習(xí)新知識(shí)项玛,先了解大概貌笨,然后就是代碼,最后看原理襟沮,有精力的話就寫(xiě)點(diǎn)東西分享出來(lái)锥惋。這里就先看下代碼如何實(shí)現(xiàn)一個(gè)動(dòng)態(tài)代理。

只要一個(gè)類滿足代理?xiàng)l件开伏,即可實(shí)現(xiàn)代理膀跌。

 public class CankingProxyHandler implements InvocationHandler {
    private Object object;
    public CankingProxyHandler(Object obj){
        this.object= obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Proxy method in");
        if ("setName".equals(method.getName())) {
            return method.invoke(object, "Proxy");
        }
        return method.invoke(object, args);
    }
 }
        CankingProxyHandler proxyHandler = new CankingProxyHandler(bean1);
        ICanking cProxy = (ICanking) Proxy.newProxyInstance(CankingBean.class.getClassLoader(), CankingBean.class.getInterfaces(), proxyHandler);
        cProxy.createApp();

代理類的每次方法調(diào)用,都會(huì)觸發(fā)proxyHandler的invoke方法固灵,這樣我們就可以在此時(shí)做一些自己的事情捅伤。

android系統(tǒng)中有些類也是滿足代理?xiàng)l件的,這樣我們同樣可以做一個(gè)代理類怎虫,來(lái)實(shí)現(xiàn)hook系統(tǒng)部分方法的目的暑认。

實(shí)現(xiàn)原理

首先來(lái)看下newProxyInstance源碼

    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);

        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * Look up or generate the designated proxy class.
         */
        Class<?> cl = getProxyClass0(loader, intfs); //代理類生成關(guān)鍵方法

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }

            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }

可以看出getProxyClass0()方法為生成代理類關(guān)鍵方法

    /**
     * Generate a proxy class.  Must call the checkProxyAccess method
     * to perform permission checks before calling this.
     */
    private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }

        // If the proxy class defined by the given loader implementing
        // the given interfaces exists, this will simply return the cached copy;
        // otherwise, it will create the proxy class via the ProxyClassFactory
        return proxyClassCache.get(loader, interfaces);
    }

看到源碼注釋,如果代理類在傳入的classloader中已經(jīng)加載則直接返回大审,否則會(huì)在ProxyClassFactory中生成蘸际。

proxyClassCache.get方法中有以下代碼

        // create subKey and retrieve the possible Supplier<V> stored by that
        // subKey from valuesMap
        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
        Supplier<V> supplier = valuesMap.get(subKey);

結(jié)合代碼和注釋可以大概看出subKeyFactory.apply(key, parameter)返回的就是代理類

那我們具體看看apply是怎么生產(chǎn)我們的代理類的:

        @Override
        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
            for (Class<?> intf : interfaces) {
                /*
                 * Verify that the class loader resolves the name of this
                 * interface to the same Class object.
                 */
                Class<?> interfaceClass = null;
                try {
                    interfaceClass = Class.forName(intf.getName(), false, loader);//加載原始接口
                } catch (ClassNotFoundException e) {
                }
                if (interfaceClass != intf) {
                    throw new IllegalArgumentException(
                        intf + " is not visible from class loader");
                }
                /*
                 * Verify that the Class object actually represents an
                 * interface.
                 */
                if (!interfaceClass.isInterface()) {
                    throw new IllegalArgumentException(
                        interfaceClass.getName() + " is not an interface");
                }
                /*
                 * Verify that this interface is not a duplicate.
                 */
                if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
                    throw new IllegalArgumentException(
                        "repeated interface: " + interfaceClass.getName());
                }
            }

            String proxyPkg = null;     // package to define proxy class in
            int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

            /*
             * Record the package of a non-public proxy interface so that the
             * proxy class will be defined in the same package.  Verify that
             * all non-public proxy interfaces are in the same package.
             */
            for (Class<?> intf : interfaces) {//解析原始接口
                int flags = intf.getModifiers();
                if (!Modifier.isPublic(flags)) {
                    accessFlags = Modifier.FINAL;
                    String name = intf.getName();
                    int n = name.lastIndexOf('.');
                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                    if (proxyPkg == null) {
                        proxyPkg = pkg;
                    } else if (!pkg.equals(proxyPkg)) {
                        throw new IllegalArgumentException(
                            "non-public interfaces from different packages");
                    }
                }
            }

            if (proxyPkg == null) {
                // if no non-public proxy interfaces, use com.sun.proxy package
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
            }

            /*
             * Choose a name for the proxy class to generate.
             */
            long num = nextUniqueNumber.getAndIncrement();
            String proxyName = proxyPkg + proxyClassNamePrefix + num;//構(gòu)造代理類名

            /*
             * Generate the specified proxy class.
             */
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);//生產(chǎn)代理類
            try {
                return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
                /*
                 * A ClassFormatError here means that (barring bugs in the
                 * proxy class generation code) there was some other
                 * invalid aspect of the arguments supplied to the proxy
                 * class creation (such as virtual machine limitations
                 * exceeded).
                 */
                throw new IllegalArgumentException(e.toString());
            }
        }

最終ProxyGenerator.generateProxyClass方法中產(chǎn)生類代理類并寫(xiě)入磁盤(pán)。這種操作代碼的代碼java總稱為元編程徒扶,java SOURCE級(jí)別的注解中也會(huì)大量用到粮彤。

代理類最終生產(chǎn)的樣子如下:

public final class $Proxy1 extends Proxy implements Subject{
    private InvocationHandler h;
    private $Proxy1(){}
    public $Proxy1(InvocationHandler h){
        this.h = h;
    }
    public int request(int i){
        Method method = Subject.class.getMethod("method", new Class[]{int.class});    //創(chuàng)建method對(duì)象
        return (Integer)h.invoke(this, method, new Object[]{new Integer(i)}); //調(diào)用了invoke方法
    }
}

從代理來(lái)結(jié)構(gòu),可以看出為什么每次方法的調(diào)用都會(huì)掉到invocationHandler的invoke方法姜骡。

——————
歡迎轉(zhuǎn)載导坟,請(qǐng)標(biāo)明出處:常興E站 www.canking.win

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市圈澈,隨后出現(xiàn)的幾起案子惫周,更是在濱河造成了極大的恐慌,老刑警劉巖康栈,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件递递,死亡現(xiàn)場(chǎng)離奇詭異喷橙,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)登舞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)贰逾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人菠秒,你說(shuō)我怎么就攤上這事疙剑。” “怎么了践叠?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵言缤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我禁灼,道長(zhǎng)轧简,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任匾二,我火速辦了婚禮,結(jié)果婚禮上拳芙,老公的妹妹穿的比我還像新娘察藐。我一直安慰自己,他們只是感情好舟扎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布分飞。 她就那樣靜靜地躺著,像睡著了一般睹限。 火紅的嫁衣襯著肌膚如雪譬猫。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,562評(píng)論 1 305
  • 那天羡疗,我揣著相機(jī)與錄音染服,去河邊找鬼。 笑死叨恨,一個(gè)胖子當(dāng)著我的面吹牛柳刮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播痒钝,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼秉颗,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了送矩?” 一聲冷哼從身側(cè)響起蚕甥,我...
    開(kāi)封第一講書(shū)人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎栋荸,沒(méi)想到半個(gè)月后菇怀,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體凭舶,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年敏释,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了库快。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡钥顽,死狀恐怖义屏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蜂大,我是刑警寧澤闽铐,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站奶浦,受9級(jí)特大地震影響兄墅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜澳叉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一隙咸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧成洗,春花似錦五督、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至遥椿,卻和暖如春基矮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背冠场。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工家浇, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人慈鸠。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓蓝谨,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親青团。 傳聞我的和親對(duì)象是個(gè)殘疾皇子譬巫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一:java概述:1,JDK:Java Development Kit督笆,java的開(kāi)發(fā)和運(yùn)行環(huán)境芦昔,java的開(kāi)發(fā)工...
    ZaneInTheSun閱讀 2,651評(píng)論 0 11
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法娃肿,內(nèi)部類的語(yǔ)法咕缎,繼承相關(guān)的語(yǔ)法珠十,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,631評(píng)論 18 399
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理凭豪,服務(wù)發(fā)現(xiàn)焙蹭,斷路器,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • 今天換了新繪本嫂伞,晰晰抱著就不撒手了 睡午覺(jué)的時(shí)候關(guān)燈躺下就開(kāi)始跟我瘋玩孔厉,晰晰徹底玩瘋了,一直處于興奮狀態(tài)不睡覺(jué)帖努,所...
    晰晰麻麻閱讀 275評(píng)論 0 0
  • 不謀全局者不足以謀一域撰豺,中國(guó)房市走向的風(fēng)向標(biāo)標(biāo)就是京滬深,京滬深的房?jī)r(jià)目前有點(diǎn)像股市中的茅臺(tái)拼余,長(zhǎng)線一直看好污桦,沒(méi)有最...
    老凱哥閱讀 182評(píng)論 0 1