《Spring實(shí)戰(zhàn)》-第四章:面向切面編程(AOP)

慢慢來(lái)比較快舀凛,虛心學(xué)技術(shù)

前言:DI (依賴(lài)注入)有助于應(yīng)用對(duì)象之間的解耦句携,而 AOP(面向切面編程) 可以實(shí)現(xiàn)橫切關(guān)注點(diǎn)與它們所影響的對(duì)象之間的解耦

一、什么是面向切面編程

Ⅰ呈昔、橫切關(guān)注點(diǎn):在軟件開(kāi)發(fā)中达椰,散布于應(yīng)用中多處的功能被稱(chēng)為橫切關(guān)注點(diǎn)( cross-cutting concern )【比如說(shuō)日志,安全和事務(wù)管理等】屎篱。通常來(lái)講服赎,這些橫切關(guān)注點(diǎn)從概念上是與應(yīng)用的業(yè)務(wù)邏輯相分離的(但是往往會(huì)直接嵌入到應(yīng)用的業(yè)務(wù)邏輯之中)。把這些橫切關(guān)注點(diǎn)與業(yè)務(wù)邏輯相分離正是面向切面編程( AOP )所要解決的問(wèn)題交播。

Ⅱ重虑、切面:橫切關(guān)注點(diǎn)可以被模塊化為特殊的類(lèi),這些類(lèi)被稱(chēng)為切面( aspect )秦士。

Ⅲ缺厉、AOP術(shù)語(yǔ)

通知( Advice ):切面的工作被稱(chēng)為通知。通知描述切面的工作隧土,同時(shí)決定切面何時(shí)工作【定義了切面工作做什么芽死,什么時(shí)候做】

  • 前置通知( Before ):在目標(biāo)方法被調(diào)用之前調(diào)用通知功能;
  • 后置通知( After ):在目標(biāo)方法完成之后調(diào)用通知次洼,此時(shí)不會(huì)關(guān)心方法的輸出是什么关贵;
  • 返回通知( After-returning ):在目標(biāo)方法成功執(zhí)行之后調(diào)用通知;
  • 異常通知( After-throwing ):在目標(biāo)方法拋出異常后調(diào)用通知卖毁;
  • 環(huán)繞通知( Around ):通知包裹了被通知的方法揖曾,在被通知的方法調(diào)用之前和調(diào)用之后執(zhí)行自定義的行為

連接點(diǎn)( Join point ):觸發(fā)切面工作的點(diǎn),比如方法執(zhí)行亥啦,異常拋出等行為

切點(diǎn)( Poincut ):決定切面工作的地方炭剪,比如某個(gè)方法等【定義了切面工作在哪里做】

切面( Aspect ):通知和切點(diǎn)的結(jié)合【面】

引入( Introduction ):允許我們向現(xiàn)有的類(lèi)添加新方法或?qū)傩?/p>

織入( Weaving ):把切面應(yīng)用到目標(biāo)對(duì)象并創(chuàng)建新的代理對(duì)象的過(guò)程【切面在指定的連接點(diǎn)被織入到目標(biāo)對(duì)象中】

通知包含了需要用于多個(gè)應(yīng)用對(duì)象的橫切行為;連接點(diǎn)是程序執(zhí)行過(guò)程中能夠應(yīng)用通知的所有點(diǎn)翔脱;切點(diǎn)定義了通知被應(yīng)用的具體位置(在哪些連接點(diǎn))奴拦。其中關(guān)鍵的概念是切點(diǎn)定義了哪些連接點(diǎn)會(huì)得到通知

Ⅳ、Spring對(duì)AOP的支持【 Spring AOP 構(gòu)建在動(dòng)態(tài)代理基礎(chǔ)之上届吁,因此错妖, Spring 對(duì) AOP 的支持局限于方法攔截【毋澹】

  1. 基于代理的經(jīng)典 Spring AOP 暂氯;
  2. 純 POJO 切面;
  3. @AspectJ 注解驅(qū)動(dòng)的切面亮蛔;
  4. 注入式 AspectJ 切面(適用于 Spring 各版本)痴施。

二、面向切面編程實(shí)現(xiàn)

1、定義切點(diǎn):

Spring支持通過(guò)AspectJ的切點(diǎn)表達(dá)式語(yǔ)言來(lái)定義 Spring 切面辣吃,同時(shí)增加通過(guò)bean的id指定bean的寫(xiě)法动遭。

如:execution( com.my.spring.bean..(..))* 指定com.my.spring.bean包下所有類(lèi)的所有方法作為切點(diǎn)

其結(jié)構(gòu)解析如下:


AspectJ切點(diǎn)表達(dá)式的指示器不只有execution:

  • arg() :限制連接點(diǎn)匹配參數(shù)為指定類(lèi)型的執(zhí)行方法
  • execution() :用于匹配是連接點(diǎn)的執(zhí)行方法
  • this() :限制連接點(diǎn)匹配 AOP 代理的 bean 引用為指定類(lèi)型的類(lèi)
  • target :限制連接點(diǎn)匹配目標(biāo)對(duì)象為指定類(lèi)型的類(lèi)
  • within() :限制連接點(diǎn)匹配指定的類(lèi)型

各指示器之間可以通過(guò)&&(與),||(或)神得,!(非)連接符進(jìn)行連接實(shí)現(xiàn)多條件查詢(xún)定義節(jié)點(diǎn)

如:execution(* com.my.spring.bean.* . *(..))&&arg(java.lang.Integer)

2.示例Demo

Spring AOP的實(shí)現(xiàn)依賴(lài)于spring-aop包和aspectjweaver包厘惦,需在pom文件引入:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>${org.springframework.version}</version>
</dependency>

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.13</version>
</dependency>

通過(guò)實(shí)例demo引入概念:

①定義一個(gè)基礎(chǔ)接口類(lèi)BaseInterface和實(shí)現(xiàn)類(lèi)BaseBean

public interface BaseInterface {

    /**
     * 新增歌曲
     *
     * @param author 作者
     * @param songTitle 歌曲名
     *
     * @return java.lang.Integer 返回當(dāng)前歌曲總數(shù)
     *
     * @author xxx 2019/3/4
     * @version 1.0
     **/
    Integer addSong(String author,String songTitle);

    /**
     * 刪除歌曲
     *
     * @param author 作者
     * @param songTitle 歌曲名
     *
     * @return java.lang.Integer 返回當(dāng)前歌曲總數(shù)
     *
     * @author xxx 2019/3/4
     * @version 1.0
     **/
    Integer delSong(String author,String songTitle);
}

@Component
public class BaseBean implements  BaseInterface{

    private String author;
    private String songTitle;
    private Integer count=0;

    @Override
    public Integer addSong(String author,String songTitle){
        this.author = author;
        this.songTitle = songTitle;
        System.out.println("新增了一首歌:"+author+"-"+songTitle);
        count++;
        return count;
    }

    @Override
    public Integer delSong(String author,String songTitle){
        this.author = author;
        this.songTitle = songTitle;
        System.out.println("刪除了一首歌:"+author+"-"+songTitle);
        count--;
        return count;
    }
}

②創(chuàng)建一個(gè)切面類(lèi)

@Aspect
@Component
public class BaseBeanAspect {

    private Logger logger = LoggerFactory.getLogger(BaseBeanAspect.class);

     /**
      * 方法執(zhí)行前的通知
      */
    @Before("execution(* com.my.spring.bean.*.*(..))")
    public void beforeInvoke(){
        logger.debug("方法執(zhí)行前");
    }

    /**
     * 方法執(zhí)行后的通知
     */
    @After("execution(* com.my.spring.bean.*.*(..))")
    public void afterInvoke(){
        logger.debug("方法執(zhí)行后");
    }

    /**
     * 方法執(zhí)行返回后的通知
     */
    @AfterReturning("execution(* com.my.spring.bean.*.*(..))")
    public void afterReturning(){
        logger.debug("==================方法執(zhí)行完成");
    }

    /**
     * 方法拋出異常的通知
     */
    @AfterThrowing("execution(* com.my.spring.bean.*.*(..))")
    public void afterThrowing(){

        logger.debug("==================方法執(zhí)行報(bào)錯(cuò)");
    }
}

③創(chuàng)建自動(dòng)化裝配的配置類(lèi)

@Configuration
@EnableAspectJAutoProxy//開(kāi)啟自動(dòng)代理開(kāi)關(guān),啟用切面
@ComponentScan(basePackages = {"com.my.spring"})
public class ComponentConfig {
}

④測(cè)試

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {ComponentConfig.class})
public class AppTest {

    @Autowired
    private BaseInterface baseInterface;

    @Test
    public void testBean(){
        baseInterface.addSong("myBean","mySong");
        baseInterface.delSong("myBean","mySong");
    }
}

⑤測(cè)試結(jié)果

2019-03-04 14:32:55.019 DEBUG com.my.spring.aspect.BaseBeanAspect - 方法執(zhí)行前
新增了一首歌:myBean-mySong
2019-03-04 14:32:55.019 DEBUG com.my.spring.aspect.BaseBeanAspect - 方法執(zhí)行后
2019-03-04 14:32:55.019 DEBUG com.my.spring.aspect.BaseBeanAspect - ==================方法執(zhí)行完成
2019-03-04 14:32:55.019 DEBUG com.my.spring.aspect.BaseBeanAspect - 方法執(zhí)行前
刪除了一首歌:myBean-mySong
2019-03-04 14:32:55.019 DEBUG com.my.spring.aspect.BaseBeanAspect - 方法執(zhí)行后
2019-03-04 14:32:55.019 DEBUG com.my.spring.aspect.BaseBeanAspect - ==================方法執(zhí)行完成

3循头、注解分析

前代碼是使用注解實(shí)現(xiàn)SpringAOP的簡(jiǎn)單示例,我們了解以下其中用到的注解和實(shí)現(xiàn):

Ⅰ炎疆、定義切面:@Aspect------------標(biāo)識(shí)當(dāng)前類(lèi)是一個(gè)切面類(lèi)(僅僅只是標(biāo)識(shí)卡骂,我們可以看到該注解源碼并沒(méi)有使用@Component注解,所以使用該注解的bean依舊只是一個(gè)普通的POJO形入,使用時(shí)依舊需要顯式或自動(dòng)裝配)

Ⅱ全跨、定義切點(diǎn):@PointCut

我們看到上述代碼中在多個(gè)地方使用切點(diǎn)使用的是重復(fù)性的表達(dá)式,其實(shí)通過(guò)@PointCut注解定義切點(diǎn)亿遂,同時(shí)通過(guò)指定空方法名引入切點(diǎn)到各個(gè)通知即可

@Pointcut("execution(* com.my.spring.bean.*.*(..))")
public void pointCut(){//被用于標(biāo)識(shí)的空方法
}

@Before("pointCut()")//以切點(diǎn)方法名引入
public void beforeInvoke(){
    logger.debug("方法執(zhí)行前");
}

Ⅱ浓若、定義通知:

@Beafore(切點(diǎn))-----------------切點(diǎn)方法執(zhí)行前的通知

@After(切點(diǎn))-------------------------切點(diǎn)方法執(zhí)行后的通知

@AfterReturning(切點(diǎn))-----------切點(diǎn)方法執(zhí)行返回后的通知

@AfterThrowing(切點(diǎn))------------切點(diǎn)方法拋異常后的通知

Ⅲ、開(kāi)啟自動(dòng)代理:@EnableAspectJAutoProxy--------在配置類(lèi)中使用蛇数,如果不啟用的話挪钓,編寫(xiě)的切面將不生效

Ⅳ、定義環(huán)繞通知:@Around("pointCut()")

環(huán)繞通知是從方法執(zhí)行前一直包裹直到方法執(zhí)行完成后的一個(gè)通知耳舅,用的比較多碌上,其中被定義的方法需要引入?yún)?shù)ProceedingJoinPoint,ProceedingJoinPoint對(duì)象封裝了當(dāng)前運(yùn)行對(duì)象的具體信息,簡(jiǎn)單實(shí)現(xiàn)如下:

 @Around("pointCut()")
public void aroundInvoke(ProceedingJoinPoint jp){
    try {
        logger.debug("=====================環(huán)繞執(zhí)行方法開(kāi)始");
        Signature signature = jp.getSignature();
        String methodName = signature.getName();
        MethodSignature methodSignature = (MethodSignature) signature;
        logger.debug("方法名:{}",methodName);
        List<Object> args = Arrays.asList(jp.getArgs());
       logger.debug("參數(shù)列表:{}",args);
       Class<?> returnType = methodSignature.getMethod().getReturnType();
       logger.debug("方法返回類(lèi)型:{}",returnType);
       Object proceed = jp.proceed();
       logger.debug("======================環(huán)繞執(zhí)行方法結(jié)束浦徊,方法執(zhí)行結(jié)果:{}",proceed);
     } catch (Throwable throwable) {
         throwable.printStackTrace();
     }
}

其中馏予,ProceedingJoinPoint對(duì)象源碼分析如下:

JoinPoint 

     java.lang.Object[] getArgs()//獲取連接點(diǎn)方法運(yùn)行時(shí)的入?yún)⒘斜恚?

     Signature getSignature() //獲取連接點(diǎn)的方法簽名對(duì)象; 

     java.lang.Object getTarget() //獲取連接點(diǎn)所在的目標(biāo)對(duì)象盔性; 

     java.lang.Object getThis() //獲取代理對(duì)象本身霞丧; 

ProceedingJoinPoint繼承JoinPoint子接口,它新增了兩個(gè)用于執(zhí)行連接點(diǎn)方法的方法

      java.lang.Object proceed() throws java.lang.Throwable:通過(guò)反射執(zhí)行目標(biāo)對(duì)象的連接點(diǎn)處的方法冕香;

      java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通過(guò)反射執(zhí)行目標(biāo)對(duì)象連接點(diǎn)處的方法蛹尝,不過(guò)使用新的入?yún)⑻鎿Q原來(lái)的入?yún)ⅰ?

4、XML實(shí)現(xiàn)切面編程

我們知道使用注解實(shí)現(xiàn)切面編程是很方便直接的悉尾,但是有時(shí)候我們并不一定擁有通知類(lèi)的源碼箩言,也就無(wú)法給對(duì)應(yīng)的方法添加注解,這時(shí)候就需要使用XML配置實(shí)現(xiàn)了焕襟。XML配置實(shí)現(xiàn)與注解實(shí)現(xiàn)十分類(lèi)似陨收,我們可以看一下基本的實(shí)現(xiàn)節(jié)點(diǎn):

定義切面:<aop:aspect ref="切面類(lèi)在xml文件中對(duì)應(yīng)bean的id">

定義切點(diǎn):<aop:pointcut id="切點(diǎn)id" expression="切點(diǎn)表達(dá)式"/>

定義通知:

<aop:beafore method="通知方法名" pointcut-ref="切點(diǎn)id"/>-------------定義方法執(zhí)行前的通知

<aop:after method="通知方法名" pointcut-ref="切點(diǎn)id"/>-------------定義方法執(zhí)行后的通知

<aop:afterReturning method="通知方法名" pointcut-ref="切點(diǎn)id"/>-------------定義方法執(zhí)行返回后的通知

<aop:afterThrowing method="通知方法名" pointcut-ref="切點(diǎn)id"/>-------------定義方法執(zhí)行拋出異常后的通知

<aop:around method="通知方法名" pointcut-ref="切點(diǎn)id"/>-------------定義方法環(huán)繞通知

④開(kāi)啟自動(dòng)代理:<aop:aspectj-autoproxy/>

⑤表示aop配置:<aop:config></aop:config>

除了開(kāi)啟自動(dòng)代理,aop的所有節(jié)點(diǎn)都需要包含在<aop:config></aop:config>節(jié)點(diǎn)中,如下demo演示:

applicaiton.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--開(kāi)啟自動(dòng)代理-->
    <aop:aspectj-autoproxy/>

    <!--裝配基本類(lèi)-->
    <bean class="com.my.spring.bean.BaseBean" id="baseBean" name="baseBean"/>

    <!--裝配切面類(lèi)-->
    <bean class="com.my.spring.aspect.BaseBeanAspect" id="baseBeanAspect"/>

    <!--aop配置-->
    <aop:config>
        <!--配置切面-->
        <aop:aspect ref="baseBeanAspect">
            <!--定義切點(diǎn)-->
            <aop:pointcut id="pointCut" expression="execution(* com.my.spring.bean.*.*(..))"/>
            <!--定義前置通知-->
            <aop:before method="beforeInvoke" pointcut-ref="pointCut"/>
            <!--定義后置通知-->
            <aop:after method="afterInvoke" pointcut-ref="pointCut"/>
            <!--定義方法執(zhí)行返回后通知-->
            <aop:after-returning method="afterReturning" pointcut-ref="pointCut"/>
            <!--定義方法異常后通知-->
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointCut"/>
            <!--定義方法環(huán)繞通知通知-->
            <aop:around method="aroundInvoke" pointcut-ref="pointCut"/>
        </aop:aspect>
    </aop:config>
</beans>

將BaseBean和BaseBeanAspect類(lèi)中的注解去除务漩,編寫(xiě)測(cè)試類(lèi):

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:application.xml"})//將配置文件作為裝配環(huán)境
public class AppXMLTest {

    @Autowired
    private BaseInterface baseInterface;

    @Test
    public void testBean(){
        baseInterface.addSong("Mr D","The World!!");
        baseInterface.delSong("Mr D","The World!!");
    }
}

測(cè)試結(jié)果:

2019-03-04 22:07:37.901 DEBUG com.my.spring.aspect.BaseBeanAspect - 方法執(zhí)行前
2019-03-04 22:07:37.903 DEBUG com.my.spring.aspect.BaseBeanAspect - =====================環(huán)繞執(zhí)行方法開(kāi)始
2019-03-04 22:07:37.907 DEBUG com.my.spring.aspect.BaseBeanAspect - 方法名:addSong
2019-03-04 22:07:37.910 DEBUG com.my.spring.aspect.BaseBeanAspect - 參數(shù)列表:[Mr D, The World!!]
2019-03-04 22:07:37.910 DEBUG com.my.spring.aspect.BaseBeanAspect - 方法返回類(lèi)型:class java.lang.Integer
2019-03-04 22:07:37.910 DEBUG com.my.spring.aspect.BaseBeanAspect - 方法執(zhí)行前
新增了一首歌:Mr D-The World!!
2019-03-04 22:07:37.911 DEBUG com.my.spring.aspect.BaseBeanAspect - ==================方法執(zhí)行完成
2019-03-04 22:07:37.911 DEBUG com.my.spring.aspect.BaseBeanAspect - 方法執(zhí)行后
2019-03-04 22:07:37.911 DEBUG com.my.spring.aspect.BaseBeanAspect - ======================環(huán)繞執(zhí)行方法結(jié)束拄衰,方法執(zhí)行結(jié)果:1
2019-03-04 22:07:37.912 DEBUG com.my.spring.aspect.BaseBeanAspect - ==================方法執(zhí)行完成
2019-03-04 22:07:37.912 DEBUG com.my.spring.aspect.BaseBeanAspect - 方法執(zhí)行后
2019-03-04 22:07:37.915 DEBUG com.my.spring.aspect.BaseBeanAspect - 方法執(zhí)行前
2019-03-04 22:07:37.915 DEBUG com.my.spring.aspect.BaseBeanAspect - =====================環(huán)繞執(zhí)行方法開(kāi)始
2019-03-04 22:07:37.916 DEBUG com.my.spring.aspect.BaseBeanAspect - 方法名:delSong
2019-03-04 22:07:37.917 DEBUG com.my.spring.aspect.BaseBeanAspect - 參數(shù)列表:[Mr D, The World!!]
2019-03-04 22:07:37.917 DEBUG com.my.spring.aspect.BaseBeanAspect - 方法返回類(lèi)型:class java.lang.Integer
2019-03-04 22:07:37.917 DEBUG com.my.spring.aspect.BaseBeanAspect - 方法執(zhí)行前
刪除了一首歌:Mr D-The World!!
2019-03-04 22:07:37.917 DEBUG com.my.spring.aspect.BaseBeanAspect - ==================方法執(zhí)行完成
2019-03-04 22:07:37.917 DEBUG com.my.spring.aspect.BaseBeanAspect - 方法執(zhí)行后
2019-03-04 22:07:37.917 DEBUG com.my.spring.aspect.BaseBeanAspect - ======================環(huán)繞執(zhí)行方法結(jié)束,方法執(zhí)行結(jié)果:0
2019-03-04 22:07:37.917 DEBUG com.my.spring.aspect.BaseBeanAspect - ==================方法執(zhí)行完成
2019-03-04 22:07:37.917 DEBUG com.my.spring.aspect.BaseBeanAspect - 方法執(zhí)行后
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末饵骨,一起剝皮案震驚了整個(gè)濱河市翘悉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌居触,老刑警劉巖妖混,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異轮洋,居然都是意外死亡制市,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)弊予,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)祥楣,“玉大人,你說(shuō)我怎么就攤上這事汉柒∥笸剩” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵碾褂,是天一觀的道長(zhǎng)兽间。 經(jīng)常有香客問(wèn)我,道長(zhǎng)正塌,這世上最難降的妖魔是什么渡八? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮传货,結(jié)果婚禮上屎鳍,老公的妹妹穿的比我還像新娘。我一直安慰自己问裕,他們只是感情好逮壁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著粮宛,像睡著了一般窥淆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上巍杈,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天忧饭,我揣著相機(jī)與錄音,去河邊找鬼筷畦。 笑死词裤,一個(gè)胖子當(dāng)著我的面吹牛刺洒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播吼砂,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼逆航,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了渔肩?” 一聲冷哼從身側(cè)響起因俐,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎周偎,沒(méi)想到半個(gè)月后抹剩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蓉坎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年澳眷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片袍嬉。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡境蔼,死狀恐怖灶平,靈堂內(nèi)的尸體忽然破棺而出伺通,到底是詐尸還是另有隱情,我是刑警寧澤逢享,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布罐监,位于F島的核電站,受9級(jí)特大地震影響瞒爬,放射性物質(zhì)發(fā)生泄漏弓柱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一侧但、第九天 我趴在偏房一處隱蔽的房頂上張望矢空。 院中可真熱鬧,春花似錦禀横、人聲如沸屁药。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)酿箭。三九已至,卻和暖如春趾娃,著一層夾襖步出監(jiān)牢的瞬間缭嫡,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工抬闷, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留妇蛀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像讥耗,于是被迫代替她去往敵國(guó)和親有勾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

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