IOC操作Bean管理

  1. 什么是Bean管理

    • Bean管理指的就是两个操作:
    • 由Spring创建对象
    • SPring注入属性
  2. Bean管理操作有两种方式

    • 基于xml配置文件方式实现
    • 基于注解方式实现
  3. 基于xml方式创建对象

    <!--配置User类对象的创建-->
    <bean id="user" class="com.spring5.test.User"></bean>
    
    • 在Spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象的创建
    • 在bean标签有很多属性,介绍常用的属性:
      • id属性:对应对象唯一的标识
      • class属性:类全路径(包类路径)
      • name属性:同id属性,但是id属性不能使用/,但name属性中可以使用/
    • 创建对象时,默认执行无参数构造方式完成对象创建

基于xml方式注入属性


DI:依赖注入,就是注入属性

  • 第一种注入方式:使用set方法进行注入

    public class Book {
    
        private String bname;
        private String bauthor;
          
        public void setBname(String bname) {
            this.bname = bname;
        }
          
        public void setBauthor(String bauthor) {
            this.bauthor = bauthor;
        }
          
        @Override
        public String toString() {
            return "Book{" +
                    "bname='" + bname + '\'' +
                    ", bauthor='" + bauthor + '\'' +
                    '}';
        }
    }
    
    <!--set方法注入属性-->
    <bean id="book" class="com.spring5.test.Book">
          <!--
              使用property完成属性注入
              name: 类属性名称
              value: 向属性注入的值
          -->
        <property name="bname" value="bookName"></property>
        <property name="bauthor" value="fallbackcolt"></property>
    </bean>
    
  • 第二种注入方式:使用有参数构造方法进行注入

    public class Orders {
    
        private String oname;
        private String address;
    
        public Orders(String oname, String address) {
            this.oname = oname;
            this.address = address;
        }
    
        @Override
        public String toString() {
            return "Orders{" +
                    "oname='" + oname + '\'' +
                    ", address='" + address + '\'' +
                    '}';
        }
    }
    
    <!--有参构造注入属性-->
    <bean id="orders" class="com.spring5.test.Orders">
        <constructor-arg name="oname" value="orderName"></constructor-arg>
        <constructor-arg name="address" value="orderAddress"></constructor-arg>
    </bean>
    

p名称空间注入(了解)

  • 使用p名称空间注入,可以简化基于xml配置方式

  • 添加p名称空间在配置文件中

  • 进行属性注入,在bean标签里面进行操作(p名称属性注入的类必须包含set方法)

  • xml注入其他类型属性
    • 字面值

      1. null值
      <!--null值-->
      <property name="address">
          <null/>
      </property>
      
      1. 属性值包含特殊符号
      <!--
          属性值包含特殊符号
          1. 把<>进行转义
          2. 把特殊符号内容写到CDATA中
      -->
      <property name="address" >
          <value><![CDATA[<<南京>>]]></value>
      </property>
      
    • 注入属性-外部bean

      1. 创建两个类service类和dao类
      public class UserService {
          // 创建USerDao类型属性,生成set方法
          private UserDao userDao;
          public void setUserDao(UserDao userDao) {
              this.userDao = userDao;
          }
      }
      
      public class UserDaoImpl implements UserDao{
          @Override
          public void update() {
              System.out.println("dao update......");
          }
      }
      
      1. 在service调用dao里面的方法
          public void add() {
              System.out.println("service add......");
              userDao.update();
          }
      
      1. 在Spring配置文件中进行配置
          <!--service和dao对象的创建-->
          <bean id="userService" class="com.spring5.test.service.UserService">
              <!--
                  注入userDao对象
                  ref属性(注入外部bean):创建userDao对象bean标签的id值
              -->
              <property name="userDao" ref="userDao"></property>
          </bean>
          <bean id="userDao" class="com.spring5.test.dao.UserDaoImpl"></bean>
      
    • 注入属性-内部bean

      1. 一对多关系: 部门和员工
      2. 在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示
      public class Dept {
      
          private String dname;
      
          public void setDname(String dname) {
              this.dname = dname;
          }
          
          @Override
          public String toString() {
              return "Dept{" +
                      "dname='" + dname + '\'' +
                      '}';
          }
      }
      
      public class Emp {
      
          private String ename;
          private String gender;
          // 员工属于某一个部门,使用对象形式表示
          private Dept dept;
      
          public void setEname(String ename) {
              this.ename = ename;
          }
      
          public void setGender(String gender) {
              this.gender = gender;
          }
      
          public void setDept(Dept dept) {
              this.dept = dept;
          }
          
          @Override
          public String toString() {
              return "Emp{" +
                      "ename='" + ename + '\'' +
                      ", gender='" + gender + '\'' +
                      ", dept=" + dept +
                      '}';
          }
      }
      
      1. 在Spring配置文件中进行配置
      <!--内部bean-->
      <bean id="emp" class="com.spring5.test.bean.Emp">
          <property name="ename" value="fallbackcolt"></property>
          <property name="gender" value="male"></property>
          <property name="dept">
              <bean id="dept" class="com.spring5.test.bean.Dept">
                  <property name="dname" value="保安部"></property>
              </bean>
          </property>
      </bean>
      
    • 注入属性-级联赋值

      • 在Spring配置文件中进行配置

        <!--级联赋值-->
        <!--第一种写法,感觉与外部注入差不多-->
        <bean id="emp" class="com.spring5.test.bean.Emp">
            <property name="ename" value="fallbackcolt"></property>
            <property name="gender" value="male"></property>
            <!--级联赋值-->
            <property name="dept" ref="dept"></property>
        </bean>
        
        <bean id="dept" class="com.spring5.test.bean.Dept">
            <property name="dname" value="财务部"></property>
        </bean>
        
        <!--第二种写法-->
        <bean id="emp2" class="com.spring5.test.bean.Emp">
            <property name="ename" value="fallbackcolt"></property>
            <property name="gender" value="male"></property>
            <!--级联赋值-->
            <!--
                使用dept.dname的前提是,Emp类必须有对应的getDept()方法
                将dept2的值重新赋值为技术部
            -->
            <property name="dept" ref="dept2"></property>
            <property name="dept.dname" value="技术部"></property>
        </bean>
        <!--创建新的Dept对象dept2,并且初始化-->
        <bean id="dept2" class="com.spring5.test.bean.Dept">
            <property name="dname"><null/></property>
        </bean>
        
      • 在Emp类中添加getDept()方法

        public Dept getDept() {
            return dept;
          }
        

xml注入集合属性

  • 创建Stu类,定义数组、list、map、set类型属性,并生成对应是set方法

    public class Stu {
    
        // 数组类型属性
        private String[] courses;
    
        // list集合类型属性
        private List<String> list;
    
        // map集合类型属性
        private Map<String, String> maps;
    
        // set集合类型属性
        private Set<String> sets;
    
        public void setCourses(String[] courses) {
            this.courses = courses;
        }
    
        public void setList(List<String> list) {
            this.list = list;
        }
    
        public void setMaps(Map<String, String> maps) {
            this.maps = maps;
        }
    
        public void setSets(Set<String> sets) {
            this.sets = sets;
        }
        
        @Override
        public String toString() {
            return "Stu{" +
                    "courses=" + Arrays.toString(courses) +
                    ", list=" + list +
                    ", maps=" + maps +
                    ", sets=" + sets +
                    '}';
        }
    }
    
  • 在Spring配置文件中进行配置

    <!--集合类型属性注入-->
    <bean id="stu" class="com.spring5.test.collectiontype.Stu">
        <!--数组类型属性注入-->
        <property name="courses">
            <!--list、array标签都可以-->
            <list>
                <value>java课程</value>
                <value>数据库课程</value>
            </list>
        </property>
    
        <!--list类型属性注入-->
        <property name="list">
            <!--list、array标签都可以-->
            <array>
                <value>张三</value>
                <value>李四</value>
            </array>
        </property>
    
        <!--map类型属性注入-->
        <property name="maps">
            <map>
                <entry key="JAVA" value="java"></entry>
                <entry key="PHP" value="php"></entry>
            </map>
        </property>
    
        <!--set类型属性注入-->
        <property name="sets">
            <set>
                <value>MySQl</value>
                <value>Redis</value>
            </set>
        </property>
    </bean>
    
  • 在集合里面设置对象类型值

    1. 创建Course类

      public class Course {
      
          // 课程名称
          private String cname;
      
          public void setCname(String cname) {
              this.cname = cname;
          }
      
          @Override
          public String toString() {
              return "Course{" +
                      "cname='" + cname + '\'' +
                      '}';
          }
      }
      
    2. 将Stu类中添加CourseList属性,并重写toString()方法

          // 学生所学的多门课程
          private List<Course> courseList;
      
          public void setCourseList(List<Course> courseList) {
              this.courseList = courseList;
          }
      
    3. 在Spring配置文件中设置对象属性值

      <!--在bean.xml中Stu对象中添加courseList属性-->
      <!--注入list集合类型属性,值为Course对象-->
      <property name="courseList">
          <list>
              <ref bean="course1"></ref>
              <ref bean="course2"></ref>
          </list>
      </property>
      
      <!--其中courseList中的值为下面两个Course对象-->
      <!--创建多个Course对象-->
      <bean id="course1" class="com.spring5.test.collectiontype.Course">
          <property name="cname" value="Spring5框架"></property>
      </bean>
      <bean id="course2" class="com.spring5.test.collectiontype.Course">
          <property name="cname" value="MyBatis框架"></property>
      </bean>
      
  • 把集合注入部分提取出来

    1. 新建Book类

      public class Book {
      
          private List<String> list;
      
          public void setList(List<String> list) {
              this.list = list;
          }
      
          @Override
          public String toString() {
              return "Book{" +
                      "list=" + list +
                      '}';
          }
      }
      
    2. 在Spring配置文件中引入名称空间util

      <?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:util="http://www.springframework.org/schema/util"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                                 http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
      </beans>
      
    3. 使用util标签完成list集合注入提取

      <!--提取list集合类型属性注入-->
      <util:list id="bookList">
          <value>从零开始学JAVA</value>
          <value>从零开始学PYTHON</value>
          <value>从零开始学MySQL</value>
      </util:list>
      
      <!--提取list集合类型属性注入使用-->
      <bean id="book" class="com.spring5.test.collectiontype.Book">
          <property name="list" ref="bookList"></property>
      </bean>
      

FactoryBean

  • Spring有两种类型bean,一种普通bean,另外一种工厂bean(FactoryBean)

    • 普通bean:在配置文件中定义bean类型就是返回类型

    • 工厂bean:在配置文件中定义bean类型可以和返回类型不一样

      1. 创建类,让这个类作为工厂bean,实现接口FactoryBean

        public class MyBean implements FactoryBean<Course> {
        
        }
        
      2. 实现接口里的方法,在实现的方法中定义返回的bean类型

            // 定义返回bean
            @Override
            public Course getObject() throws Exception {
                Course course = new Course();
                course.setCname("test");
                return course;
            }
        
            @Override
            public Class<?> getObjectType() {
                return null;
            }
        
            @Override
            public boolean isSingleton() {
                return FactoryBean.super.isSingleton();
            }
        

bean作用域

  • 在Spring里面,设置bean实例是单实例还是多实例
  • 在Spring里面,默认情况下bean是单实例对象
  • 设置bean多实例对象
    • 在Spring配置文件中,bean标签中,有属性scope用于设置单实例或者多实例
    • scope属性值:
      1. 默认值:singleton,表示单实例对象
      2. prototype,表示多实例对象
      3. request,表示每一次http新的请求都会产生一个新的bean对象
      4. session,表示每一个独立的session会有一个新的bean对象
    • singletonprototype区别:
      1. singleton是单实例,prototype是多实例
      2. 设置scope值是singleton时,加载Spring配置文件时,就会创建单实例对象
      3. 设置scope值是prototype时,在调用getBean()方法才会创建多实例对象

bean的生命周期

  • 生命周期

    • 从对象创建到对象销毁的过程
  • bean的生命周期

    1. 通过构造器创建bean实例(无参数构造)
    2. 为bean的属性设置值和对其他bean的引用(调用set方法)
    3. 调用bean的初始化的方法(通过设置bean标签中的init-method为声明的方法进行配置)
    4. bean可以使用了(对象获取到了)
    5. 当容器关闭的时候,调用bean的销毁的方法((通过设置bean标签中的destroy-method为声明的方法进行配置)
  • 演示bean的生命周期

    1. 新建Orders类

      public class Orders {
      
          public Orders() {
              System.out.println("1.执行了无参数构造创建bean实例");
          }
      
          private String oname;
      
          public void setOname(String oname) {
              this.oname = oname;
              System.out.println("2.调用set方法设置属性的值");
          }
      
          // 创建执行初始化的方法
          public void initMethod() {
              System.out.println("3.执行初始化方法");
          }
      
          // 创建执行销毁的方法
          public void destroyMethod() {
              System.out.println("5.执行销毁的方法");
          }
      
      }
      
    2. 配置bean.xml文件

      <bean id="orders" class="com.spring5.test.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
          <property name="oname" value="PC"></property>
      </bean>
      
    3. 测试

      @Test
      public void testOrders() {
          ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
          Orders orders = context.getBean("orders", Orders.class);
          System.out.println("4.获取创建的bean实例对象");
          System.out.println(orders);
      
          // 手动执行bean实例的销毁
          // ClassPathXmlApplicationContext才有close,ApplicationContext没有close
          ((ClassPathXmlApplicationContext)context).close();
      }
      
    4. 测试运行结果

      1.执行了无参数构造创建bean实例
      2.调用set方法设置属性的值
      3.执行初始化方法
      4.获取创建的bean实例对象
      com.spring5.test.bean.Orders@587e5365
      5.执行销毁的方法

      Process finished with exit code 0

  • bean的后置处理器,加上后置处理器后bean的生命周期有7步

    1. 通过构造器创建bean实例(无参数构造)
    2. 为bean的属性设置值和对其他bean的引用(调用set方法)
    3. 把bean实例传递给bean后置处理器的postProcessBeforeInitialization方法
    4. 调用bean的初始化的方法(通过设置bean标签中的init-method为声明的方法进行配置)
    5. 把bean实例传递给bean后置处理器的postProcessAfterInitialization方法
    6. bean可以使用了(对象获取到了)
    7. 当容器关闭的时候,调用bean的销毁的方法((通过设置bean标签中的destroy-method为声明的方法进行配置)
  • 演示添加后置处理器效果

    1. 创建类,实现接口BeanPostProcessor

      public class OrdersPost implements BeanPostProcessor {
      
          @Override
          public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
              System.out.println("a.在初始化之前执行的方法");
              return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
          }
      
          @Override
          public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
              System.out.println("b.在初始化之后执行的方法");
              return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
          }
      }
      
    2. 在bean.xml中配置后置处理器

      <!--配置后置处理器-->
      <bean id="ordersPost" class="com.spring5.test.bean.OrdersPost"></bean>
      
    3. 测试运行结果

      1.执行了无参数构造创建bean实例
      2.调用set方法设置属性的值
      a.在初始化之前执行的方法
      3.执行初始化方法
      b.在初始化之后执行的方法
      4.获取创建的bean实例对象
      com.spring5.test.bean.Orders@305b7c14
      5.执行销毁的方法

      Process finished with exit code 0


xml自动装配

  • 什么是自动装配

    根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入

  • 演示自动装配过程

    • 根据属性名称自动注入

      <!--
          实现自动装配
          autowire: 配置自动装配
          |___byName: 根据属性名称注入,注入bean的id值和类属性名一样
          |___byType: 根据属性类型注入
      -->
      <bean id="emp" class="com.spring5.test.autowire.Emp" autowire="byName">
          <!--<property name="dept" ref="dept"></property>-->
      </bean>
      <bean id="dept" class="com.spring5.test.autowire.Dept"></bean>
      
    • 根据属性类型自动注入

      <bean id="emp" class="com.spring5.test.autowire.Emp" autowire="byType">
          <!--<property name="dept" ref="dept"></property>-->
      </bean>
      <bean id="dept" class="com.spring5.test.autowire.Dept"></bean>
      

管理外部属性文件

  • 直接配置数据库信息

    • 配置druid连接池

    • 引入druid连接池依赖jar包

    • 配置bean.xml

      <!--直接配置连接池-->
      <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
          <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
          <property name="url" value="jdbc:mysql://localhost:3306/Test"></property>
          <property name="username" value="test"></property>
          <property name="password" value="123456"></property>
      </bean>
      
      
  • 通过引入外部属性文件配置数据库连接池

    1. 创建外部属性文件,properties格式文件,写数据库信息

      prop.driverClass=com.mysql.jdbc.Driver
      prop.url=jdbc:mysql://localhost:3306/Test
      prop.username=test
      prop.password=123456
      
    2. 把外部properties属性文件引入到Spring配置文件中

      • 引入context命名空间

        <beans xmlns="http://www.springframework.org/schema/beans"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:context="http://www.springframework.org/schema/context"
               xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                                   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
        
      • 在Spring配置文件中使用标签引入外部属性文件

        <!--引入外部属性文件-->
        <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
        <!--配置连接池-->
        <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="${prop.driverClass}"></property>
            <property name="url" value="${prop.url}"></property>
            <property name="username" value="${prop.username}"></property>
            <property name="password" value="${prop.password}"></property>
        </bean>
        

基于注解方式注入属性

  • 什么是注解

    1. 注解是代码特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值...)
    2. 使用注解,注解可以作用在类、方法以及属性上面
    3. 使用注解的目的:可以简化xml配置
  • Spring针对Bean管理中创建对象提供注解

    1. @Component,通用注解?
    2. @Service,一般用于业务逻辑层,Service层
    3. @Controller,一般用于web层
    4. @Repository,一般用于dao层,持久层

    上述四个注解功能是一样的,都可以用来创建bean实例

  • 基于注解方式实现对象创建

    1. 导入依赖spring-aop-5.3.9.jar

    2. 开启组件扫描

      <!--
          开启组件扫描
          1. 如果扫描多个包,多个包使用逗号隔开
          2. 扫描包的上层目录
      -->
      <!--<context:component-scan base-package="com.spring5.test.testdemo,com.spring5.test.dao"></context:component-scan>-->
      <context:component-scan base-package="com.spring5.test"></context:component-scan>
      
    3. 创建类,在类上添加创建对象注解

      /*
          在注解里面value属性值可以省略不写,默认值为首字母小写的类名称
       */
      @Component(value = "userService") // <bean id="userService" class="..."></bean>
      public class UserService {
      
          public void add() {
              System.out.println("add......");
          }
      
      }
      
    4. 开启组件扫描细节配置

      <!--
          示例1
          use-default-filters="false"     表示不使用默认的filter
          context:include-filter          设置扫描的内容
      -->
      <context:component-scan base-package="com.spring5.test" use-default-filters="false">
          <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
      </context:component-scan>
      
      <!--
          示例2
          context:exclude-filter          设置不扫描的内容
      -->
      <context:component-scan base-package="com.spring5.test">
          <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
      </context:component-scan>
      
    5. 基于注解方式实现属性注入

      • @AutoWired:根据属性类型进行自动注入

        1. 把service和dao对象创建,在service和dao类添加创建对象注解
        2. 在service注入dao对象,在service类添加dao类型属性,在属性上面
      • @Qualifier:根据属性名称进行自动注入(和@AutoWired一起使用,Qualifier(value="xxx")

      • @Resource:可以根据类型注入,也可以根据名称注入(高版本已经移除该注解,@Resource是javax的包,不是Spring的包)

      • @Value:注入普通类型属性(@Value(value="xxx")

        public interface UserDao {
        
            public void add();
        
        }
        
        @Repository(value = "userDaoImpl1")
        public class UserDaoImpl implements UserDao{
        
            @Override
            public void add() {
                System.out.println("userDaoImpl add...");
            }
        
        }
        
        // 在注解里面value属性值可以省略不写,默认值为首字母小写的类名称
        @Service(value = "userService") // <bean id="userService" class="..."></bean>
        public class UserService {
        
            // 定义dao类型属性
            // 不需要添加set方法
            // 添加注入属性注解
            @Autowired
            @Qualifier(value = "userDaoImpl1")
            private UserDao userDao;
        
            @Value(value = "initNameValue")
            private String name;
        
            public void add() {
                System.out.println("name=" + name);
                System.out.println("userService add......");
                userDao.add();
            }
        
        }
        
  • 完全注解开发

    1. 创建配置类,替代xml配置文件

      @Configuration // 作为配置类,替代xml配置文件
      @ComponentScan(basePackages = {"com.spring5.test"})
      public class SpringConfig {
      
      }
      
    2. 编写测试类

      @Test
      public void addTest2() {
          ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
          UserService userService = context.getBean("userService", UserService.class);
          System.out.println(userService);
          userService.add();
      }
      

      com.spring5.test.service.UserService@57d7f8ca
      name=initNameValue
      userService add......
      userDaoImpl add...

      Process finished with exit code 0

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

推荐阅读更多精彩内容