源碼>Spring IOC源碼深度剖析!干貨滿滿闪水!干貨到底!

今天帶來Spring IOC源碼深度剖析蒙具!喜歡的朋友們可以來個一鍵三連支持下博主哦~

Spring IOC源碼深度剖析

  • 好處:提?培養(yǎng)代碼架構(gòu)思維球榆、深?理解框架
  • 原則
    1.定焦原則:抓主線
    2.宏觀原則:站在上帝視?,關(guān)注源碼結(jié)構(gòu)和業(yè)務(wù)流程(淡化具體某?代碼的編寫細(xì)節(jié))
  • 讀源碼的?法和技巧
    1.斷點(diǎn)(觀察調(diào)?棧)
    2.反調(diào)(Find Usages)
    3.經(jīng)驗(yàn)(spring框架中doXXX禁筏,做具體處理的地?)
  • Spring源碼構(gòu)建
    1.下載源碼(github)
    2.安裝gradle 5.6.3(類似于maven) Idea 2019.1 Jdk 11.0.5
    3.導(dǎo)?(耗費(fèi)?定時間)
    4.編譯?程(順序:core-oxm-context-beans-aspects-aop)
    5.?程—>tasks—>compileTestJava

第1節(jié) Spring IoC容器初始化主體流程

1.1 Spring IoC的容器體系

IoC容器是Spring的核?模塊持钉,是抽象了對象管理、依賴關(guān)系管理的框架解決?案篱昔。Spring 提供了很多的容器每强,其中 BeanFactory 是頂層容器(根容器)始腾,不能被實(shí)例化,它定義了所有 IoC 容器 必須遵從的?套原則空执,具體的容器實(shí)現(xiàn)可以增加額外的功能浪箭,?如我們常?到的ApplicationContext,其下更具體的實(shí)現(xiàn)如 ClassPathXmlApplicationContext 包含了解析 xml 等?系列的內(nèi)容辨绊,AnnotationConfigApplicationContext 則是包含了注解解析等?系列的內(nèi)容奶栖。Spring IoC 容器繼承體系?常聰明,需要使?哪個層次?哪個層次即可邢羔,不必使?功能??全的驼抹。

BeanFactory 頂級接??法棧如下

在這里插入圖片描述

BeanFactory 容器繼承體系
在這里插入圖片描述

通過其接?設(shè)計桑孩,我們可以看到我們?貫使?的 ApplicationContext 除了繼承BeanFactory的?接?拜鹤,還繼承了ResourceLoader、MessageSource等接?流椒,因此其提供的功能也就更豐富了敏簿。

下?我們以 ClasspathXmlApplicationContext 為例,深?源碼說明 IoC 容器的初始化流程宣虾。

1.2 Bean?命周期關(guān)鍵時機(jī)點(diǎn)

思路:創(chuàng)建?個類 LagouBean 惯裕,讓其實(shí)現(xiàn)?個特殊的接?,并分別在接?實(shí)現(xiàn)的構(gòu)造器绣硝、接??法中斷點(diǎn)蜻势,觀察線程調(diào)?棧,分析出 Bean 對象創(chuàng)建和管理關(guān)鍵點(diǎn)的觸發(fā)時機(jī)鹉胖。
LagouBean類

package com.lagou;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import
org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
/**
* @Author 應(yīng)癲
* @create 2019/12/3 11:46
*/
public class LagouBean implements InitializingBean{
 /**
 * 構(gòu)造函數(shù)
 */
 public LagouBean(){
 System.out.println("LagouBean 構(gòu)造器...");
 }
 /**
 * InitializingBean 接?實(shí)現(xiàn)
 */
 public void afterPropertiesSet() throws Exception {
 System.out.println("LagouBean afterPropertiesSet...");
 } }

BeanPostProcessor 接?實(shí)現(xiàn)類

package com.lagou;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
/**
* @Author 應(yīng)癲
* @create 2019/12/3 16:59
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
 public MyBeanPostProcessor() {
 System.out.println("BeanPostProcessor 實(shí)現(xiàn)類構(gòu)造函數(shù)...");
 }
 @Override
 public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
 if("lagouBean".equals(beanName)) {
 System.out.println("BeanPostProcessor 實(shí)現(xiàn)類
postProcessBeforeInitialization ?法被調(diào)?中......");
 }
 return bean;
 }
 @Override
 public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
 if("lagouBean".equals(beanName)) {
 System.out.println("BeanPostProcessor 實(shí)現(xiàn)類
postProcessAfterInitialization ?法被調(diào)?中......");
 }
 return bean;
 } }

BeanFactoryPostProcessor 接?實(shí)現(xiàn)類

package com.lagou;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import
org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
/**
* @Author 應(yīng)癲
* @create 2019/12/3 16:56
*/
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
 public MyBeanFactoryPostProcessor() {
 System.out.println("BeanFactoryPostProcessor的實(shí)現(xiàn)類構(gòu)造函數(shù)...");
 }
 @Override
 public void postProcessBeanFactory(ConfigurableListableBeanFactory
beanFactory) throws BeansException {
 System.out.println("BeanFactoryPostProcessor的實(shí)現(xiàn)?法調(diào)?中......");
 } }

applicationContext.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
 https://www.springframework.org/schema/beans/spring-beans.xsd
">
 <bean id="lagouBean" class="com.lagou.LagouBean"/>
 <bean id="myBeanFactoryPostProcessor"
class="com.lagou.MyBeanFactoryPostProcessor"/>
 <bean id="myBeanPostProcessor" class="com.lagou.MyBeanPostProcessor"/>
</beans>

IoC 容器源碼分析?例

/**
 *Ioc 容器源碼分析基礎(chǔ)案例
*/
@Test
public void testIoC() {
 ApplicationContext applicationContext = new 
ClassPathXmlApplicationContext("classpath:applicationContext.xml");
 LagouBean lagouBean = applicationContext.getBean(LagouBean.class);
 System.out.println(lagouBean);
} 

(1)分析 Bean 的創(chuàng)建是在容器初始化時還是在 getBean 時

在這里插入圖片描述

根據(jù)斷點(diǎn)調(diào)試握玛,我們發(fā)現(xiàn),在未設(shè)置延遲加載的前提下甫菠,Bean 的創(chuàng)建是在容器初始化過程中完成的挠铲。
(2)分析構(gòu)造函數(shù)調(diào)?情況


在這里插入圖片描述

在這里插入圖片描述

通過如上觀察,我們發(fā)現(xiàn)構(gòu)造函數(shù)的調(diào)?時機(jī)在AbstractApplicationContext類refresh?法的
finishBeanFactoryInitialization(beanFactory)處;
(3)分析 InitializingBean 之 afterPropertiesSet 初始化?法調(diào)?情況

在這里插入圖片描述

觀察調(diào)?棧


在這里插入圖片描述

通過如上觀察寂诱,我們發(fā)現(xiàn) InitializingBean中afterPropertiesSet ?法的調(diào)?時機(jī)也是在
AbstractApplicationContext類refresh?法的finishBeanFactoryInitialization(beanFactory);
(4)分析BeanFactoryPostProcessor 初始化和調(diào)?情況
分別在構(gòu)造函數(shù)拂苹、postProcessBeanFactory ?法處打斷點(diǎn),觀察調(diào)?棧痰洒,發(fā)現(xiàn)
BeanFactoryPostProcessor 初始化在AbstractApplicationContext類refresh?法的
invokeBeanFactoryPostProcessors(beanFactory);
postProcessBeanFactory 調(diào)?在AbstractApplicationContext類refresh?法的
invokeBeanFactoryPostProcessors(beanFactory);
(5)分析 BeanPostProcessor 初始化和調(diào)?情況
分別在構(gòu)造函數(shù)瓢棒、postProcessBeanFactory ?法處打斷點(diǎn),觀察調(diào)?棧丘喻,發(fā)現(xiàn)
BeanPostProcessor 初始化在AbstractApplicationContext類refresh?法的
registerBeanPostProcessors(beanFactory);
postProcessBeforeInitialization 調(diào)?在AbstractApplicationContext類refresh?法的
finishBeanFactoryInitialization(beanFactory);
postProcessAfterInitialization 調(diào)?在AbstractApplicationContext類refresh?法的
finishBeanFactoryInitialization(beanFactory);
(6)總結(jié)
根據(jù)上?的調(diào)試分析脯宿,我們發(fā)現(xiàn) Bean對象創(chuàng)建的?個關(guān)鍵時機(jī)點(diǎn)代碼層級的調(diào)?都在
AbstractApplicationContext 類 的 refresh ?法中,可?這個?法對于Spring IoC 容器初始化來說相當(dāng)
關(guān)鍵仓犬,匯總?cè)缦拢?br>

在這里插入圖片描述

1.3 Spring IoC容器初始化主流程

由上分析可知嗅绰,Spring IoC 容器初始化的關(guān)鍵環(huán)節(jié)就在 AbstractApplicationContext#refresh() ?法中,我們查看 refresh ?法來俯瞰容器創(chuàng)建的主體流程,主體流程下的具體?流程我們后?再來討論窘面。

@Override
public void refresh() throws BeansException, IllegalStateException {
 synchronized (this.startupShutdownMonitor) {
 // 第?步:刷新前的預(yù)處理
 prepareRefresh();
 /*
 第?步:
 獲取BeanFactory翠语;默認(rèn)實(shí)現(xiàn)是DefaultListableBeanFactory
 加載BeanDefition 并注冊到 BeanDefitionRegistry
 */
 ConfigurableListableBeanFactory beanFactory =
obtainFreshBeanFactory();
 // 第三步:BeanFactory的預(yù)準(zhǔn)備?作(BeanFactory進(jìn)??些設(shè)置,?如context的類加
載器等)
 prepareBeanFactory(beanFactory);
 try {
 // 第四步:BeanFactory準(zhǔn)備?作完成后進(jìn)?的后置處理?作
 postProcessBeanFactory(beanFactory);
 // 第五步:實(shí)例化并調(diào)?實(shí)現(xiàn)了BeanFactoryPostProcessor接?的Bean
 invokeBeanFactoryPostProcessors(beanFactory);
 // 第六步:注冊BeanPostProcessor(Bean的后置處理器)财边,在創(chuàng)建bean的前后等執(zhí)
?
 registerBeanPostProcessors(beanFactory);
 // 第七步:初始化MessageSource組件(做國際化功能肌括;消息綁定,消息解析)酣难;
 initMessageSource();
 // 第?步:初始化事件派發(fā)器
 initApplicationEventMulticaster();
 // 第九步:?類重寫這個?法谍夭,在容器刷新的時候可以?定義邏輯
 onRefresh();
 // 第?步:注冊應(yīng)?的監(jiān)聽器。就是注冊實(shí)現(xiàn)了ApplicationListener接?的監(jiān)聽器
bean
 registerListeners();
 /*
 第??步:
 初始化所有剩下的?懶加載的單例bean
 初始化創(chuàng)建?懶加載?式的單例Bean實(shí)例(未設(shè)置屬性)
 填充屬性
 初始化?法調(diào)?(?如調(diào)?afterPropertiesSet?法憨募、init-method?法)
 調(diào)?BeanPostProcessor(后置處理器)對實(shí)例bean進(jìn)?后置處
 */
 finishBeanFactoryInitialization(beanFactory);
 /*
 第??步:
 完成context的刷新紧索。主要是調(diào)?LifecycleProcessor的onRefresh()?法,并且發(fā)布事
件 (ContextRefreshedEvent)
 */
 finishRefresh();
 }
  ......
 }
}

第2節(jié) BeanFactory創(chuàng)建流程

2.1 獲取BeanFactory?流程

時序圖如下


在這里插入圖片描述

2.2 BeanDefinition加載解析及注冊?流程

(1)該?流程涉及到如下?個關(guān)鍵步驟
Resource定位:指對BeanDefinition的資源定位過程菜谣。通俗講就是找到定義Javabean信息的XML?件珠漂,并將其封裝成Resource對象。
BeanDefinition載? :把?戶定義好的Javabean表示為IoC容器內(nèi)部的數(shù)據(jù)結(jié)構(gòu)尾膊,這個容器內(nèi)部的數(shù)據(jù)結(jié)構(gòu)就是BeanDefinition媳危。
注冊BeanDefinition到 IoC 容器
(2)過程分析
Step 1:?流程??在 AbstractRefreshableApplicationContext#refreshBeanFactory ?法中

在這里插入圖片描述

Step 2:依次調(diào)?多個類的 loadBeanDefinitions ?法 —> AbstractXmlApplicationContext —>AbstractBeanDefinitionReader —> XmlBeanDefinitionReader ?直執(zhí)?到XmlBeanDefinitionReader 的 doLoadBeanDefinitions ?法


在這里插入圖片描述

Step 3:我們重點(diǎn)觀察XmlBeanDefinitionReader 類的 registerBeanDefinitions ?法,期間產(chǎn)?了多次重載調(diào)?冈敛,我們定位到最后?個


在這里插入圖片描述

此處我們關(guān)注兩個地?:?個createRederContext?法待笑,?個是DefaultBeanDefinitionDocumentReader類的registerBeanDefinitions?法,先進(jìn)?createRederContext ?法看看


在這里插入圖片描述

我們可以看到抓谴,此處 Spring ?先完成了 NamespaceHandlerResolver 的初始化峦耘。
我們再進(jìn)? registerBeanDefinitions ?法中追蹤嘱巾,調(diào)?了
DefaultBeanDefinitionDocumentReader#registerBeanDefinitions ?法


在這里插入圖片描述

進(jìn)? doRegisterBeanDefinitions ?法


在這里插入圖片描述

進(jìn)? parseBeanDefinitions ?法


在這里插入圖片描述

進(jìn)? parseDefaultElement ?法


在這里插入圖片描述

進(jìn)? processBeanDefinition ?法


在這里插入圖片描述

?此湿镀,注冊流程結(jié)束憔四,我們發(fā)現(xiàn),所謂的注冊就是把封裝的 XML 中定義的 Bean信息封裝為
BeanDefinition 對象之后放??個Map中措拇,BeanFactory 是以 Map 的結(jié)構(gòu)組織這些 BeanDefinition的我纪。


在這里插入圖片描述

可以在DefaultListableBeanFactory中看到此Map的定義

/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new
ConcurrentHashMap<>(256);

(3)時序圖

在這里插入圖片描述

第3節(jié) Bean創(chuàng)建流程

  • 通過最開始的關(guān)鍵時機(jī)點(diǎn)分析,我們知道Bean創(chuàng)建?流程??在
    AbstractApplicationContext#refresh()?法的finishBeanFactoryInitialization(beanFactory) 處


    在這里插入圖片描述
  • 進(jìn)?finishBeanFactoryInitialization


    在這里插入圖片描述
  • 繼續(xù)進(jìn)?DefaultListableBeanFactory類的preInstantiateSingletons?法丐吓,我們找到下?部分的代碼浅悉,看到??Bean或者普通Bean,最終都是通過getBean的?法獲取實(shí)例


    在這里插入圖片描述
  • 繼續(xù)跟蹤下去券犁,我們進(jìn)?到了AbstractBeanFactory類的doGetBean?法术健,這個?法中的代碼很多,我們直接找到核?部分


    在這里插入圖片描述
  • 接著進(jìn)?到AbstractAutowireCapableBeanFactory類的?法粘衬,找到以下代碼部分


    在這里插入圖片描述
  • 進(jìn)?doCreateBean?法看看荞估,該?法我們關(guān)注兩塊重點(diǎn)區(qū)域

創(chuàng)建Bean實(shí)例咳促,此時尚未設(shè)置屬性


在這里插入圖片描述

給Bean填充屬性,調(diào)?初始化?法勘伺,應(yīng)?BeanPostProcessor后置處理器


在這里插入圖片描述

第4節(jié) lazy-init 延遲加載機(jī)制原理

  • lazy-init 延遲加載機(jī)制分析

普通 Bean 的初始化是在容器啟動初始化階段執(zhí)?的跪腹,?被lazy-init=true修飾的 bean 則是在從容器?第?次進(jìn)?context.getBean() 時進(jìn)?觸發(fā)。Spring 啟動的時候會把所有bean信息(包括XML和注解)解析轉(zhuǎn)化成Spring能夠識別的BeanDefinition并存到Hashmap?供下?的初始化時?飞醉,然后對每個BeanDefinition 進(jìn)?處理冲茸,如果是懶加載的則在容器初始化階段不處理,其他的則在容器初始化階段進(jìn)?初始化并依賴注?缅帘。

public void preInstantiateSingletons() throws BeansException {
 // 所有beanDefinition集合
 List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
 // 觸發(fā)所有?懶加載單例bean的初始化
 for (String beanName : beanNames) {
 // 獲取bean 定義
 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
 // 判斷是否是懶加載單例bean轴术,如果是單例的并且不是懶加載的則在容器創(chuàng)建時初始化
 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
 // 判斷是否是 FactoryBean
 if (isFactoryBean(beanName)) {
 final FactoryBean<?> factory = (FactoryBean<?>)
getBean(FACTORY_BEAN_PREFIX + beanName);
 boolean isEagerInit;
 if (System.getSecurityManager() != null && factory instanceof
SmartFactoryBean) {
 isEagerInit = AccessController.doPrivileged(new
PrivilegedAction<Boolean>() {
 @Override
 public Boolean run() {
 return ((SmartFactoryBean<?>) factory).isEagerInit();
 }
 }, getAccessControlContext());
 }
 }else {
 /*
 如果是普通bean則進(jìn)?初始化并依賴注?,此 getBean(beanName)接下來觸發(fā)的邏輯
和
 懶加載時 context.getBean("beanName") 所觸發(fā)的邏輯是?樣的
 */
 getBean(beanName);
 }
 }
 }
}
  • 總結(jié)

1.對于被修飾為lazy-init的bean Spring 容器初始化階段不會進(jìn)? init 并且依賴注?钦无,當(dāng)?shù)?次進(jìn)?getBean時候才進(jìn)?初始化并依賴注?
2.對于?懶加載的bean逗栽,getBean的時候會從緩存?頭獲取,因?yàn)槿萜鞒跏蓟A段 Bean 已經(jīng)初始化完成并緩存了起來

第5節(jié) Spring IoC循環(huán)依賴問題

5.1 什么是循環(huán)依賴

循環(huán)依賴其實(shí)就是循環(huán)引?铃诬,也就是兩個或者兩個以上的 Bean 互相持有對?祭陷,最終形成閉環(huán)。?如A依賴于B趣席,B依賴于C,C?依賴于A醇蝴。


在這里插入圖片描述

注意宣肚,這?不是函數(shù)的循環(huán)調(diào)?,是對象的相互依賴關(guān)系悠栓。循環(huán)調(diào)?其實(shí)就是?個死循環(huán)霉涨,除?有終結(jié)條件。

Spring中循環(huán)依賴場景有:

  • 構(gòu)造器的循環(huán)依賴(構(gòu)造器注?)
  • Field 屬性的循環(huán)依賴(set注?)

其中惭适,構(gòu)造器的循環(huán)依賴問題?法解決笙瑟,只能拋出 BeanCurrentlyInCreationException 異常,在解決屬性循環(huán)依賴時癞志,spring采?的是提前暴露對象的?法往枷。

5.2 循環(huán)依賴處理機(jī)制

  • 單例 bean 構(gòu)造器參數(shù)循環(huán)依賴(?法解決)
  • prototype 原型 bean循環(huán)依賴(?法解決)
    對于原型bean的初始化過程中不論是通過構(gòu)造器參數(shù)循環(huán)依賴還是通過setXxx?法產(chǎn)?循環(huán)依
    賴,Spring都 會直接報錯處理凄杯。

AbstractBeanFactory.doGetBean()?法:

if (isPrototypeCurrentlyInCreation(beanName)) {
 throw new BeanCurrentlyInCreationException(beanName);
}
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
 Object curVal = this.prototypesCurrentlyInCreation.get();
 return (curVal != null &&
 (curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>)
curVal).contains(beanName))));
}

在獲取bean之前如果這個原型bean正在被創(chuàng)建則直接拋出異常错洁。原型bean在創(chuàng)建之前會進(jìn)?標(biāo)記這個beanName正在被創(chuàng)建,等創(chuàng)建結(jié)束之后會刪除標(biāo)記

try {
 //創(chuàng)建原型bean之前添加標(biāo)記
 beforePrototypeCreation(beanName);
 //創(chuàng)建原型bean
 prototypeInstance = createBean(beanName, mbd, args);
}
finally {
 //創(chuàng)建原型bean之后刪除標(biāo)記
 afterPrototypeCreation(beanName);
}

總結(jié):Spring 不?持原型 bean 的循環(huán)依賴戒突。

  • 單例bean通過setXxx或者@Autowired進(jìn)?循環(huán)依賴
    Spring 的循環(huán)依賴的理論依據(jù)基于 Java 的引?傳遞屯碴,當(dāng)獲得對象的引?時,對象的屬性是可以延
    后設(shè)置的膊存,但是構(gòu)造器必須是在獲取引?之前

Spring通過setXxx或者@Autowired?法解決循環(huán)依賴其實(shí)是通過提前暴露?個ObjectFactory對象來完成的导而,簡單來說ClassA在調(diào)?構(gòu)造器完成對象初始化之后忱叭,在調(diào)?ClassA的setClassB?法之前就把ClassA實(shí)例化的對象通過ObjectFactory提前暴露到Spring容器中。

  • Spring容器初始化ClassA通過構(gòu)造器初始化對象后提前暴露到Spring容器今艺。
boolean earlySingletonExposure = (mbd.isSingleton() &&
this.allowCircularReferences &&
 isSingletonCurrentlyInCreation(beanName));
 if (earlySingletonExposure) {
 if (logger.isDebugEnabled()) {
 logger.debug("Eagerly caching bean '" + beanName +
 "' to allow for resolving potential circular references");
 }
 //將初始化后的對象提前已ObjectFactory對象注?到容器中
 addSingletonFactory(beanName, new ObjectFactory<Object>() {
 @Override
 public Object getObject() throws BeansException {
 return getEarlyBeanReference(beanName, mbd, bean);
 }
 });
 }
  • ClassA調(diào)?setClassB?法窑多,Spring?先嘗試從容器中獲取ClassB,此時ClassB不存在Spring容器中洼滚。

  • Spring容器初始化ClassB埂息,同時也會將ClassB提前暴露到Spring容器中

  • ClassB調(diào)?setClassA?法,Spring從容器中獲取ClassA 遥巴,因?yàn)榈?步中已經(jīng)提前暴露了ClassA千康,因此可以獲取到ClassA實(shí)例

  • ClassA通過spring容器獲取到ClassB,完成了對象初始化操作铲掐。

  • 這樣ClassA和ClassB都完成了對象初始化操作拾弃,解決了循環(huán)依賴問題。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末摆霉,一起剝皮案震驚了整個濱河市豪椿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌携栋,老刑警劉巖搭盾,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異婉支,居然都是意外死亡鸯隅,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進(jìn)店門向挖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蝌以,“玉大人,你說我怎么就攤上這事何之「” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵溶推,是天一觀的道長徊件。 經(jīng)常有香客問我,道長悼潭,這世上最難降的妖魔是什么庇忌? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮舰褪,結(jié)果婚禮上皆疹,老公的妹妹穿的比我還像新娘。我一直安慰自己占拍,他們只是感情好略就,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布捎迫。 她就那樣靜靜地躺著,像睡著了一般表牢。 火紅的嫁衣襯著肌膚如雪窄绒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天崔兴,我揣著相機(jī)與錄音彰导,去河邊找鬼。 笑死敲茄,一個胖子當(dāng)著我的面吹牛位谋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播堰燎,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼掏父,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了秆剪?” 一聲冷哼從身側(cè)響起赊淑,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎仅讽,沒想到半個月后陶缺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡何什,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年组哩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片处渣。...
    茶點(diǎn)故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蛛砰,靈堂內(nèi)的尸體忽然破棺而出罐栈,到底是詐尸還是另有隱情,我是刑警寧澤泥畅,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布荠诬,位于F島的核電站,受9級特大地震影響位仁,放射性物質(zhì)發(fā)生泄漏柑贞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一聂抢、第九天 我趴在偏房一處隱蔽的房頂上張望钧嘶。 院中可真熱鬧,春花似錦琳疏、人聲如沸有决。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽书幕。三九已至新荤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間台汇,已是汗流浹背苛骨。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留苟呐,地道東北人痒芝。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像掠抬,于是被迫代替她去往敵國和親吼野。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評論 2 355

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