Spring Aop:一、四种advice

本文参考实验楼教程:https://www.shiyanlou.com/courses/578/learning/?id=1940

  Spring Aop即 Aspect-Oriented Programming,面向切面编程。是用于处理系统中各个模块(不同方法)之间的交叉关注的问题。
  简单地说,就是一个拦截器,拦截一些处理过程。
  例如:当一个method被执行,Spring AOP能够劫持正在运行的method,在method执行前后加入一些额外的功能。(日志记录、性能统计、权限控制等)

实验环境:
  JDK1.8
  idea 开发环境

一、Spring AOP 支持4种类型的通知(advice)

  • Before advice --- method 执行前通知
  • After returning advice --- method 执行完毕或者返回一个结果后通知
  • After throwing advice --- method 抛出异常后通知
  • Around advice --- 环绕通知,结合了以上三种

下面来学习如何使用这四种通知。
以下是整个实验项目结构:

project.png

1、准备环境,创建一个maven工程SpringAop

 1)、添加maven依赖,对应的pom.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.shiyanlou.spring</groupId>
  <artifactId>SpringAopTest</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>SpringAopTest</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <spring.version>5.1.1.RELEASE</spring.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.2</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjtools</artifactId>
      <version>1.9.2</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.9.2</version>
    </dependency>
    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.2.9</version>
    </dependency>
  </dependencies>

</project>

 2)、创建类 CustomerService.java 如下:

package com.shiyanlou.spring.aop.advice;

import org.springframework.stereotype.Service;

/**
 * Created by Administrator on 2019/10/30.
 */

public class CustomerService {
    private String name;
    private String url;

    public CustomerService() {
    }

    public CustomerService(String name, String url) {
        this.name = name;
        this.url = url;
    }

    public String getName() {
        return name;
    }

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

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void printName(){
        System.out.println("Customer name: " + name);
    }

    public void printURL(){
        System.out.println("Customer URL: " + url);
    }

    public void printThrowException(){
        throw new IllegalArgumentException();
    }
}

 3)、在src/main/resources/下新建 Xml 配置文件 SpringAopAdvice.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"
       xsi:schemaLocation="
                            http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="customerService" class="com.shiyanlou.spring.aop.advice.CustomerService">
        <property name="name" value="weihouye"/>
        <property name="url" value="www.weihouyeaiyangzhan.com"/>
    </bean>

</beans>

 4)、在com.shiyanlou.spring包下的App.java中编写如下:

package com.shiyanlou.spring;

import com.shiyanlou.spring.aop.advice.CustomerService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App
{
    private static ApplicationContext context;

    public static void main( String[] args ) {

        context = new ClassPathXmlApplicationContext("SpringAopAdvice.xml");

        CustomerService cust = (CustomerService) context.getBean("customerService");

        System.out.println("*************************");
        cust.printName();
        System.out.println("*************************");
        cust.printURL();
        System.out.println("*************************");
        try {
            cust.printThrowException();
        } catch (IllegalArgumentException e){
        }

    }
}

 5)、运行App.java文件,结果如下:


*************************
Customer name: weihouye
*************************
Customer URL: www.weihouyeaiyangzhan.com
*************************

2、Before advice

 1)、定义org.springframework.aop.MethodBeforeAdvice的实现类WeiBeforeMethod,重写before方法,该方法将在被代理的类的方法之前运行。代码如下:

package com.shiyanlou.spring.aop.advice;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

/**
 * Created by Administrator on 2019/10/30.
 */
public class WeiBeforeMethod implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("WeiBeforeMethod: Before method hi wei!!!");
    }
}

 2)、在SpringAopAdvice.xml配置文件中加入新的bean配置weiBeforeMethod,然后创建一个代理bean(Proxy),命名为customerServiceProxy
  代理bean中target定义了被代理(被劫持)的类,拦截器interceptorNames则定义了想要用哪个类(advice)劫持target,拦截器可以有多个,所以写在<list>中。配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
                            http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="customerService" class="com.shiyanlou.spring.aop.advice.CustomerService">
        <property name="name" value="weihouye"/>
        <property name="url" value="www.weihouyeaiyangzhan.com"/>
    </bean>

    <bean id="weiBeforeMethod" class="com.shiyanlou.spring.aop.advice.WeiBeforeMethod"/>

    <bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="customerService"/>
        <property name="interceptorNames">
            <list>
                <value>weiBeforeMethod</value>
            </list>
        </property>
    </bean>
</beans>

用 Spring proxy 之前,必须添加 CGLIB 类库,在之前的 pom.xml 文件中,已经添加到了其中,以下是 pom.xml 依赖:

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

 3)、App.java如下

package com.shiyanlou.spring;

import com.shiyanlou.spring.aop.advice.CustomerService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Hello world!
 *
 */
public class App
{
    private static ApplicationContext context;

    public static void main( String[] args ) {

        context = new ClassPathXmlApplicationContext("SpringAopAdvice.xml");

        CustomerService cust = (CustomerService) context.getBean("customerServiceProxy");

        System.out.println("*************************");
        cust.printName();
        System.out.println("*************************");
        cust.printURL();
        System.out.println("*************************");
        try {
            cust.printThrowException();
        } catch (IllegalArgumentException e){
        }
    }
}

ps:注意 App.java中获取的是代理bean,即customerServiceProxy,由代理bean去执行原来的功能。

 4)、运行结果如下:


*************************
WeiBeforeMethod: Before method hi wei!!!
Customer name: weihouye
*************************
WeiBeforeMethod: Before method hi wei!!!
Customer URL: www.weihouyeaiyangzhan.com
*************************
WeiBeforeMethod: Before method hi wei!!!

  可以看到,被代理类CustomerServiceWeiBeforeMethod劫持,被代理类中的方法被执行前,均先执行WeiBeforeMethod中的before方法。

3、After Returning Advice

 1)、创建一个org.springframework.aop.AfterReturningAdvice接口的实现类WeiAfterMethod.java,重写afterReturning方法,用于劫持被代理类;被代理类中的方法执行完毕或者返回结果后,将执行WeiAfterMethod中的afterReturning方法,若中途异常退出,则不会执行该方法。
WeiAfterMethod.java代码如下:

package com.shiyanlou.spring.aop.advice;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

/**
 * Created by Administrator on 2019/10/30.
 */
public class WeiAfterMethod implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("WeiAfterMethod: After Method hi wei!!");
    }
}

 2)、修改bean配置xml文件 SpringAopAdvice.xml,加入weiAfterMethod配置,如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
                            http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="customerService" class="com.shiyanlou.spring.aop.advice.CustomerService">
        <property name="name" value="weihouye"/>
        <property name="url" value="www.weihouyeaiyangzhan.com"/>
    </bean>

    <bean id="weiBeforeMethod" class="com.shiyanlou.spring.aop.advice.WeiBeforeMethod"/>
    <bean id="weiAfterMethod" class="com.shiyanlou.spring.aop.advice.WeiAfterMethod"/>

    <bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="customerService"/>
        <property name="interceptorNames">
            <list>
                <!--<value>weiBeforeMethod</value>-->
                <value>weiAfterMethod</value>
            </list>
        </property>
    </bean>
</beans>

 3)、同样在App.java中获取并运行代理bean,结果如下:


*************************
Customer name: weihouye
WeiAfterMethod: After Method hi wei!!
*************************
Customer URL: www.weihouyeaiyangzhan.com
WeiAfterMethod: After Method hi wei!!
*************************

&emps;可以看到,在CustomerService.java中的每个方法执行完毕后,均会执行WeiAfterMethod.javaafterReturning方法,抛出异常除外。

4、Afetr Throwing Advice

 1)、创建一个实现org.springframework.aop.ThrowsAdvice接口的实现类WeiThrowExceptionMethod.java,劫持IllegalArgumentException异常,当被劫持的类抛出该异常时,将会执行afterThrowing方法;代码如下:

package com.shiyanlou.spring.aop.advice;

import org.springframework.aop.ThrowsAdvice;

/**
 * Created by Administrator on 2019/10/30.
 */
public class WeiThrowExceptionMethod implements ThrowsAdvice {

    public void afterThrowing(Exception ex){
        System.out.println("WeiThrowException : Throw exception hi wei!!");
    }
}

 2)、修改bean配置xml文件 SpringAopAdvice.xml,加入weiThrowExceptionMethod配置,如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
                            http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="customerService" class="com.shiyanlou.spring.aop.advice.CustomerService">
        <property name="name" value="weihouye"/>
        <property name="url" value="www.weihouyeaiyangzhan.com"/>
    </bean>

    <bean id="weiBeforeMethod" class="com.shiyanlou.spring.aop.advice.WeiBeforeMethod"/>
    <bean id="weiAfterMethod" class="com.shiyanlou.spring.aop.advice.WeiAfterMethod"/>
    <bean id="weiThrowExceptionMethod" class="com.shiyanlou.spring.aop.advice.WeiThrowExceptionMethod"/>
    <bean id="weiAroundMethod" class="com.shiyanlou.spring.aop.advice.WeiAroundMethod"/>

    <bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="customerService"/>
        <property name="interceptorNames">
            <list>
                <!--<value>weiBeforeMethod</value>-->
                <!--<value>weiAfterMethod</value>-->
                <value>weiThrowExceptionMethod</value>
            </list>
        </property>
    </bean>
</beans>

 3)、同样在App.java中获取并运行代理bean,结果如下:


*************************
Customer name: weihouye
*************************
Customer URL: www.weihouyeaiyangzhan.com
*************************
WeiThrowException : Throw exception hi wei!!

 可以看到当执行到CustomerService.javaprintThrowException方法时,我们抛出了IllegalArgumentException异常,异常抛出后执行了拦截器WeiThrowExceptionMethod.javaafterThrowing方法。


5、Around advice

 1)、结合上面3种形式的advice,创建一个org.aopalliance.intercept.MethodInterceptor接口的实现类WeiAroundMethod.java,重写public Object invoke(MethodInvocation invocation) throws Throwable方法;
 必须通过方法调用对象invocation.proceed()来调用原来的被代理的方法,当然也可以不调用;代码如下,注意注释中包含十分重要的信息。

package com.shiyanlou.spring.aop.advice;


import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import java.util.Arrays;

/**
 * Created by Administrator on 2019/10/30.
 */
public class WeiAroundMethod implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {

        //Method调用的处理
        System.out.println("Method Name: " + invocation.getMethod().getName());
        System.out.println("Method Arguments: " + Arrays.toString(invocation.getArguments()));
        //相当于MethodBeforeAdvice
        System.out.println("WeiBeforeMethod: Before method hi wei!!!");

        try {
            //调用原方法,即调用CustomerService中的方法
            Object result = invocation.proceed();

            //相当于AfterReturningAdvice
            System.out.println("WeiAfterMethod: After Method hi wei!!");

            return result;
        } catch (IllegalArgumentException e) {
            //相当于ThrowsAdvice
            System.out.println("WeiThrowException : Throw exception hi wei!!");

            throw e; //将异常抛出
        }
    }
}

 2)、修改bean配置xml文件 SpringAopAdvice.xml,加入weiAroundMethod配置,如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
                            http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="customerService" class="com.shiyanlou.spring.aop.advice.CustomerService">
        <property name="name" value="weihouye"/>
        <property name="url" value="www.weihouyeaiyangzhan.com"/>
    </bean>

    <bean id="weiBeforeMethod" class="com.shiyanlou.spring.aop.advice.WeiBeforeMethod"/>
    <bean id="weiAfterMethod" class="com.shiyanlou.spring.aop.advice.WeiAfterMethod"/>
    <bean id="weiThrowExceptionMethod" class="com.shiyanlou.spring.aop.advice.WeiThrowExceptionMethod"/>
    <bean id="weiAroundMethod" class="com.shiyanlou.spring.aop.advice.WeiAroundMethod"/>

    <bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="customerService"/>
        <property name="interceptorNames">
            <list>
                <!--<value>weiBeforeMethod</value>-->
                <!--<value>weiAfterMethod</value>-->
                <!--<value>weiThrowExceptionMethod</value>-->
                <value>weiAroundMethod</value>
            </list>
        </property>
    </bean>
</beans>

 3)、运行App.java结果如下:


*************************
Method Name: printName
Method Arguments: []
WeiBeforeMethod: Before method hi wei!!!
Customer name: weihouye
WeiAfterMethod: After Method hi wei!!
*************************
Method Name: printURL
Method Arguments: []
WeiBeforeMethod: Before method hi wei!!!
Customer URL: www.weihouyeaiyangzhan.com
WeiAfterMethod: After Method hi wei!!
*************************
Method Name: printThrowException
Method Arguments: []
WeiBeforeMethod: Before method hi wei!!!
WeiThrowException : Throw exception hi wei!!

 可以看出Around advice 结合了前面三种advice。


6、改进

 在上边的结果中,CustomerService.java的全部方法均被拦截,下面展示如何使用Pointcuts只拦截printName()
 在Spring AOP中,有3个常用的名词,Advices、Pointcuts、Advisor,解释如下:

  • Advices:表示一个方法执行前或者执行后的动作;
  • Pointcuts:表示根据一个方法的名字或者正则表达式去拦截一个方法;
  • Advisor:Advices和Pointcuts组成的独立的单元,且可以传给proxy factory对象。

 我们可以用名字匹配法或者正则表达式去匹配要拦截的方法。



 1)、Pointcuts ——Name match example (根据方法名匹配)

SpringAopAdvice.xml中,创建一个NameMatchMethodPointcut的 Bean,并将想要拦截的方法名printName注入到属性mappedName中。配置如下:

    <bean id="customerPointcut" class="org.springframework.aop.support.NameMatchMethodPointcut">
        <property name="mappedName" value="printName"/>
    </bean>



 创建一个DefaultPointcutAdvisor的 Advisor bean,将 Pointcut 和 Advice 注入到 Advisor中。如下:

    <bean id="customerAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
        <property name="pointcut" ref="customerPointcut"/>
        <property name="advice" ref="weiAroundMethod"/>
    </bean>



 更改代理customerServiceProxyinterceptorNames中的值,将上面的Advisor代替原来的weiAroundMethod,所有的配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
                            http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="customerService" class="com.shiyanlou.spring.aop.advice.CustomerService">
        <property name="name" value="weihouye"/>
        <property name="url" value="www.weihouyeaiyangzhan.com"/>
    </bean>

    <!--<bean id="weiBeforeMethod" class="com.shiyanlou.spring.aop.advice.WeiBeforeMethod"/>-->
    <!--<bean id="weiAfterMethod" class="com.shiyanlou.spring.aop.advice.WeiAfterMethod"/>-->
    <!--<bean id="weiThrowExceptionMethod" class="com.shiyanlou.spring.aop.advice.WeiThrowExceptionMethod"/>-->
    <bean id="weiAroundMethod" class="com.shiyanlou.spring.aop.advice.WeiAroundMethod"/>

    <bean id="customerPointcut" class="org.springframework.aop.support.NameMatchMethodPointcut">
        <property name="mappedName" value="printName"/>
    </bean>

    <bean id="customerAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
        <property name="pointcut" ref="customerPointcut"/>
        <property name="advice" ref="weiAroundMethod"/>
    </bean>

    <bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="customerService"/>
        <property name="interceptorNames">
            <list>
                <!--<value>weiBeforeMethod</value>-->
                <!--<value>weiAfterMethod</value>-->
                <!--<value>weiThrowExceptionMethod</value>-->
                <value>customerAdvisor</value>
            </list>
        </property>
    </bean>
</beans>



 运行一下App.java,发现只有个printName方法被拦截了。结果输出如下:

*************************
Method Name: printName
Method Arguments: []
WeiBeforeMethod: Before method hi wei!!!
Customer name: weihouye
WeiAfterMethod: After Method hi wei!!
*************************
Customer URL: www.weihouyeaiyangzhan.com
*************************



 以上 Poincut 和 Advisor可以一起配置,即不用单独配置 customerPointcut 和 customerAdvisor,只要在配置 customerAdvisor 时选择 NameMatchMethodPointcutAdvisor,如下:

    <!--pointcut和advisor可以一起配置,只要在配置customerAdvisor时,选择NameMatchMethodPointcutAdvisor-->
    <bean id="customerAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        <property name="mappedName" value="printName"/>
        <property name="advice" ref="weiAroundMethod"/>
    </bean>



 2)、Pointcuts ——Regular expression match example (根据正则表达式匹配)

 可以使用正则表达式匹配拦截方法,Advisor 配置如下:

    <bean id="customerAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <property name="patterns">
            <list>
                <value>.*URL.*</value>
            </list>
        </property>
        <property name="advice" ref="weiAroundMethod"/>
    </bean>

 运行结果:只有个printURL方法被拦截

*************************
Customer name: weihouye
*************************
Method Name: printURL
Method Arguments: []
WeiBeforeMethod: Before method hi wei!!!
Customer URL: www.weihouyeaiyangzhan.com
WeiAfterMethod: After Method hi wei!!
*************************
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352