面向?qū)ο缶幊淘O(shè)計模式------代理模式(靜態(tài)代理鬓椭、動態(tài)代理)

代理模式

??代理模式的定義:給某一個對象提供一個代理颠猴,并由代理對象控制對原對象的引用。
??代理(Proxy)是一種設(shè)計模式小染,提供了對目標對象另外的訪問方式翘瓮;即通過代理對象訪問目標對象。這樣做的好處是:可以在目標對象實現(xiàn)的基礎(chǔ)上裤翩,增強額外的功能操作资盅,即擴展目標對象的功能。
??這里使用到編程中的一個思想:不要隨意去修改別人已經(jīng)寫好的代碼或者方法岛都,如果需改修改律姨,可以通過代理的方式來擴展該方法。
??舉個例子來說明代理的作用:假設(shè)我們想邀請一位明星臼疫,那么并不是直接聯(lián)系明星择份,而是聯(lián)系明星的經(jīng)紀人,來達到同樣的目的烫堤。明星就是一個目標對象荣赶,他只要負責活動中的節(jié)目凤价,而其他瑣碎的事情就交給他的代理人(經(jīng)紀人)來解決。這就是代理思想在現(xiàn)實中的一個例子拔创。

??代理模式的關(guān)鍵點是:代理對象與目標對象利诺。代理對象是對目標對象的擴展,并會調(diào)用目標對象剩燥。
??代理模式包含如下角色:
??ISubject:抽象主題角色慢逾,是一個接口。該接口是對象和它的代理共用的接口灭红。
??RealSubject:真實主題角色侣滩,是實現(xiàn)抽象主題接口的類。
??Proxy:代理角色变擒,內(nèi)部含有對真實對象RealSubject的引用君珠,從而可以操作真實對象。代理對象提供與真實對象相同的接口娇斑,以便在任何時刻都能代替真實對象策添。同時,代理對象可以在執(zhí)行真實對象操作時毫缆,附加其他的操作唯竹,相當于對真實對象進行封裝。
??代理模式的應(yīng)用:
??遠程代理:也就是為一個對象在不同的地址空間提供局部代表苦丁。這樣可以隱藏一個對象存在于不同地址空間的事實摩窃。
??虛擬代理:是根據(jù)需要創(chuàng)建開銷很大的對象。通過它來存放實例化需要很長時間的真實對象芬骄。
??安全代理:用來控制真實對象訪問時的權(quán)限。
??智能代理:是指當調(diào)用真實的對象時鹦聪,代理處理一些另外的事情账阻。
??一般將代理分類的話,可分為靜態(tài)代理和動態(tài)代理兩種泽本。

靜態(tài)代理

??靜態(tài)代理比較簡單淘太,是由程序員編寫的代理類,并在程序運行前就編譯好的规丽,而不是由程序動態(tài)產(chǎn)生代理類蒲牧,這就是所謂的靜態(tài)。
??考慮這樣的場景赌莺,管理員在網(wǎng)站上執(zhí)行操作冰抢,在生成操作結(jié)果的同時需要記錄操作日志,這是很常見的艘狭。此時就可以使用代理模式挎扰,代理模式可以通過聚合和繼承兩種方式實現(xiàn):

/**
 * @Description: 抽象主題接口
 * @author: zxt
 * @time: 2018年7月7日 下午2:29:46
 */
public interface Manager {
    public void doSomething();
}

/**
 * @Description: 真實的主題類
 * @author: zxt
 * @time: 2018年7月7日 下午2:31:21
 */
public class Admin implements Manager {
    @Override
    public void doSomething() {
        System.out.println("這是真實的主題類:Admin doSomething!!!");
    }
}

/**
 * @Description: 以聚合的方式實現(xiàn)代理主題
 * @author: zxt
 * @time: 2018年7月7日 下午2:37:08
 */
public class AdminPoly implements Manager {
    // 真實主題類的引用
    private Admin admin;
    
    public AdminPoly(Admin admin) {
        this.admin = admin;
    }
    
    @Override
    public void doSomething() {
        System.out.println("聚合方式實現(xiàn)代理:Admin操作開始4涠!");
        admin.doSomething();
        System.out.println("聚合方式實現(xiàn)代理:Admin操作結(jié)束W窬搿尽超!");
    }
}

/**
 * @Description: 繼承方式實現(xiàn)代理
 * @author: zxt
 * @time: 2018年7月7日 下午2:40:39
 */
public class AdminProxy extends Admin {
    @Override
    public void doSomething() {
        System.out.println("繼承方式實現(xiàn)代理:Admin操作開始!梧躺!");
        super.doSomething();
        System.out.println("繼承方式實現(xiàn)代理:Admin操作結(jié)束K扑!");
    }
}

public static void main(String[] args) {
    // 1掠哥、聚合方式的測試
    Admin admin = new Admin();
    Manager manager = new AdminPoly(admin);
    manager.doSomething();
    
    System.out.println("============================");
    // 2巩踏、繼承方式的測試
    AdminProxy proxy = new AdminProxy();
    proxy.doSomething();
}

??聚合實現(xiàn)方式中代理類聚合了被代理類,且代理類及被代理類都實現(xiàn)了同一個接口龙致,可實現(xiàn)靈活多變蛀缝。繼承式的實現(xiàn)方式則不夠靈活。
??比如目代,在管理員操作的同時需要進行權(quán)限的處理屈梁,操作內(nèi)容的日志記錄,操作后數(shù)據(jù)的變化三個功能榛了。三個功能的排列組合有6種在讶,也就是說使用繼承要編寫6個繼承了Admin的代理類,而使用聚合霜大,僅需要針對權(quán)限的處理构哺、日志記錄和數(shù)據(jù)變化三個功能編寫代理類,在業(yè)務(wù)邏輯中根據(jù)具體需求改變代碼順序即可战坤。
??缺點:
??1)曙强、代理類和委托類實現(xiàn)了相同的接口,代理類通過委托類實現(xiàn)了相同的方法途茫。這樣就出現(xiàn)了大量的代碼重復(fù)碟嘴。如果接口增加一個方法,除了所有實現(xiàn)類需要實現(xiàn)這個方法外囊卜,所有代理類也需要實現(xiàn)此方法娜扇。增加了代碼維護的復(fù)雜度。
??2)栅组、代理對象只服務(wù)于一種類型的對象雀瓢,如果要服務(wù)多類型的對象。勢必要為每一種對象都進行代理玉掸,靜態(tài)代理在程序規(guī)模稍大時就無法勝任了刃麸。

動態(tài)代理

??實現(xiàn)動態(tài)代理的關(guān)鍵技術(shù)是反射。
??一般來說排截,對代理模式而言嫌蚤,一個主題類與一個代理類一一對應(yīng)辐益,這也是靜態(tài)代理模式的特點。
??但是脱吱,也存在這樣的情況智政,有n各主題類,但是代理類中的“前處理箱蝠、后處理”都是一樣的续捂,僅調(diào)用主題不同。也就是說宦搬,多個主題類對應(yīng)一個代理類牙瓢,共享“前處理,后處理”功能间校,動態(tài)調(diào)用所需主題矾克,大大減小了程序規(guī)模,這就是動態(tài)代理模式的特點憔足。動態(tài)代理主要有兩種:JDK自帶的動態(tài)代理和CGLIB動態(tài)代理胁附。
??首先是另一個靜態(tài)代理的實例:

1、一個可移動接口

public interface Moveable {
    
    public void move();
}

2滓彰、一個實現(xiàn)了該接口的Car類

public class Car implements Moveable {

    @Override
    public void move() {
        try {
            Thread.sleep(new Random().nextInt(1000));
            System.out.println("汽車行駛中----");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

3控妻、現(xiàn)在需要有一個代理類來記錄Car的運行時間:

public class CarTimeProxy implements Moveable {
    private Moveable m;
    
    public CarTimeProxy(Moveable m) {
        super();
        this.m = m;
    }

    @Override
    public void move() {
        long startTime = System.currentTimeMillis();
        System.out.println("汽車行駛前----");
        m.move();
        long endTime = System.currentTimeMillis();
        System.out.println("汽車行駛結(jié)束----行駛時間為:" + (endTime - startTime) + "毫秒!");
    }
}

4揭绑、另一個代理類記錄Car的日志:

public class CarLogProxy implements Moveable {
    private Moveable m;
    
    public CarLogProxy(Moveable m) {
        super();
        this.m = m;
    }

    @Override
    public void move() {
        System.out.println("日志開始");
        m.move();
        System.out.println("日志結(jié)束");
    }
}

5弓候、客戶端的調(diào)用:

public class CarTest {

    public static void main(String[] args) {
        Car car = new Car();
        // 先寫日志,再計時
        CarTimeProxy ctp = new CarTimeProxy(car);
        CarLogProxy clp = new CarLogProxy(ctp);
        clp.move();
        
        System.out.println();
        // 先計時他匪,再寫日志
        CarLogProxy clp1 = new CarLogProxy(car);
        CarTimeProxy ctp1 = new CarTimeProxy(clp1);
        ctp1.move();
    }
}



JDK的動態(tài)代理

在java的動態(tài)代理機制中菇存,有兩個重要的類或接口,一個是InvocationHandler(Interface)邦蜜、另一個則是 Proxy(Class)撰筷,這一個類和接口是實現(xiàn)我們動態(tài)代理所必須用到的。




??JDK動態(tài)代理的實現(xiàn)
??1畦徘、創(chuàng)建一個實現(xiàn)接口InvocationHandler的類,它必須實現(xiàn)invoke方法抬闯。
??使用JDK動態(tài)代理類時井辆,需要實現(xiàn)InvocationHandler接口,所有動態(tài)代理類的方法調(diào)用溶握,都會交由InvocationHandler接口實現(xiàn)類里的invoke()方法去處理杯缺。這是動態(tài)代理的關(guān)鍵所在。
??2睡榆、創(chuàng)建被代理的類以及接口萍肆。
??3袍榆、調(diào)用Proxy的靜態(tài)方法,創(chuàng)建代理類塘揣。
??newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h);
??4包雀、通過代理調(diào)用方法。
??使用JDK動態(tài)代理的方式實現(xiàn)上面Car的時間代理:

1亲铡、首先是InvocationHandler接口的實現(xiàn)類:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class TimeHandler implements InvocationHandler {
    // 被傳遞過來的要被代理的對象
    private Object object;
    
    public TimeHandler(Object object) {
        super();
        this.object = object;
    }

    /**
     * proxy:被代理的對象
     * method:被代理的方法
     * args:被代理方法的參數(shù)
     * 
     * 函數(shù)返回:method的返回
     * 
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long startTime = System.currentTimeMillis();
        System.out.println("汽車行駛前----");
        method.invoke(object, args);
        long endTime = System.currentTimeMillis();
        System.out.println("汽車行駛結(jié)束----行駛時間為:" + (endTime - startTime) + "毫秒才写!");
        return null;
    }
}

2、創(chuàng)建動態(tài)代理類:

/**
 * @Description: JDK動態(tài)代理的測試類
 * @author: zxt
 * @time: 2019年3月1日 下午7:59:29
 */
public class TimeHandlerTest {

    public static void main(String[] args) {
        // 需要被代理的對象
        Car car = new Car();
        InvocationHandler h = new TimeHandler(car);
        
        Class<?> clazz = car.getClass();
        
        /**
         * 參數(shù)一:類加載器
         * 參數(shù)二:被代理類實現(xiàn)的接口
         * 參數(shù)三:InvocationHandler實例
         * 
         * 函數(shù)返回:返回由InvocationHandler接口接收的被代理類的一個動態(tài)代理類對象
         */
        Moveable m = (Moveable) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), h);
        m.move();
    }
}


cglib動態(tài)代理

??JDK動態(tài)代理可以在運行時動態(tài)生成字節(jié)碼奖蔓,主要使用到了一個接口InvocationHandler與Proxy.newProxyInstance靜態(tài)方法赞草。使用內(nèi)置的Proxy實現(xiàn)動態(tài)代理有一個問題:被代理的類必須要實現(xiàn)某接口,未實現(xiàn)接口則沒辦法完成動態(tài)代理吆鹤。
??如果項目中有些類沒有實現(xiàn)接口厨疙,則不應(yīng)該為了實現(xiàn)動態(tài)代理而刻意去抽象出一些沒有實際意義的接口,通過cglib可以解決該問題疑务。
??CGLIB(Code Generation Library)是一個開源項目沾凄,是一個強大的,高性能暑始,高質(zhì)量的Code生成類庫搭独,它可以在運行期擴展Java類與實現(xiàn)Java接口,通俗地說cglib可以在運行時動態(tài)生成字節(jié)碼廊镜。
??使用cglib完成動態(tài)代理牙肝,大概的原理是:cglib繼承被代理的類,重寫方法嗤朴,織入通知配椭,動態(tài)生成字節(jié)碼并運行。對指定目標類產(chǎn)生一個子類雹姊,通過方法攔截技術(shù)攔截所有父類的方法調(diào)用股缸,因為是繼承實現(xiàn)所以final類是沒有辦法動態(tài)代理的。

CGLIB動態(tài)代理實例:

import java.util.Random;

// 不實現(xiàn)接口的被代理類
public class Train {
    
    public void move() {
        try {
            Thread.sleep(new Random().nextInt(1000));
            System.out.println("火車行駛中----");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();
    
    // 得到代理類的方法
    public Object getProxy(Class<?> clazz) {
        // 設(shè)置創(chuàng)建子類的類  (即我們需要為哪個類產(chǎn)生代理類)
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        
        return enhancer.create();
    }
    
    /**
     * 攔截所有目標類方法的調(diào)用
     * 
     * object:目標類的實例
     * method:目標類的目標方法的反射實例
     * args:目標方法的參數(shù)
     * proxy:代理類的實例
     */
    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        long startTime = System.currentTimeMillis();
        System.out.println("火車行駛前----");
        
        // 代理類調(diào)用父類的方法 (由于Cglib動態(tài)代理的實現(xiàn)是通過繼承被代理類吱雏,因此代理類這里需要調(diào)用父類的方法)
        proxy.invokeSuper(object, args);
        
        long endTime = System.currentTimeMillis();
        System.out.println("火車行駛結(jié)束----行駛時間為:" + (endTime - startTime) + "毫秒敦姻!");
        return null;
    }
}
public class CglibProxyTest {
    
    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy();
        Train train = (Train) cglibProxy.getProxy(Train.class);
        train.move();
    }
}


JDK動態(tài)代理的模擬實現(xiàn)

模擬JDK動態(tài)代理的實現(xiàn),根據(jù)Java源代碼動態(tài)生成代理類歧杏。

package com.zxt.jdkproxy;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

import org.apache.commons.io.FileUtils;

import com.zxt.staticproxy.Car;

/**
 * 
 * @Description: 模擬JDK動態(tài)代理的實現(xiàn)
 * 動態(tài)代理的實現(xiàn)思路:
 * 實現(xiàn)功能:通過自定義的Proxy的newProxyInstance方法返回代理對象
 * 1镰惦、聲明一段源碼(動態(tài)產(chǎn)生代理)
 * 2、編譯源碼(JDK Compiler API)犬绒,產(chǎn)生新的類(代理類)
 * 3旺入、將這個類load到內(nèi)存當中,產(chǎn)生一個新的對象(代理對象)
 * 4、return 代理對象
 *
 * @author: zxt
 *
 * @time: 2019年4月18日 下午3:44:58
 *
 */
public class MyProxy {
    
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static Object newProxyInstance(Class<?> inteface) throws Exception {
        // 1茵瘾、聲明一段源碼(動態(tài)產(chǎn)生代理)
        String rt = "\r\n";
        String methodStr = "";
        for(Method m : inteface.getMethods()) {
            methodStr += "  @Override" + rt
                       + "  public void " + m.getName() + "() {" + rt
                       + "      System.out.println(\"日志開始\");" + rt
                       + "      m." + m.getName() + "();" + rt
                       + "      System.out.println(\"日志結(jié)束\");" + rt
                       + "  }";
        }
        String code = 
            "package com.zxt.jdkproxy;" + rt + "\n"
            + "import com.zxt.staticproxy.Moveable;" + rt + "\n"
            + "public class $MyProxy0 implements " + inteface.getSimpleName() + " {" + rt + "\n"
            + " private " + inteface.getSimpleName() + " m;" + rt + "\n"
            + " public $MyProxy0(" + inteface.getSimpleName() + " m) {" + rt
            + "     super();" + rt
            + "     this.m = m;" + rt
            + " }" + rt + "\n"
            + methodStr + rt + "\n"
            + "}";
        
        
        // 由源代碼生成java類文件
        String filename = System.getProperty("user.dir") + "/bin/com/zxt/jdkproxy/$MyProxy0.java";
        File file = new File(filename);
        // 使用commons-io里面的簡便的工具類來寫文件
        FileUtils.writeStringToFile(file, code, "UTF-8");
        
        
        // 2礼华、編譯源碼(JDK Compiler API),產(chǎn)生新的類(代理類)
        // 拿到編譯器
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        // 文件管理者
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
        // 獲取文件
        Iterable units = fileManager.getJavaFileObjects(filename);
        // 獲取編譯任務(wù)
        CompilationTask task = compiler.getTask(null, fileManager, null, null, null, units);
        // 編譯
        task.call();
        fileManager.close();
        
        // 3拗秘、加載到內(nèi)存
        ClassLoader cl = ClassLoader.getSystemClassLoader();
        Class c = cl.loadClass("com.zxt.jdkproxy.$MyProxy0");
        
        // 4圣絮、返回代理類
        Constructor ctr = c.getConstructor(inteface);
        return ctr.newInstance(new Car());
    }
    
    
    public static void main(String[] args) {

    }
}
public class MyProxyTest {
    public static void main(String[] args) throws Exception {
        Moveable m = (Moveable) MyProxy.newProxyInstance(Moveable.class);
        m.move();
    }
}

??可以發(fā)現(xiàn)上述實現(xiàn)中的源代碼是寫死在類中的,因此無法對任意類進行動態(tài)代理聘殖,所以仿照InvocationHandler接口晨雳,定義自己的InvocationHandler接口從而實現(xiàn)對不同的類進行動態(tài)代理。

import java.lang.reflect.Method;

public interface MyInvocationHandler {

    public void invoke(Object o, Method m);
}

實現(xiàn)該接口的類

import java.lang.reflect.Method;

public class MyLogHandler implements MyInvocationHandler {
    // 需要被代理的對象
    private Object target;

    public MyLogHandler(Object target) {
        super();
        this.target = target;
    }

    @Override
    public void invoke(Object o, Method m) {
        try {
            System.out.println("日志開始");
            m.invoke(target);
            System.out.println("日志結(jié)束");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

對動態(tài)代理MyProxy類進行改進

/**
 * 
 * @Description: 模擬JDK動態(tài)代理的實現(xiàn)
 * 動態(tài)代理的實現(xiàn)思路:
 * 實現(xiàn)功能:通過自定義的Proxy的newProxyInstance方法返回代理對象
 * 1奸腺、聲明一段源碼(動態(tài)產(chǎn)生代理)
 * 2餐禁、編譯源碼(JDK Compiler API),產(chǎn)生新的類(代理類)
 * 3突照、將這個類load到內(nèi)存當中帮非,產(chǎn)生一個新的對象(代理對象)
 * 4、return 代理對象
 *
 * @author: zxt
 *
 * @time: 2019年4月18日 下午3:44:58
 *
 */
public class MyProxy {
    
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static Object newProxyInstance(Class<?> inteface, MyInvocationHandler h) throws Exception {
        // 1讹蘑、聲明一段源碼(動態(tài)產(chǎn)生代理)
        String rt = "\r\n";
        String methodStr = "";
        for(Method m : inteface.getMethods()) {
            methodStr += "  @Override" + rt
                       + "  public void " + m.getName() + "() {" + rt
                       + "      try { " + rt
                       + "          Method md = " + inteface.getSimpleName() + ".class.getMethod(\""
                                              + m.getName() + "\");" + rt
                       + "          h.invoke(this, md);" + rt
                       + "      } catch (Exception e) { " + rt
                       + "          e.printStackTrace();" + rt
                       + "      }" + rt
                       + "  }";
        }
        String code = 
            "package com.zxt.jdkproxy;" + rt + "\n"
            + "import java.lang.reflect.Method;" + rt
            + "import com.zxt.staticproxy.Moveable;" + rt + "\n"
            + "public class $MyProxy0 implements " + inteface.getSimpleName() + " {" + rt + "\n"
            + " private MyInvocationHandler h;" + rt + "\n"
            + " public $MyProxy0( MyInvocationHandler h ) {" + rt
            + "     this.h = h;" + rt
            + " }" + rt + "\n"
            + methodStr + rt + "\n"
            + "}";
        
        
        // 由源代碼生成java類文件
        String filename = System.getProperty("user.dir") + "/bin/com/zxt/jdkproxy/$MyProxy0.java";
        File file = new File(filename);
        // 使用commons-io里面的簡便的工具類來寫文件
        FileUtils.writeStringToFile(file, code, "UTF-8");
        
        
        // 2末盔、編譯源碼(JDK Compiler API),產(chǎn)生新的類(代理類)
        // 拿到編譯器
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        // 文件管理者
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
        // 獲取文件
        Iterable units = fileManager.getJavaFileObjects(filename);
        // 獲取編譯任務(wù)
        CompilationTask task = compiler.getTask(null, fileManager, null, null, null, units);
        // 編譯
        task.call();
        fileManager.close();
        
        // 3座慰、加載到內(nèi)存
        ClassLoader cl = ClassLoader.getSystemClassLoader();
        Class c = cl.loadClass("com.zxt.jdkproxy.$MyProxy0");
        
        // 4陨舱、返回代理類
        Constructor ctr = c.getConstructor(MyInvocationHandler.class);
        return ctr.newInstance(h);
    }
}

測試類:

public class MyProxyTest {
    
    public static void main(String[] args) throws Exception {
        // 需要被代理的對象
        Car car = new Car();
        MyInvocationHandler h = new MyLogHandler(car);

        Moveable m = (Moveable) MyProxy.newProxyInstance(Moveable.class, h);
        m.move();
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市版仔,隨后出現(xiàn)的幾起案子游盲,更是在濱河造成了極大的恐慌,老刑警劉巖蛮粮,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件益缎,死亡現(xiàn)場離奇詭異,居然都是意外死亡然想,警方通過查閱死者的電腦和手機莺奔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來变泄,“玉大人令哟,你說我怎么就攤上這事》劣迹” “怎么了励饵?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長滑燃。 經(jīng)常有香客問我,道長颓鲜,這世上最難降的妖魔是什么表窘? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任典予,我火速辦了婚禮,結(jié)果婚禮上乐严,老公的妹妹穿的比我還像新娘瘤袖。我一直安慰自己琳袄,他們只是感情好董虱,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著艰毒,像睡著了一般既琴。 火紅的嫁衣襯著肌膚如雪占婉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天甫恩,我揣著相機與錄音逆济,去河邊找鬼。 笑死磺箕,一個胖子當著我的面吹牛奖慌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播松靡,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼简僧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了雕欺?” 一聲冷哼從身側(cè)響起岛马,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎阅茶,沒想到半個月后蛛枚,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡脸哀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年蹦浦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撞蜂。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡盲镶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蝌诡,到底是詐尸還是另有隱情溉贿,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布浦旱,位于F島的核電站宇色,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜宣蠕,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一例隆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧抢蚀,春花似錦镀层、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至屋休,卻和暖如春坞古,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背博投。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工绸贡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人毅哗。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓听怕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親虑绵。 傳聞我的和親對象是個殘疾皇子尿瞭,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

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