BeanFactory—接口篇

BeanFactory总览

BeanFactory接口是Spring IoC的基础。它的特定契约主要用于与Spring的其他部分以及相关的第三方框架集成,它的“DefaultListableBeanFactory”实现是高级“GenericApplicationContext”容器中的一个关键委托。

“BeanFactory”和相关接口(如“BeanFactoryAware”、“InitializingBean”、“DisposableBean”)是其他框架组件的重要集成点:不需要任何注解甚至反射,它们允许容器及其组件之间非常高效的交互。应用程序级bean可能使用相同的回调接口,但通常更喜欢声明性依赖注入,通过注解或编程配置。

请注意,核心的“BeanFactory”API级别及其“DefaultListableBeanFactory”实现对配置格式或要使用的任何组件注释不做任何假设。所有这些功能都是通过诸如“XmlBeanDefinitionReader”和“AutowiredAnnotationBeanPostProcessor”等扩展来实现的,这些扩展在作为核心元数据表示的共享“BeanDefinition”对象上运行。这就是使Spring容器如此灵活和可扩展的本质。

BeanFactory接口体系

如果bean name配置为单例,应用内只会获取到一个实例.如果配置为原型,那么可以实例化好后填充属性(基于用户的配置).

BeanFactory需要管理bean的生命周期,比如初始化时需要按顺序实现如下接口:

  1. BeanNameAware's {@code setBeanName}
  2. BeanClassLoaderAware's {@code setBeanClassLoader}
  3. BeanFactoryAware's {@code setBeanFactory}
  4. ResourceLoaderAware's {@code setResourceLoader}仅对application context有效
  5. ApplicationEventPublisherAware's {@code setApplicationEventPublisher}仅对application context有效
  6. MessageSourceAware's {@code setMessageSource}仅对application context有效
  7. ApplicationContextAware's {@code setApplicationContext}仅对application context有效
  8. ServletContextAware's {@code setServletContext}仅对application context有效
  9. {@code postProcessBeforeInitialization} methods of BeanPostProcessors
  10. InitializingBean's {@code afterPropertiesSet}
  11. a custom init-method definition xml中配置的init-method
  12. {@code postProcessAfterInitialization} methods of BeanPostProcessors

还有关闭容器的接口:

  1. DisposableBean's {@code destroy}
  2. a custom destroy-method definition xml配置中的destroy-method

接口里定义了一个变量String FACTORY_BEAN_PREFIX = "&"; 这是用来区分是获取FactoryBean还是FactoryBean的createBean创建的实例.如果&开始则获取FactoryBean;否则获取createBean创建的实例.

BeanFactory接口方法

序号 方法名称 描述
1 Object getBean(String name) throws BeansException; 返回指定bean的一个实例,该实例可以是共享的,也可以是独立的。
2 <T> T getBean(String name, Class<T> requiredType) throws BeansException; 输入bean必须匹配。可以是实际类的接口或超类,也可以是任何匹配的{null}。例如,如果值是{Object.class}对象。无论返回的实例的类是什么,这个方法都会成功。
3 <T> T getBean(Class<T> requiredType) throws BeansException; 允许指定显式构造函数参数/工厂方法参数,覆盖bean定义中指定的默认参数(如果有的话)
4 Object getBean(String name, Object... args) throws BeansException; 使用显式参数创建bean实例时使用的args参数(仅在创建新实例而不是检索现有实例时使用)
5 <T> T getBean(Class<T> requiredType, Object... args) throws BeansException; 使用显式参数创建bean实例时使用的args参数(仅在创建新实例而不是检索现有实例时使用)
6 boolean containsBean(String name); 这个bean工厂是包含bean定义还是外部注册的具有给定名称的singleton实例
7 boolean isSingleton(String name) throws NoSuchBeanDefinitionException; 是否singleton
8 boolean isPrototype(String name) throws NoSuchBeanDefinitionException; 是否prototype
9 boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException; name与传入类型是否匹配,ResolvableType是封装的java.lang.reflect.Type
10 boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException; name与传入类型是否匹配
11 Class<?> getType(String name) throws NoSuchBeanDefinitionException; 返回给定bean name的类型
12 String[] getAliases(String name); 返回给定bean name的别名

总结:
1、4个获取实例的方法。getBean的重载方法。
2、4个判断的方法。判断是否存在,是否为单例、原型,名称类型是否匹配。
3、1个获取类型的方法、一个获取别名的方法。根据名称获取类型、根据名称获取别名。一目了然!
这10个方法,很明显,这是一个典型的工厂模式的工厂接口。

2. AutowireCapableBeanFactory

在BeanFactory基础上实现对已存在实例的管理.

可以使用这个接口集成其它框架, 捆绑并填充并不由Spring管理生命周期并已存在的实例.像集成WebWork的Actions 和Tapestry Page就很实用.

一般应用开发者不会使用这个接口,所以像ApplicationContext这样的外观实现类不会实现这个接口,如果真手痒痒可以通过ApplicationContext的getAutowireCapableBeanFactory接口获取.

这边定义了5种自动装配策略:不注入AUTOWIRE_NO,使用bean name策略装配AUTOWIRE_BY_NAME,使用类型装配策略AUTOWIRE_BY_TYPE,使用构造器装配策略AUTOWIRE_CONSTRUCTOR,自动装配策略AUTOWIRE_AUTODETECT

这边的自动策略是先尝试构造器,然后才是byType.这边应该是跟xml配置文件中的装配策略对应.

AutowireCapableBeanFactory定义的方法:

序号 方法名称 描述
1 <T> T createBean(Class<T> beanClass) throws BeansException; 创建和填充外部bean实例的典型方法
2 void autowireBean(Object existingBean) throws BeansException; 使用autowireBeanProperties装配属性
3 Object configureBean(Object existingBean, String beanName) throws BeansException; 自动装配属性,填充属性值,使用诸如setBeanName,setBeanFactory这样的工厂回调填充属性,最好还要调用post processor
4 Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException; 在bean的生命周期进行细粒度控制的专门方法。会执行bean完整的初始化,包括BeanPostProcessors和initializeBean
5 Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException; 根据指定Class创建一个全新的Bean实例
6 void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) throws BeansException; 在bean的生命周期进行细粒度控制的专门方法。
7 void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException; 在bean的生命周期进行细粒度控制的专门方法。
8 Object initializeBean(Object existingBean, String beanName) throws BeansException; 在bean的生命周期进行细粒度控制的专门方法。
9 Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException; 在bean的生命周期进行细粒度控制的专门方法。
10 Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException; 初始化之后执行BeanPostProcessors
11 void destroyBean(Object existingBean); 销毁给定的bean
12 <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException; 解析与给定对象类型(如果有的话)唯一匹配的bean实例,包括它的bean名称。
13 Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName) throws BeansException; 分解指定的依赖
14 Object resolveDependency(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException; 分解指定的依赖

ListableBeanFactory

ListableBeanFactory是BeanFactory接口的扩展,bean工厂可以枚举所有bean实例,而不是根据客户的请求逐一查找。需要预加载所有bean定义(例如基于xml的工厂)的BeanFactory实现可以实现这个接口。

这个接口中的方法仅仅关注此工厂内部的bean定义,会会忽略任何被像ConfigurableBeanFactory的registerSingleton方法已注册的单例的bean。getBeanNamesOfType和getBeansOfType例外,但也会手动的检查已被注册的单例bean。当然,BeanFactory的getBean方法也可以透明的访问这些特殊的bean(已被注册的单例bean)。然而,在一般的场合,无论如何,所有bean都会被外部定义,所以许多程序不需要考虑这方面区别。

注意: getBeanDefinitionCount和containsBeanDefinition的实现方法因为效率比较低,还是少用为好.

总结:
1、总共5个静态不可变常量来指明装配策略,其中一个常量被Spring3.0废弃、一个常量表示没有自动装配,另外3个常量指明不同的装配策略——根据名称、根据类型、根据构造方法。
2、9个跟自动装配有关的方法,实在是繁杂,具体的意义我们研究类的时候再分辨吧。
3、2个执行BeanPostProcessors的方法。
4、3个分解指定依赖的方法
这个工厂接口继承自BeanFacotory,它扩展了自动装配的功能,根据类定义BeanDefinition装配Bean、执行前、后处理器等。

ListableBeanFactory方法

序号 方法名称 描述
1 boolean containsBeanDefinition(String beanName); 检查这个BeanFactory是否包含给定名字的的bean定义。 不考虑这个工厂参与的任何层级关系,忽略不是bean定义的所有通过其他方式注册的单例bean
2 int getBeanDefinitionCount(); 返回在此工厂中定义的bean数量。不考虑这个工厂参与的任何层级关系,忽略不是bean定义的所有通过其他方式注册的单例bean
3 String[] getBeanDefinitionNames(); 返回此工厂中定义的所有bean的名字。不考虑此工厂参与的所有层次关系,忽略不是bean定义的所有通过其他方式注册的单例bean
4 String[] getBeanNamesForType(ResolvableType type); 返回匹配给定类型(包括子类)的所有bean的名字,如果是普通bean,则是bean定义的名字,如果是FactoryBean,则是其getObjectType方法返回的对象的名字
5 String[] getBeanNamesForType(Class<?> type); 返回匹配给定类型(包括子类)的所有bean的名字,如果是普通bean,则是bean定义的名字,如果是FactoryBean,则是其getObjectType方法返回的对象的名字
6 String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit); allowEagerInit:是否允许马上加载 ,如果是factoryBean创建的对象,此处应是true
7 <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException; 返回匹配给定类型(包含子类)的实例,可能是通过bean定义创建,也可以是FactoryBean时其getObjectType返回
8 String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType); 返回指定注解的bean name
9 Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException; 返回指定注解的bean map
10 <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) throws NoSuchBeanDefinitionException; 返回指定bean name上的指定注解对象

HierarchicalBeanFactory

提供父容器的访问功能.至于父容器的设置,需要找ConfigurableBeanFactory的setParentBeanFactory(接口把设置跟获取给拆开了!)。

HierarchicalBeanFactory方法

序号 方法名称 描述
1 BeanFactory getParentBeanFactory(); 返回父bean factory对象
2 boolean containsLocalBean(String name); 检查这个BeanFactory是否包含给定名字的的bean定义。 不考虑这个工厂参与的任何层级关系,忽略不是bean定义的所有通过其他方式注册的单例bean

ConfigurableBeanFactory

ConfigurableBeanFactory定义BeanFactory的配置.ConfigurableBeanFactory中定义了太多太多的api,比如类加载器,类型转化,属性编辑器,BeanPostProcessor,作用域,bean定义,处理bean依赖关系,合并其他ConfigurableBeanFactory,bean如何销毁.

ConfigurableBeanFactory同时继承了HierarchicalBeanFactory 和 SingletonBeanRegistry 这两个接口,即同时继承了分层和单例类注册的功能。

ConfigurableBeanFactory方法

序号 方法名称 描述
1 String SCOPE_SINGLETON = "singleton"; 单例
2 String SCOPE_PROTOTYPE = "prototype"; 原型
3 void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException; 搭配HierarchicalBeanFactory接口的getParentBeanFactory方法
4 void setBeanClassLoader(ClassLoader beanClassLoader); 设置、返回工厂的类加载器
5 ClassLoader getBeanClassLoader(); 设置、返回工厂的类加载器
6 void setTempClassLoader(ClassLoader tempClassLoader); 设置、返回一个临时的类加载器
7 ClassLoader getTempClassLoader(); 设置、返回一个临时的类加载器
8 void setCacheBeanMetadata(boolean cacheBeanMetadata); 设置、是否缓存元数据,如果false,那么每次请求实例,都会从类加载器重新加载(热加载)
9 isCacheBeanMetadata(); 是否缓存元数据
10 void setBeanExpressionResolver(BeanExpressionResolver resolver); Bean表达式分解器
11 BeanExpressionResolver getBeanExpressionResolver(); 设置、返回一个转换服务
12 void setConversionService(ConversionService conversionService); 设置、返回一个转换服务
13 ConversionService getConversionService(); 设置属性编辑登记员...
14 void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar); 注册常用属性编辑器
15 void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass); 用工厂中注册的通用的编辑器初始化指定的属性编辑注册器
16 void copyRegisteredEditorsTo(PropertyEditorRegistry registry); 设置、得到一个类型转换器
17 void setTypeConverter(TypeConverter typeConverter); 设置、得到一个类型转换器
18 TypeConverter getTypeConverter(); 设置、得到一个类型转换器
19 void addEmbeddedValueResolver(StringValueResolver valueResolver); 增加一个嵌入式的StringValueResolver
20 boolean hasEmbeddedValueResolver(); 是否有一个嵌入式的StringValueResolver
21 String resolveEmbeddedValue(String value); 分解指定的嵌入式的值
22 void addBeanPostProcessor(BeanPostProcessor beanPostProcessor); 设置一个Bean后处理器
23 int getBeanPostProcessorCount(); 返回Bean后处理器的数量
24 void registerScope(String scopeName, Scope scope); 注册范围
25 String[] getRegisteredScopeNames(); 返回注册的范围名
26 Scope getRegisteredScope(String scopeName); 返回指定的范围
27 AccessControlContext getAccessControlContext(); 返回本工厂的一个安全访问上下文
28 void copyConfigurationFrom(ConfigurableBeanFactory otherFactory); 从其他的工厂复制相关的所有配置
29 void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException; 给指定的Bean注册别名
30 void resolveAliases(StringValueResolver valueResolver); 根据指定的StringValueResolver移除所有的别名
31 BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; 返回指定Bean合并后的Bean定义
32 boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException; 判断指定Bean是否为一个工厂Bean
33 void setCurrentlyInCreation(String beanName, boolean inCreation); 设置一个Bean是否正在创建
34 boolean isCurrentlyInCreation(String beanName); 返回指定Bean是否已经成功创建
35 void registerDependentBean(String beanName, String dependentBeanName); 注册一个依赖于指定bean的Bean
36 String[] getDependentBeans(String beanName); 返回依赖于指定Bean的所欲Bean名
37 String[] getDependenciesForBean(String beanName); 返回指定Bean依赖的所有Bean名
38 void destroyBean(String beanName, Object beanInstance); 销毁指定的Bean
39 void destroyScopedBean(String beanName); 销毁指定的范围Bean
40 void destroySingletons(); 销毁所有的单例类

分类:
1、2个静态不可变常量分别代表单例类和原型类。
2、1个设置父工厂的方法,跟HierarchicalBeanFactory接口的getParentBeanFactory方法互补。
3、4个跟类加载器有关的方法:get/set工厂类加载器和get/set临时类加载器。
4、2个设置、是否缓存元数据的方法(热加载开关)。
5、11个处理Bean注册、加载等细节的方法,包括:Bean表达式分解器、转换服务、属性编辑登记员、属性编辑器、属性编辑注册器、类型转换器、嵌入式的字符串分解器
6、2个处理Bean后处理器的方法。
7、3个跟注册范围相关的方法。
8、1个返回安全访问上下文的方法、1个从其他的工厂复制相关的所有配置的方法。
9、2个跟Bean别名相关的方法、1个返回合并后的Bean定义的方法。
10、1个判断是否为工厂Bean的方法、2个跟当前Bean创建时机相关的方法。
11、3个跟Bean依赖相关的方法、3个销毁Bean相关的方法。
SingletonBeanRegistry 这两个接口,并额外独有38个方法!这38个方法包含了工厂创建、注册一个Bean的众多细节。这个工厂名为ConfigurableBeanFactory,真是名不虚传!统计一下此时的ConfigurableBeanFactory的方法数吧。自有的37个方法、HierarchicalBeanFactory的2个方法、SingletonBeanRegistry的5个方法、爷爷接口BeanFactory的10个方法,共有54个方法!虽然方法繁多,还算井井有条!

ConfigurableListableBeanFactory

提供bean definition的解析,注册功能,再对单例来个预加载(解决循环依赖问题).

貌似我们一般开发就会直接定义这么个接口了事.而不是像Spring这样先根据使用情况细分那么多,到这边再合并

ConfigurableListableBeanFactory方法

序号 方法名称 描述
1 void ignoreDependencyType(Class<?> type); 忽略自动装配的依赖类型
2 void ignoreDependencyInterface(Class<?> ifc); 忽略自动装配的接口
3 void registerResolvableDependency(Class<?> dependencyType, Object autowiredValue); 注册一个可分解的依赖
4 boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor) throws NoSuchBeanDefinitionException; 判断指定的Bean是否有资格作为自动装配的候选者
5 BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; 返回注册的Bean定义
6 void freezeConfiguration(); 暂时冻结所有的Bean配置
7 boolean isConfigurationFrozen(); 判断本工厂配置是否被冻结
8 void preInstantiateSingletons() throws BeansException; 使所有的非延迟加载的单例类都实例化。
9 Iterator<String> getBeanNamesIterator(); 返回bean name迭代器
10 void clearMetadataCache(); 清除元数据缓存

具体:
1、2个忽略自动装配的的方法。
2、1个注册一个可分解依赖的方法。
3、1个判断指定的Bean是否有资格作为自动装配的候选者的方法。
4、1个根据指定bean名,返回注册的Bean定义的方法。
5、2个冻结所有的Bean配置相关的方法。
6、1个使所有的非延迟加载的单例类都实例化的方法。
7、1个返回所有bean name的迭代器方法
8、1个清除元数据缓存的方法
总结:工厂接口ConfigurableListableBeanFactory同时继承了3个接口,ListableBeanFactory、AutowireCapableBeanFactory 和 ConfigurableBeanFactory,扩展之后,加上自有的这8个方法,这个工厂接口总共有83个方法,实在是巨大到不行了。这个工厂接口的自有方法总体上只是对父类接口功能的补充,包含了BeanFactory体系目前的所有方法,可以说是接口的集大成者。

BeanFactory or ApplicationContext?

尽量使用‘ApplicationContext’除非你有很好的理由不这样做,使用‘GenericApplicationContext’和它的子类‘AnnotationConfigApplicationContext’作为通用的自定义引导实现。这些是Spring核心容器的主要入口点,用于所有常见目的:加载配置文件、触发类路径扫描、以编程方式注册bean定义和带注释的类。

因为“ApplicationContext”包含“BeanFactory”的所有功能,所以通常建议使用它而不是普通的“BeanFactory”,除非是需要对bean处理进行完全控制的场景。在‘ApplicationContext’(如‘GenericApplicationContext’实现)中,有几种类型的bean将被约定(即通过bean名称或bean类型)检测,特别是后处理器,而普通的‘DefaultListableBeanFactory’与任何特殊bean无关。

对于许多扩展容器特性,如注释处理和AOP代理,' BeanPostProcessor '扩展点是必不可少的。如果你只使用一个普通的“DefaultListableBeanFactory”,这样的后处理器在默认情况下不会被检测和激活。这种情况可能令人困惑,因为您的bean配置实际上没有任何问题;在这种情况下,需要通过额外的设置完全引导容器。

下表列出了“BeanFactory”和“ApplicationContext”接口和实现提供的功能

Feature BeanFactory ApplicationContext
Bean instantiation/wiring Yes Yes
Integrated lifecycle management No Yes
Automatic BeanPostProcessor registration No Yes
Automatic BeanFactoryPostProcessor registration No Yes
Convenient MessageSource access (for internalization) No Yes
Built-in ApplicationEvent publication mechanism No Yes

要显式地将bean后处理器注册到DefaultListableBeanFactory,您需要以编程方式调用addBeanPostProcessor:

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// populate the factory with bean definitions

// now register any needed BeanPostProcessor instances
factory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
factory.addBeanPostProcessor(new MyBeanPostProcessor());

// now start using the factory

要将' BeanFactoryPostProcessor '应用到普通的' DefaultListableBeanFactory '上,需要调用其' postProcessBeanFactory '方法:

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new FileSystemResource("beans.xml"));

// bring in some property values from a Properties file
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));

// now actually do the replacement
cfg.postProcessBeanFactory(factory);

在这两种情况下,显式注册步骤都不方便,这就是为什么在spring支持的应用程序中,各种“ApplicationContext”变体比普通的“defaultlistablebeanfactory”更受青睐的原因,特别是在典型的企业设置中依赖“BeanFactoryPostProcessor”和“BeanPostProcessor”实现扩展容器功能时更是如此。

一个“AnnotationConfigApplicationContext”具有所有现成注册的通用注释后处理器,并且可以通过配置注释(如“@EnableTransactionManagement”)在幕后引入额外的处理器。在Spring基于注释的配置模型的抽象级别上,bean后处理器的概念仅仅是一个内部容器细节。

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

推荐阅读更多精彩内容