Java 靜態(tài)代理俄烁、Java動態(tài)代理涩咖、CGLIB動態(tài)代理

開篇

Java 的代理就是客戶類不再直接和委托類打交道, 而是通過一個中間層來訪問, 這個中間層就是代理海诲。為啥要這樣呢, 是因為使用代理有 2 個優(yōu)勢:

可以隱藏委托類的實現(xiàn)

可以實現(xiàn)客戶與委托類之間的解耦, 在不修改委托類代碼的情況下能夠做一些額外的處理

我們舉個很常見的例子: 工廠會生產(chǎn)很多的玩具, 但是我們買玩具都是到商店買的, 而不是到工廠去買的, 工廠怎么生產(chǎn)我們并不關(guān)心, 我們只知道到商店可以買到自己想要的玩具,并且檩互,如果我們需要送人的話商店可以把這些玩具使用禮品盒包裝特幔。這個工廠就是委托類, 商店就是代理類, 我們就是客戶類。

在 Java 中我們有很多場景需要使用代理類, 比如遠程 RPC 調(diào)用的時候我們就是通過代理類去實現(xiàn)的, 還有 Spring 的 AOP 切面中我們也是為切面生成了一個代理類等等闸昨。
代理類主要分為靜態(tài)代理蚯斯、JDK 動態(tài)代理和 CGLIB 動態(tài)代理,它們各有優(yōu)缺點饵较,沒有最好的, 存在就是有意義的拍嵌,在不同的場景下它們會有不同的用武之地。

1. Java 靜態(tài)代理
首先, 定義接口和接口的實現(xiàn)類, 然后定義接口的代理對象, 將接口的實例注入到代理對象中, 然后通過代理對象去調(diào)用真正的實現(xiàn)類告抄,實現(xiàn)過程非常簡單也比較容易理解, 靜態(tài)代理的代理關(guān)系在編譯期間就已經(jīng)確定了的撰茎。它適合于代理類較少且確定的情況。它可實現(xiàn)在怒修改委托類代碼的情況下做一些額外的處理打洼,比如包裝禮盒,實現(xiàn)客戶類與委托類的解耦逆粹。缺點是只適用委托方法少的情況下, 試想一下如果委托類有幾百上千個方法, 豈不是很難受, 要在代理類中寫一堆的代理方法募疮。這個需求動態(tài)代理可以搞定

// 委托接口
public interface IHelloService {

    /**
     * 定義接口方法
     * @param userName
     * @return
     */
    String sayHello(String userName);

}
// 委托類實現(xiàn)
public class HelloService implements IHelloService {

    @Override
    public String sayHello(String userName) {
        System.out.println("helloService" + userName);
        return "HelloService" + userName;
    }
}

// 代理類
public class StaticProxyHello implements IHelloService {

    private IHelloService helloService = new HelloService();

    @Override
    public String sayHello(String userName) {
        /** 代理對象可以在此處包裝一下*/
        System.out.println("代理對象包裝禮盒...");
        return helloService.sayHello(userName);
    }
}
// 測試靜態(tài)代理類
public class MainStatic {
    public static void main(String[] args) {
        StaticProxyHello staticProxyHello = new StaticProxyHello();
        staticProxyHello.sayHello("isole");
    }
}

2. 動態(tài)代理技術(shù)
代理類在程序運行時創(chuàng)建的代理方式被成為 動態(tài)代理。在了解動態(tài)代理之前, 我們先簡回顧一下 JVM 的類加載機制中的加載階段要做的三件事情
( 附 Java 中的類加載器 )

通過一個類的全名或其它途徑來獲取這個類的二進制字節(jié)流

將這個字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運行時數(shù)據(jù)結(jié)構(gòu)

在內(nèi)存中生成一個代表這個類的 Class 對象, 作為方法區(qū)中對這個類訪問的入口

而我們要說的動態(tài)代理僻弹,主要就發(fā)生在第一個階段, 這個階段類的二進制字節(jié)流的來源可以有很多, 比如 zip 包阿浓、網(wǎng)絡(luò)、運行時計算生成蹋绽、其它文件生成 (JSP)芭毙、數(shù)據(jù)庫獲取。其中運行時計算生成就是我們所說的動態(tài)代理技術(shù)卸耘,在 Proxy 類中, 就是運用了 ProxyGenerator.generateProxyClass 來為特定接口生成形式為 *$Proxy 的代理類的二進制字節(jié)流退敦。所謂的動態(tài)代理就是想辦法根據(jù)接口或者目標(biāo)對象計算出代理類的字節(jié)碼然后加載進 JVM 中。實際計算的情況會很復(fù)雜蚣抗,我們借助一些諸如 JDK 動態(tài)代理實現(xiàn)侈百、CGLIB 第三方庫來完成的

另一方面為了讓生成的代理類與目標(biāo)對象 (就是委托類) 保持一致, 我們有 2 種做法:通過接口的 JDK 動態(tài)代理 和通過繼承類的 CGLIB 動態(tài)代理。(還有一個使用了 ASM 框架的 javassist 太復(fù)雜了,我還沒研究過, 這里TODO下)

3. JDK 動態(tài)代理
在 Java 的動態(tài)代理中, 主要涉及 2 個類,java.lang.reflect.Proxy和java.lang.reflect.InvocationHandler
我們需要一個實現(xiàn) InvocationHandler 接口的中間類, 這個接口只有一個方法 invoke 方法, 方法的每個參數(shù)的注釋如下代碼钝域。

我們對處理類中的所有方法的調(diào)用都會變成對 invoke 方法的調(diào)用讽坏,這樣我們可以在 invoke 方法中添加統(tǒng)一的處理邏輯(也可以根據(jù) method 參數(shù)判斷是哪個方法)。中間類 (實現(xiàn)了 InvocationHandler 的類) 有一個委托類對象引用, 在 Invoke 方法中調(diào)用了委托類對象的相應(yīng)方法例证,通過這種聚合的方式持有委托類對象引用路呜,把外部對 invoke 的調(diào)用最終都轉(zhuǎn)為對委托類對象的調(diào)用。

實際上织咧,中間類與委托類構(gòu)成了靜態(tài)代理關(guān)系胀葱,在這個關(guān)系中,中間類是代理類烦感,委托類是委托類巡社。然后代理類與中間類也構(gòu)成一個靜態(tài)代理關(guān)系,在這個關(guān)系中手趣,中間類是委托類晌该,代理類是代理類。也就是說绿渣,動態(tài)代理關(guān)系由兩組靜態(tài)代理關(guān)系組成朝群,這就是動態(tài)代理的原理。

public interface InvocationHandler {
    /**
     * 調(diào)用處理
     * @param proxy 代理類對象
     * @param methon 標(biāo)識具體調(diào)用的是代理類的哪個方法
     * @param args 代理類方法的參數(shù)
     */
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}
Demo 如下:

// 委托類接口
public interface IHelloService {

    /**
     * 方法1
     * @param userName
     * @return
     */
    String sayHello(String userName);

    /**
     * 方法2
     * @param userName
     * @return
     */
    String sayByeBye(String userName);

}
// 委托類
public class HelloService implements IHelloService {

    @Override
    public String sayHello(String userName) {
        System.out.println(userName + " hello");
        return userName + " hello";
    }

    @Override
    public String sayByeBye(String userName) {
        System.out.println(userName + " ByeBye");
        return userName + " ByeBye";
    }
}
// 中間類
public class JavaProxyInvocationHandler implements InvocationHandler {

    /**
     * 中間類持有委托類對象的引用,這里會構(gòu)成一種靜態(tài)代理關(guān)系
     */
    private Object obj ;

    /**
     * 有參構(gòu)造器,傳入委托類的對象
     * @param obj 委托類的對象
     */
    public JavaProxyInvocationHandler(Object obj){
        this.obj = obj;

    }

    /**
     * 動態(tài)生成代理類對象,Proxy.newProxyInstance
     * @return 返回代理類的實例
     */
    public Object newProxyInstance() {
        return Proxy.newProxyInstance(
                //指定代理對象的類加載器
                obj.getClass().getClassLoader(),
                //代理對象需要實現(xiàn)的接口中符,可以同時指定多個接口
                obj.getClass().getInterfaces(),
                //方法調(diào)用的實際處理者姜胖,代理對象的方法調(diào)用都會轉(zhuǎn)發(fā)到這里
                this);
    }


    /**
     *
     * @param proxy 代理對象
     * @param method 代理方法
     * @param args 方法的參數(shù)
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("invoke before");
        Object result = method.invoke(obj, args);
        System.out.println("invoke after");
        return result;
    }
}
// 測試動態(tài)代理類
public class MainJavaProxy {
    public static void main(String[] args) {
        JavaProxyInvocationHandler proxyInvocationHandler = new JavaProxyInvocationHandler(new HelloService());
        IHelloService helloService = (IHelloService) proxyInvocationHandler.newProxyInstance();
        helloService.sayByeBye("paopao");
        helloService.sayHello("yupao");
    }

}

在上面的測試動態(tài)代理類中, 我們調(diào)用 Proxy 類的 newProxyInstance 方法來獲取一個代理類實例。這個代理類實現(xiàn)了我們指定的接口并且會把方法調(diào)用分發(fā)到指定的調(diào)用處理器淀散。

首先通過 newProxyInstance 方法獲取代理類的實例, 之后就可以通過這個代理類的實例調(diào)用代理類的方法右莱,對代理類的方法調(diào)用都會調(diào)用中間類 (實現(xiàn)了 invocationHandle 的類) 的 invoke 方法,在 invoke 方法中我們調(diào)用委托類的對應(yīng)方法档插,然后加上自己的處理邏輯慢蜓。

java 動態(tài)代理最大的特點就是動態(tài)生成的代理類和委托類實現(xiàn)同一個接口。java 動態(tài)代理其實內(nèi)部是通過反射機制實現(xiàn)的郭膛,也就是已知的一個對象晨抡,在運行的時候動態(tài)調(diào)用它的方法,并且調(diào)用的時候還可以加一些自己的邏輯在里面则剃。(附: Java 反射)

3.2 Proxy.newProxyInstance 源碼閱讀

上面說過, Proxy.newProxyInstance 通過反射機制用來動態(tài)生成代理類對象, 為接口創(chuàng)建一個代理類耘柱,這個代理類實現(xiàn)這個接口。具體源碼如下:

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        // 檢查空指針
        Objects.requireNonNull(h);
        // 用原型實例指定創(chuàng)建對象的種類,并且通過拷貝這些原型創(chuàng)建新的對象
        final Class<?>[] intfs = interfaces.clone();
        // 獲取系統(tǒng)的安全接口,不為空的話需要驗證是否允許訪問這種關(guān)系的代理訪問
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * 生成代理類 Class,通過類加載器和接口
         */
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * 通過構(gòu)造器來創(chuàng)建實例
         */
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }
            //獲取所有的構(gòu)造器
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            // 構(gòu)造器不是public的話需要設(shè)置可以訪問
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            // 返回創(chuàng)建的代理類Class的實例對象
            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);
        }
    }

4. CGLIB 動態(tài)代理
JDK 動態(tài)代理依賴接口實現(xiàn)棍现,而當(dāng)我們只有類沒有接口的時候就需要使用另一種動態(tài)代理技術(shù) CGLIB 動態(tài)代理调煎。首先 CGLIB 動態(tài)代理是第三方框架實現(xiàn)的,在 maven 工程中我們需要引入 cglib 的包, 如下:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2</version>
</dependency>

CGLIB 代理是針對類來實現(xiàn)代理的轴咱,原理是對指定的委托類生成一個子類并重寫其中業(yè)務(wù)方法來實現(xiàn)代理汛蝙。代理類對象是由 Enhancer 類創(chuàng)建的烈涮。CGLIB 創(chuàng)建動態(tài)代理類的模式是:

查找目標(biāo)類上的所有非 final 的 public 類型的方法 (final 的不能被重寫)

將這些方法的定義轉(zhuǎn)成字節(jié)碼

將組成的字節(jié)碼轉(zhuǎn)換成相應(yīng)的代理的 Class 對象然后通過反射獲得代理類的實例對象

實現(xiàn) MethodInterceptor 接口, 用來處理對代理類上所有方法的請求


// 委托類,是一個簡單類
public class CglibHelloClass {
   /**
    * 方法1
    * @param userName
    * @return
    */
   public String sayHello(String userName){
       System.out.println("目標(biāo)對象的方法執(zhí)行了");
       return userName + " sayHello";
   }

   public String sayByeBye(String userName){
       System.out.println("目標(biāo)對象的方法執(zhí)行了");
       return userName + " sayByeBye";
   }

}
/**
* CglibInterceptor 用于對方法調(diào)用攔截以及回調(diào)
*
*/
public class CglibInterceptor implements MethodInterceptor {
   /**
    * CGLIB 增強類對象,代理類對象是由 Enhancer 類創(chuàng)建的窖剑,
    * Enhancer 是 CGLIB 的字節(jié)碼增強器坚洽,可以很方便的對類進行拓展
    */
   private Enhancer enhancer = new Enhancer();

   /**
    *
    * @param obj  被代理的對象
    * @param method 代理的方法
    * @param args 方法的參數(shù)
    * @param proxy CGLIB方法代理對象
    * @return  cglib生成用來代替Method對象的一個對象,使用MethodProxy比調(diào)用JDK自身的Method直接執(zhí)行方法效率會有提升
    * @throws Throwable
    */
   @Override
   public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
       System.out.println("方法調(diào)用之前");
       Object o = proxy.invokeSuper(obj, args);
       System.out.println("方法調(diào)用之后");
       return o;
   }


   /**
    * 使用動態(tài)代理創(chuàng)建一個代理對象
    * @param c
    * @return
    */
   public  Object newProxyInstance(Class<?> c) {
       /**
        * 設(shè)置產(chǎn)生的代理對象的父類,增強類型
        */
       enhancer.setSuperclass(c);
       /**
        * 定義代理邏輯對象為當(dāng)前對象西土,要求當(dāng)前對象實現(xiàn) MethodInterceptor 接口
        */
       enhancer.setCallback(this);
       /**
        * 使用默認無參數(shù)的構(gòu)造函數(shù)創(chuàng)建目標(biāo)對象,這是一個前提,被代理的類要提供無參構(gòu)造方法
        */
       return enhancer.create();
   }
}

//測試類
public class MainCglibProxy {
    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy();
        CglibHelloClass cglibHelloClass = (CglibHelloClass) cglibProxy.newProxyInstance(CglibHelloClass.class);
        cglibHelloClass.sayHello("isole");
        cglibHelloClass.sayByeBye("sss");
    }
}

對于需要被代理的類讶舰,它只是動態(tài)生成一個子類以覆蓋非 final 的方法,同時綁定鉤子回調(diào)自定義的攔截器需了。值得說的是跳昼,它比 JDK 動態(tài)代理還要快。值得注意的是肋乍,我們傳入目標(biāo)類作為代理的父類鹅颊。不同于 JDK 動態(tài)代理,我們不能使用目標(biāo)對象來創(chuàng)建代理墓造。目標(biāo)對象只能被 CGLIB 創(chuàng)建堪伍。在例子中,默認的無參構(gòu)造方法被使用來創(chuàng)建目標(biāo)對象觅闽。

總結(jié)

靜態(tài)代理比較容易理解, 需要被代理的類和代理類實現(xiàn)自同一個接口, 然后在代理類中調(diào)用真正實現(xiàn)類, 并且靜態(tài)代理的關(guān)系在編譯期間就已經(jīng)確定了帝雇。而動態(tài)代理的關(guān)系是在運行期間確定的。靜態(tài)代理實現(xiàn)簡單蛉拙,適合于代理類較少且確定的情況尸闸,而動態(tài)代理則給我們提供了更大的靈活性。

JDK 動態(tài)代理所用到的代理類在程序調(diào)用到代理類對象時才由 JVM 真正創(chuàng)建孕锄,JVM 根據(jù)傳進來的 業(yè)務(wù)實現(xiàn)類對象 以及 方法名 吮廉,動態(tài)地創(chuàng)建了一個代理類的 class 文件并被字節(jié)碼引擎執(zhí)行,然后通過該代理類對象進行方法調(diào)用畸肆。我們需要做的茧痕,只需指定代理類的預(yù)處理、調(diào)用后操作即可恼除。

靜態(tài)代理和動態(tài)代理都是基于接口實現(xiàn)的, 而對于那些沒有提供接口只是提供了實現(xiàn)類的而言, 就只能選擇 CGLIB 動態(tài)代理了

JDK 動態(tài)代理和 CGLIB 動態(tài)代理的區(qū)別

JDK 動態(tài)代理基于 Java 反射機制實現(xiàn), 必須要實現(xiàn)了接口的業(yè)務(wù)類才能用這種方法生成代理對象。

CGLIB 動態(tài)代理基于 ASM 框架通過生成業(yè)務(wù)類的子類來實現(xiàn)曼氛。

JDK 動態(tài)代理的優(yōu)勢是最小化依賴關(guān)系豁辉,減少依賴意味著簡化開發(fā)和維護并且有 JDK 自身支持。還可以平滑進行 JDK 版本升級舀患,代碼實現(xiàn)簡單徽级。基于 CGLIB 框架的優(yōu)勢是無須實現(xiàn)接口聊浅,達到代理類無侵入餐抢,我們只需操作我們關(guān)系的類现使,不必為其它相關(guān)類增加工作量,性能比較高旷痕。

描述代理的幾種實現(xiàn)方式? 分別說出優(yōu)缺點?

代理可以分為 "靜態(tài)代理" 和 "動態(tài)代理"碳锈,動態(tài)代理又分為 "JDK 動態(tài)代理" 和 "CGLIB 動態(tài)代理" 實現(xiàn)。

靜態(tài)代理:代理對象和實際對象都繼承了同一個接口欺抗,在代理對象中指向的是實際對象的實例售碳,這樣對外暴露的是代理對象而真正調(diào)用的是 Real Object.

優(yōu)點:可以很好的保護實際對象的業(yè)務(wù)邏輯對外暴露,從而提高安全性绞呈。*

缺點:不同的接口要有不同的代理類實現(xiàn)贸人,會很冗余

JDK 動態(tài)代理:
為了解決靜態(tài)代理中,生成大量的代理類造成的冗余佃声;
JDK 動態(tài)代理只需要實現(xiàn) InvocationHandler 接口艺智,重寫 invoke 方法便可以完成代理的實現(xiàn),

jdk 的代理是利用反射生成代理類 Proxyxx.class 代理類字節(jié)碼圾亏,并生成對象
jdk 動態(tài)代理之所以只能代理接口是因為代理類本身已經(jīng) extends 了 Proxy十拣,而 java 是不允許多重繼承的,但是允許實現(xiàn)多個接口

優(yōu)點:解決了靜態(tài)代理中冗余的代理實現(xiàn)類問題召嘶。

缺點:JDK 動態(tài)代理是基于接口設(shè)計實現(xiàn)的父晶,如果沒有接口,會拋異常弄跌。

CGLIB 代理:
由于 JDK 動態(tài)代理限制了只能基于接口設(shè)計甲喝,而對于沒有接口的情況,JDK 方式解決不了铛只;
CGLib 采用了非常底層的字節(jié)碼技術(shù)埠胖,其原理是通過字節(jié)碼技術(shù)為一個類創(chuàng)建子類,并在子類中采用方法攔截的技術(shù)攔截所有父類方法的調(diào)用淳玩,順勢織入橫切邏輯直撤,來完成動態(tài)代理的實現(xiàn)。
實現(xiàn)方式實現(xiàn) MethodInterceptor 接口蜕着,重寫 intercept 方法谋竖,通過 Enhancer 類的回調(diào)方法來實現(xiàn)。

但是 CGLib 在創(chuàng)建代理對象時所花費的時間卻比 JDK 多得多承匣,所以對于單例的對象蓖乘,因為無需頻繁創(chuàng)建對象,用 CGLib 合適韧骗,反之嘉抒,使用 JDK 方式要更為合適一些。
同時袍暴,由于 CGLib 由于是采用動態(tài)創(chuàng)建子類的方法些侍,對于 final 方法隶症,無法進行代理。

優(yōu)點:沒有接口也能實現(xiàn)動態(tài)代理岗宣,而且采用字節(jié)碼增強技術(shù)蚂会,性能也不錯。
缺點:技術(shù)實現(xiàn)相對難理解些狈定。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末颂龙,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子纽什,更是在濱河造成了極大的恐慌措嵌,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芦缰,死亡現(xiàn)場離奇詭異企巢,居然都是意外死亡,警方通過查閱死者的電腦和手機让蕾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門浪规,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人探孝,你說我怎么就攤上這事笋婿。” “怎么了顿颅?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵缸濒,是天一觀的道長。 經(jīng)常有香客問我粱腻,道長庇配,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任绍些,我火速辦了婚禮捞慌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘柬批。我一直安慰自己啸澡,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布氮帐。 她就那樣靜靜地躺著锻霎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪揪漩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天吏口,我揣著相機與錄音奄容,去河邊找鬼冰更。 笑死,一個胖子當(dāng)著我的面吹牛昂勒,可吹牛的內(nèi)容都是我干的蜀细。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼戈盈,長吁一口氣:“原來是場噩夢啊……” “哼奠衔!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起塘娶,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤归斤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后刁岸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體脏里,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年虹曙,在試婚紗的時候發(fā)現(xiàn)自己被綠了迫横。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡酝碳,死狀恐怖矾踱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情疏哗,我是刑警寧澤呛讲,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站沃斤,受9級特大地震影響圣蝎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜衡瓶,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一徘公、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧哮针,春花似錦关面、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蛮放,卻和暖如春缩抡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背包颁。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工瞻想, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留压真,地道東北人。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓蘑险,卻偏偏與公主長得像滴肿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子佃迄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,092評論 2 355