JDK動(dòng)態(tài)代理和 CGLIB 代理

代碼示例

接口

publicinterfaceIUserDao{voidsave();}

實(shí)現(xiàn)類

publicclassUserDaoimplementsIUserDao{@Overridepublicvoidsave(){? ? ? ? System.out.println("=====已經(jīng)保存數(shù)據(jù)=======");? ? }}

代理類

publicclassDynamicJdkProxy{/**

? ? * 維護(hù)一個(gè)目標(biāo)對(duì)象

? ? */privateObject target;publicDynamicJdkProxy(Object target){this.target = target;? ? }/**

? ? * 給目標(biāo)對(duì)象生成代理對(duì)象

? ? *

? ? * @return

? ? */publicObjectgetProxyInstance(){returnProxy.newProxyInstance(? ? ? ? ? ? ? ? target.getClass().getClassLoader(),? ? ? ? ? ? ? ? target.getClass().getInterfaces(),newInvocationHandler() {? ? ? ? ? ? ? ? ? ? @OverridepublicObjectinvoke(Object proxy, Method method, Object[] args) throws Throwable{? ? ? ? ? ? ? ? ? ? ? ? System.out.println("開始事務(wù)2");//執(zhí)行目標(biāo)對(duì)象方法Object returnValue = method.invoke(target, args);? ? ? ? ? ? ? ? ? ? ? ? System.out.println("提交事務(wù)2");returnreturnValue;? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? );? ? }}

運(yùn)行

//生成相應(yīng)的class文件System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");// 目標(biāo)對(duì)象IUserDao target =newUserDao();// 【原始的類型 class com.example.learning.proxy.UserDao】System.out.println(target.getClass());// 給目標(biāo)對(duì)象,創(chuàng)建代理對(duì)象IUserDao proxy = (IUserDao)newDynamicJdkProxy(target).getProxyInstance();// class $Proxy0? 內(nèi)存中動(dòng)態(tài)生成的代理對(duì)象System.out.println(proxy.getClass());// 執(zhí)行方法? 【代理對(duì)象】proxy.save();

執(zhí)行結(jié)果

class com.example.learning.proxy.UserDaoclass com.sun.proxy.$Proxy0開始事務(wù)2=====已經(jīng)保存數(shù)據(jù)=======提交事務(wù)2Process finished withexitcode0

源碼分析:

publicstaticObjectnewProxyInstance(ClassLoader loader,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Class<?>[] interfaces,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? InvocationHandler h)throwsIllegalArgumentException{//克隆接口finalClass[] intfs = interfaces.clone();//重點(diǎn):生成 $Proxy0.class 文件并通過 ClassLoader 加載進(jìn)來Class cl = getProxyClass0(loader, intfs);//創(chuàng)建代理類的構(gòu)造器finalConstructor cons = cl.getConstructor(constructorParams);//生成代理類的實(shí)例returncons.newInstance(newObject[]{h});? ? }

再來看 getProxyClass0 的具體實(shí)現(xiàn):ProxyClassFactory工廠類:

Map, Boolean> interfaceSet =newIdentityHashMap<>(interfaces.length);for(Class intf : interfaces) {? ? ? ? ? ? ? ? ? ? interfaceClass = Class.forName(intf.getName(),false, loader);? ? ? ? ? ? }StringproxyPkg =null;// package to define proxy class in//如果需要代理的類中有非public函數(shù),直接取代理類的路徑for(Class intf : interfaces) {intflags = intf.getModifiers();if(!Modifier.isPublic(flags)) {? ? ? ? ? ? ? ? ? ? accessFlags = Modifier.FINAL;Stringname = intf.getName();intn = name.lastIndexOf('.');Stringpkg = ((n ==-1) ?"": name.substring(0, n +1));if(proxyPkg ==null) {? ? ? ? ? ? ? ? ? ? ? ? proxyPkg = pkg;? ? ? ? ? ? ? ? ? ? }elseif(!pkg.equals(proxyPkg)) {thrownewIllegalArgumentException("non-public interfaces from different packages");? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? ? ? }//如果全是 Public 函數(shù),取com.sun.proxy 作為包名if(proxyPkg ==null) {// if no non-public proxy interfaces, use com.sun.proxy packageproxyPkg = ReflectUtil.PROXY_PACKAGE +".";? ? ? ? ? ? }/*

? ? ? ? ? ? *? 生成代理類名稱 com.sun.proxy.$ProxyXXX

? ? ? ? ? ? */longnum= nextUniqueNumber.getAndIncrement();StringproxyName = proxyPkg + proxyClassNamePrefix +num;/*

? ? ? ? ? ? * 產(chǎn)生代理類class

? ? ? ? ? ? */byte[] proxyClassFile = ProxyGenerator.generateProxyClass(? ? ? ? ? ? ? ? proxyName, interfaces, accessFlags);//加載classreturndefineClass0(loader, proxyName,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? proxyClassFile,0, proxyClassFile.length);? ? ? ? }

生成class

publicstaticbyte[] generateProxyClass(finalString var0, Class[] var1,intvar2) {? ? ? ? ProxyGenerator var3 =newProxyGenerator(var0, var1, var2);finalbyte[] var4 = var3.generateClassFile();if(saveGeneratedFiles) {? ? ? ? ...? ? ? ? }

是否生成class標(biāo)識(shí)

privatestaticfinalbooleansaveGeneratedFiles = (Boolean)AccessController.doPrivileged(newGetBooleanAction("sun.misc.ProxyGenerator.saveGeneratedFiles"));

生成后的代理類:

publicfinalclass$Proxy0extendsProxyimplementsIUserDao{privatestaticMethod m1;privatestaticMethod m3;privatestaticMethod m2;privatestaticMethod m0;public$Proxy0(InvocationHandler var1)throws{super(var1);? ? }publicfinalbooleanequals(Object var1)throws{//省略}publicfinalvoidsave()throws{try{super.h.invoke(this, m3, (Object[])null);? ? ? ? }catch(RuntimeException | Error var2) {throwvar2;? ? ? ? }catch(Throwable var3) {thrownewUndeclaredThrowableException(var3);? ? ? ? }? ? }publicfinalStringtoString()throws{//省略}publicfinalinthashCode()throws{//省略}static{try{? ? ? ? ? ? m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));? ? ? ? ? ? m3 = Class.forName("com.example.learning.proxy.IUserDao").getMethod("save");? ? ? ? ? ? m2 = Class.forName("java.lang.Object").getMethod("toString");? ? ? ? ? ? m0 = Class.forName("java.lang.Object").getMethod("hashCode");? ? ? ? }catch(NoSuchMethodException var2) {thrownewNoSuchMethodError(var2.getMessage());? ? ? ? }catch(ClassNotFoundException var3) {thrownewNoClassDefFoundError(var3.getMessage());? ? ? ? }? ? }}

核心代碼

調(diào)用的就是InvocationHandler#invoke方法super.h.invoke(this, m3, (Object[])null);? h為Proxy類的/**

? ? * the invocation handler for this proxy instance.

? ? * @serial

? ? */protectedInvocationHandler h;

JDK 代理通過在運(yùn)行期期間創(chuàng)建一個(gè)接口的實(shí)現(xiàn)類來完成對(duì)目標(biāo)對(duì)象的代理.

CGLIB 代理

CGLIB代理:實(shí)現(xiàn)原理類似于JDK動(dòng)態(tài)代理诈乒,只是它在運(yùn)行期間生成的代理對(duì)象是針對(duì)目標(biāo)類擴(kuò)展的子類。CGLIB是高效的代碼生成包,底層依靠ASM(開源的Java字節(jié)碼編輯類庫)操作字節(jié)碼實(shí)現(xiàn)。

代理類

publicclassUserDaoCG{publicvoidsave(){? ? ? ? System.out.println("=====已經(jīng)保存數(shù)據(jù)=======");? ? }}

CG 代理

publicclassCgLibProxyimplementsMethodInterceptor{/**

? ? * 維護(hù)目標(biāo)對(duì)象

? ? */privateObject target;publicCgLibProxy(Object target){this.target = target;? ? }/**? ? * 給目標(biāo)對(duì)象創(chuàng)建一個(gè)代理對(duì)象? ? *? ? *@return*/publicObjectgetProxyInstance(){//1.工具類Enhancer en =newEnhancer();//2.設(shè)置父類en.setSuperclass(target.getClass());//3.設(shè)置回調(diào)函數(shù)en.setCallback(this);//4.創(chuàng)建子類(代理對(duì)象)returnen.create();? ? }@OverridepublicObjectintercept(Object obj, Method method, Object[] args, MethodProxy proxy)throwsThrowable{? ? ? ? System.out.println("開始CGLib事務(wù)...");//執(zhí)行目標(biāo)對(duì)象的方法Object returnValue = method.invoke(target, args);? ? ? ? System.out.println("提交CGLib事務(wù)...");returnreturnValue;? ? }}

運(yùn)行代理

System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"/Users/xxx/IdeaProjects/learning/cg");//目標(biāo)對(duì)象UserDao target =newUserDao();//代理對(duì)象UserDao proxy = (UserDao)newCgLibProxy(target).getProxyInstance();//執(zhí)行代理對(duì)象的方法proxy.save();

運(yùn)行結(jié)果

CGLIB debugging enabled, writing to'/Users/xxx/IdeaProjects/learning/cg'開始CGLib事務(wù)...=====已經(jīng)保存數(shù)據(jù)=======提交CGLib事務(wù)...

生成的代理類

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)//package com.example.learning.proxy;import java.lang.reflect.Method;import org.springframework.cglib.core.ReflectUtils;import org.springframework.cglib.core.Signature;import org.springframework.cglib.proxy.Callback;import org.springframework.cglib.proxy.Factory;import org.springframework.cglib.proxy.MethodInterceptor;import org.springframework.cglib.proxy.MethodProxy;public class UserDao$$EnhancerByCGLIB$$6efc5e8bextends UserDao implements Factory {? ? private boolean CGLIB$BOUND;? ? public static Object CGLIB$FACTORY_DATA;? ? private static final ThreadLocal CGLIB$THREAD_CALLBACKS;? ? private static final Callback[] CGLIB$STATIC_CALLBACKS;? ? private MethodInterceptor CGLIB$CALLBACK_0;? ? private static Object CGLIB$CALLBACK_FILTER;? ? private static final Method CGLIB$save$0$Method;? ? private static final MethodProxy CGLIB$save$0$Proxy;? ? private static final Object[] CGLIB$emptyArgs;? ? private static final Method CGLIB$equals$1$Method;? ? private static final MethodProxy CGLIB$equals$1$Proxy;? ? private static final Method CGLIB$toString$2$Method;? ? private static final MethodProxy CGLIB$toString$2$Proxy;? ? private static final Method CGLIB$hashCode$3$Method;? ? private static final MethodProxy CGLIB$hashCode$3$Proxy;? ? private static final Method CGLIB$clone$4$Method;? ? private static final MethodProxy CGLIB$clone$4$Proxy;? ? static void CGLIB$STATICHOOK1() {? ? ? ? CGLIB$THREAD_CALLBACKS= new ThreadLocal();? ? ? ? CGLIB$emptyArgs= new Object[0];? ? ? ? Class var0 = Class.forName("com.example.learning.proxy.UserDao$$EnhancerByCGLIB$$6efc5e8b");? ? ? ? Class var1;? ? ? ? Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals","(Ljava/lang/Object;)Z","toString","()Ljava/lang/String;","hashCode","()I","clone","()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());? ? ? ? CGLIB$equals$1$Method= var10000[0];? ? ? ? CGLIB$equals$1$Proxy= MethodProxy.create(var1, var0,"(Ljava/lang/Object;)Z","equals","CGLIB$equals$1");? ? ? ? CGLIB$toString$2$Method= var10000[1];? ? ? ? CGLIB$toString$2$Proxy= MethodProxy.create(var1, var0,"()Ljava/lang/String;","toString","CGLIB$toString$2");? ? ? ? CGLIB$hashCode$3$Method= var10000[2];? ? ? ? CGLIB$hashCode$3$Proxy= MethodProxy.create(var1, var0,"()I","hashCode","CGLIB$hashCode$3");? ? ? ? CGLIB$clone$4$Method= var10000[3];? ? ? ? CGLIB$clone$4$Proxy= MethodProxy.create(var1, var0,"()Ljava/lang/Object;","clone","CGLIB$clone$4");? ? ? ? CGLIB$save$0$Method= ReflectUtils.findMethods(new String[]{"save","()V"}, (var1 = Class.forName("com.example.learning.proxy.UserDao")).getDeclaredMethods())[0];? ? ? ? CGLIB$save$0$Proxy= MethodProxy.create(var1, var0,"()V","save","CGLIB$save$0");? ? }? ? final void CGLIB$save$0() {? ? ? ? super.save();? ? }? ? public final voidsave() {? ? ? ? MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;if(var10000 == null) {? ? ? ? ? ? CGLIB$BIND_CALLBACKS(this);? ? ? ? ? ? var10000 = this.CGLIB$CALLBACK_0;? ? ? ? }if(var10000 != null) {? ? ? ? ? ? var10000.intercept(this, CGLIB$save$0$Method, CGLIB$emptyArgs, CGLIB$save$0$Proxy);? ? ? ? }else{? ? ? ? ? ? super.save();? ? ? ? }? ? }? ? final boolean CGLIB$equals$1(Object var1) {returnsuper.equals(var1);? ? }? ? public final boolean equals(Object var1) {? ? ? ? MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;if(var10000 == null) {? ? ? ? ? ? CGLIB$BIND_CALLBACKS(this);? ? ? ? ? ? var10000 = this.CGLIB$CALLBACK_0;? ? ? ? }if(var10000 != null) {? ? ? ? ? ? Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);returnvar2 == null ?false: (Boolean)var2;? ? ? ? }else{returnsuper.equals(var1);? ? ? ? }? ? }? ? final String CGLIB$toString$2() {returnsuper.toString();? ? }? ? public final StringtoString() {? ? ? ? MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;if(var10000 == null) {? ? ? ? ? ? CGLIB$BIND_CALLBACKS(this);? ? ? ? ? ? var10000 = this.CGLIB$CALLBACK_0;? ? ? ? }returnvar10000 != null ? (String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy) : super.toString();? ? }? ? final int CGLIB$hashCode$3() {returnsuper.hashCode();? ? }? ? public final inthashCode() {? ? ? ? MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;if(var10000 == null) {? ? ? ? ? ? CGLIB$BIND_CALLBACKS(this);? ? ? ? ? ? var10000 = this.CGLIB$CALLBACK_0;? ? ? ? }if(var10000 != null) {? ? ? ? ? ? Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);returnvar1 == null ? 0 : ((Number)var1).intValue();? ? ? ? }else{returnsuper.hashCode();? ? ? ? }? ? }? ? final Object CGLIB$clone$4() throws CloneNotSupportedException {returnsuper.clone();? ? }? ? protected final Objectclone() throws CloneNotSupportedException {? ? ? ? MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;if(var10000 == null) {? ? ? ? ? ? CGLIB$BIND_CALLBACKS(this);? ? ? ? ? ? var10000 = this.CGLIB$CALLBACK_0;? ? ? ? }returnvar10000 != null ? var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy) : super.clone();? ? }? ? public static MethodProxy CGLIB$findMethodProxy(Signature var0) {? ? ? ? String var10000 = var0.toString();? ? ? ? switch(var10000.hashCode()) {case-508378822:if(var10000.equals("clone()Ljava/lang/Object;")) {returnCGLIB$clone$4$Proxy;? ? ? ? ? ? }break;case1826985398:if(var10000.equals("equals(Ljava/lang/Object;)Z")) {returnCGLIB$equals$1$Proxy;? ? ? ? ? ? }break;case1872760024:if(var10000.equals("save()V")) {returnCGLIB$save$0$Proxy;? ? ? ? ? ? }break;case1913648695:if(var10000.equals("toString()Ljava/lang/String;")) {returnCGLIB$toString$2$Proxy;? ? ? ? ? ? }break;case1984935277:if(var10000.equals("hashCode()I")) {returnCGLIB$hashCode$3$Proxy;? ? ? ? ? ? }? ? ? ? }returnnull;? ? }? ? public UserDao$$EnhancerByCGLIB$$6efc5e8b() {? ? ? ? CGLIB$BIND_CALLBACKS(this);? ? }? ? public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {? ? ? ? CGLIB$THREAD_CALLBACKS.set(var0);? ? }? ? public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {? ? ? ? CGLIB$STATIC_CALLBACKS= var0;? ? }? ? private static final void CGLIB$BIND_CALLBACKS(Object var0) {? ? ? ? UserDao$$EnhancerByCGLIB$$6efc5e8bvar1 = (UserDao$$EnhancerByCGLIB$$6efc5e8b)var0;if(!var1.CGLIB$BOUND) {? ? ? ? ? ? var1.CGLIB$BOUND=true;? ? ? ? ? ? Object var10000 = CGLIB$THREAD_CALLBACKS.get();if(var10000 == null) {? ? ? ? ? ? ? ? var10000 = CGLIB$STATIC_CALLBACKS;if(var10000 == null) {return;? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? ? ? var1.CGLIB$CALLBACK_0= (MethodInterceptor)((Callback[])var10000)[0];? ? ? ? }? ? }? ? public Object newInstance(Callback[] var1) {? ? ? ? CGLIB$SET_THREAD_CALLBACKS(var1);? ? ? ? UserDao$$EnhancerByCGLIB$$6efc5e8bvar10000 = new UserDao$$EnhancerByCGLIB$$6efc5e8b();? ? ? ? CGLIB$SET_THREAD_CALLBACKS((Callback[])null);returnvar10000;? ? }? ? public Object newInstance(Callback var1) {? ? ? ? CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});? ? ? ? UserDao$$EnhancerByCGLIB$$6efc5e8bvar10000 = new UserDao$$EnhancerByCGLIB$$6efc5e8b();? ? ? ? CGLIB$SET_THREAD_CALLBACKS((Callback[])null);returnvar10000;? ? }? ? public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {? ? ? ? CGLIB$SET_THREAD_CALLBACKS(var3);? ? ? ? UserDao$$EnhancerByCGLIB$$6efc5e8bvar10000 = new UserDao$$EnhancerByCGLIB$$6efc5e8b;? ? ? ? switch(var1.length) {case0:? ? ? ? ? ? var10000.();? ? ? ? ? ? CGLIB$SET_THREAD_CALLBACKS((Callback[])null);returnvar10000;? ? ? ? default:? ? ? ? ? ? throw new IllegalArgumentException("Constructor not found");? ? ? ? }? ? }? ? public Callback getCallback(int var1) {? ? ? ? CGLIB$BIND_CALLBACKS(this);? ? ? ? MethodInterceptor var10000;? ? ? ? switch(var1) {case0:? ? ? ? ? ? var10000 = this.CGLIB$CALLBACK_0;break;? ? ? ? default:? ? ? ? ? ? var10000 = null;? ? ? ? }returnvar10000;? ? }? ? public void setCallback(int var1, Callback var2) {? ? ? ? switch(var1) {case0:? ? ? ? ? ? this.CGLIB$CALLBACK_0= (MethodInterceptor)var2;? ? ? ? default:? ? ? ? }? ? }? ? public Callback[]getCallbacks() {? ? ? ? CGLIB$BIND_CALLBACKS(this);returnnew Callback[]{this.CGLIB$CALLBACK_0};? ? }? ? public void setCallbacks(Callback[] var1) {? ? ? ? this.CGLIB$CALLBACK_0= (MethodInterceptor)var1[0];? ? }? ? static {? ? ? ? CGLIB$STATICHOOK1();? ? }}

關(guān)鍵代碼

public finalvoidsave() {//代理類MethodInterceptor var10000 =this.CGLIB$CALLBACK_0;if(var10000 == null) {CGLIB$BIND_CALLBACKS(this);? ? ? ? ? ? var10000 =this.CGLIB$CALLBACK_0;? ? ? ? }//如果代理類不為空,直接調(diào)用代理方法if(var10000 != null) {? ? ? ? ? ? var10000.intercept(this,CGLIB$save$0$Method,CGLIB$emptyArgs,CGLIB$save$0$Proxy);? ? ? ? }else{super.save();? ? ? ? }? ? }

深圳網(wǎng)站建設(shè)www.sz886.com

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末眨层,一起剝皮案震驚了整個(gè)濱河市蜒秤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌莲趣,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饱溢,死亡現(xiàn)場(chǎng)離奇詭異喧伞,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)绩郎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門潘鲫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肋杖,你說我怎么就攤上這事溉仑。” “怎么了状植?”我有些...
    開封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵浊竟,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我津畸,道長(zhǎng)振定,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任肉拓,我火速辦了婚禮后频,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘帝簇。我一直安慰自己徘郭,他們只是感情好靠益,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著残揉,像睡著了一般胧后。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上抱环,一...
    開封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天壳快,我揣著相機(jī)與錄音,去河邊找鬼镇草。 笑死眶痰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的梯啤。 我是一名探鬼主播竖伯,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼因宇!你這毒婦竟也來了七婴?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤察滑,失蹤者是張志新(化名)和其女友劉穎打厘,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贺辰,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡户盯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了饲化。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片莽鸭。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖滓侍,靈堂內(nèi)的尸體忽然破棺而出蒋川,到底是詐尸還是另有隱情牲芋,我是刑警寧澤撩笆,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站缸浦,受9級(jí)特大地震影響夕冲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜裂逐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一歹鱼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧卜高,春花似錦弥姻、人聲如沸南片。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽疼进。三九已至,卻和暖如春秧廉,著一層夾襖步出監(jiān)牢的瞬間伞广,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來泰國打工疼电, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嚼锄,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓蔽豺,卻偏偏與公主長(zhǎng)得像区丑,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子修陡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350