2. spring初級(jí)容器XmlBeanFactory初始化

一苇经、本文目錄

  1. spring的簡單使用方法
  2. spring初級(jí)容器XmlBeanFactory簡單介紹
  3. spring初級(jí)容器XmlBeanFactory初始化

二捎迫、spring的簡單使用

  1. 我們首先新建一個(gè)Student類,作為我們的示例bean
  2. spring的初衷,就是裝載一個(gè)一個(gè)的bean腻贰,這些bean迅腔,其實(shí)就是簡單的Java對(duì)象
public class Student {
    private String name="JHXY";

    private int age;
   // 省略getter牍帚、setter银伟、toString方法
  1. spring對(duì)應(yīng)的applicationContext.xml文件中配置student實(shí)例bean
<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"
       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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id="student" class="com.jhxy.common.Student"/>
</beans>
  1. 測試代碼
public static void main(String[] args) {
      
        XmlBeanFactory xmlBeanFactory =
                new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));

        // 從XmlBeanFactory即:spring容器中,獲取student bean
        Student student = (Student) xmlBeanFactory.getBean("student");

        System.out.println(student.getName());
    }
  1. 測試結(jié)果


    image.png
  2. XmlBeanFactory基本工作原理

  1. spring最基本的容器:XmlBeanFactory,我們熟知的ApplicationContent相當(dāng)于spring的高級(jí)容器
  2. ApplicationContenxt高級(jí)容器在XmlBeanFactory基礎(chǔ)上并徘,添加了很多擴(kuò)展功能和特性
  3. ClassPathResource封裝了applicationContext.xml文件,作為XmlBeanFactory構(gòu)造方法參數(shù)遣钳,創(chuàng)建XmlBeanFactory

三、spring初級(jí)容器XmlBeanFactory簡單介紹

  1. 通過下載Spring源碼,使用Intellij進(jìn)行代碼調(diào)試,我們已經(jīng)將spring的源碼下載到了本地麦乞,通過Intellij進(jìn)行源碼閱讀蕴茴,通過上面的簡單使用,我們知道,spring的初級(jí)容器XmlBeanFactory在初始化的時(shí)候姐直,其實(shí)就是通過簡單的new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));創(chuàng)建spring的初級(jí)容器
  2. 首先倦淀,我們來看下構(gòu)造函數(shù)的參數(shù),ClassPathResource對(duì)應(yīng)的Resource是什么
  3. 我們先來看下ClassPathResource對(duì)應(yīng)的類繼承關(guān)系


    Resource類繼承圖
  4. 我們可以看到
  1. ClassPathResource實(shí)現(xiàn)了Resource接口
  2. Resource接口繼承了InputStreamSource
  3. 和ClassPathResource相似的還有InputStreamResource,ByteArrayResource,FileSystemResource
  1. 其實(shí)spring將所有的資源都抽象成一個(gè)InputStreamSource,這樣声畏,不同的來源使用不同的實(shí)現(xiàn)類撞叽。
  2. Resource 接口中的方法


    Resource接口中的方法
  1. exists():對(duì)資源狀態(tài)的判斷,資源是否存在
  2. isReadable():對(duì)資源狀態(tài)的判斷插龄,是否是可讀狀態(tài)
  3. isOpen():對(duì)資源狀態(tài)的判斷愿棋,資源是否打開狀態(tài)
  4. isFile():對(duì)資源狀態(tài)的判斷,判斷是否是文件類型
  1. 通過類繼承圖可以知道均牢,Resource接口繼承了InputStreamSource糠雨,這就意味著所有的資源只要封裝了Resource接口,就可以通過調(diào)用InputStreamSource的getInputStream方法來獲取資源對(duì)應(yīng)的InputStream輸入流了
  2. 而資源是多種多樣的膨处,我們平時(shí)項(xiàng)目中的applicationContext.xml其實(shí)就是項(xiàng)目的classpath下的xml,ClassPathResource就是用來加載classpath路徑下的資源文件
  3. 所以见秤,各種Resource是如何加載資源的,我們通過示例中的ClassPathResource的getInputStream方法可以看出,ClasspathResource就是通過class或者classLoader的底層方法來加載的
/**
     * This implementation opens an InputStream for the given class path resource.
     * @see java.lang.ClassLoader#getResourceAsStream(String)
     * @see java.lang.Class#getResourceAsStream(String)
     */
    @Override
    public InputStream getInputStream() throws IOException {
        InputStream is;
        if (this.clazz != null) {
            is = this.clazz.getResourceAsStream(this.path);
        }
        else if (this.classLoader != null) {
            is = this.classLoader.getResourceAsStream(this.path);
        }
        else {
            is = ClassLoader.getSystemResourceAsStream(this.path);
        }
        if (is == null) {
            throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
        }
        return is;
    }
  1. 綜上真椿,我們可以得出結(jié)論:Resource就是spring內(nèi)部資源的一個(gè)抽象,而InputStreamResource的接口實(shí)現(xiàn)乎澄,使我們對(duì)各種來源的資源都可以輕松的獲取對(duì)應(yīng)的輸入流InputStream

四突硝、spring初級(jí)容器XmlBeanFactory的初始化

  1. 我們知道,創(chuàng)建spring初級(jí)容器XmlBeanFactory置济,通過XmlBeanFactory構(gòu)造函數(shù)直接創(chuàng)建解恰,先來看下XmlBeanFactory的構(gòu)造函數(shù)
public class XmlBeanFactory extends DefaultListableBeanFactory {

    //XmlBeanDefinitionReader用于讀取資源的reader組件
    private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);


    /**
     * Create a new XmlBeanFactory with the given resource,
     * which must be parsable using DOM.
     * @param resource the XML resource to load bean definitions from
     * @throws BeansException in case of loading or parsing errors
     */
    public XmlBeanFactory(Resource resource) throws BeansException {
        this(resource, null);
    }

    /**
     * Create a new XmlBeanFactory with the given input stream,
     * which must be parsable using DOM.
     * @param resource the XML resource to load bean definitions from
     * @param parentBeanFactory parent bean factory
     * @throws BeansException in case of loading or parsing errors
     */
    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
//我們再去父類的構(gòu)造方法中看看锋八,構(gòu)造方法中實(shí)現(xiàn)了哪些功能
        super(parentBeanFactory);
        //通過 XmlBeanDefinitionReader進(jìn)行加載資源
        this.reader.loadBeanDefinitions(resource);
    }

}
  1. XmlBeanFactory構(gòu)造函數(shù)中,首先要調(diào)用父類的構(gòu)造方法护盈,我們一路走下去挟纱,最終走到AbstractAutowireCapableBeanFactory中
  1. 在AbstractAutowireCapableBeanFactory中,ignoreDependencyInterface方法設(shè)置了一些類腐宋,分別是BeanNameAware紊服、BeanFactoryAware、BeanClassLoaderAware
    2.ignoreDependencyInterface方法胸竞,就是將參數(shù)中的類添加到集合ignoredDependencyInterfaces中
public AbstractAutowireCapableBeanFactory() {
        super();
        ignoreDependencyInterface(BeanNameAware.class);
        ignoreDependencyInterface(BeanFactoryAware.class);
        ignoreDependencyInterface(BeanClassLoaderAware.class);
    }
  1. 我們再來看下這三個(gè)感知接口的類繼承關(guān)系圖


    感知接口Aware類繼承圖
  2. 通過接口名字Aware欺嗤,應(yīng)該能猜到,這些都是感知相關(guān)的接口卫枝,當(dāng)bean實(shí)現(xiàn)了這些接口煎饼,在spring實(shí)例化bean的時(shí)候,就可以通過感知接口中的方法注入相應(yīng)的數(shù)據(jù)
  3. 我們首先通過一個(gè)例子來看下校赤,BeanNameAware的作用
public class Student implements BeanNameAware{
    private String name="JHXY";
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("beanName:" + name);
    }
}

applicationContext和之前的配置一樣吆玖,測試代碼

 public static void main(String[] args) {
        XmlBeanFactory xmlBeanFactory =
                new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
        // 從XmlBeanFactory即:spring容器中,獲取student bean
        Student student = (Student) xmlBeanFactory.getBean("student");
        System.out.println(student.getName());
    }

測試結(jié)果


BeanNameAware感知接口測試結(jié)果
  1. 通過測試結(jié)果可以看到马篮,BeanNameAware中的setBeanName方法被調(diào)用衰伯,并且bean name就是我們在zpplicationContext中配置的Student 的id的屬性值,student
  2. 那現(xiàn)在有個(gè)疑問积蔚,為什么Student實(shí)現(xiàn)了BeanNameAware接口之后意鲸,setBeanName方法就會(huì)被調(diào)用?setBeanName什么時(shí)候被調(diào)用尽爆,調(diào)用之后為什么就能拿到beanName怎顾?不著急,我們繼續(xù)看
  3. ignoreDependencyInterface方法是干什么的漱贱?通過注釋我們可以知道,在自動(dòng)裝配的時(shí)候槐雾,忽略指定的接口依賴
   /**
     * Ignore the given dependency interface for autowiring.
     * <p>This will typically be used by application contexts to register
     * dependencies that are resolved in other ways, like BeanFactory through
     * BeanFactoryAware or ApplicationContext through ApplicationContextAware.
     * <p>By default, only the BeanFactoryAware interface is ignored.
     * For further types to ignore, invoke this method for each type.
     * @see org.springframework.beans.factory.BeanFactoryAware
     * @see org.springframework.context.ApplicationContextAware
     */
      public void ignoreDependencyInterface(Class<?> ifc) {
        this.ignoredDependencyInterfaces.add(ifc);
    }
  1. 我們順藤摸瓜,看看ignoredDependencyInterfaces集合在哪里被調(diào)用幅狮,如下代碼

根據(jù)注釋募强,一個(gè)bean的屬性,是否要從依賴排查中剔除崇摄,這句話什么意思呢擎值?

也就是說,我們一個(gè)bean的某個(gè)屬性逐抑,是否要被注入對(duì)應(yīng)的依賴鸠儿,還要看一下你這個(gè)屬性對(duì)應(yīng)的類是否實(shí)現(xiàn)了BeanNameAware、BeanFactoryAware、BeanClassLoaderAware這些接口

/**
     * Determine whether the given bean property is excluded from dependency checks.
     * <p>This implementation excludes properties defined by CGLIB and
     * properties whose type matches an ignored dependency type or which
     * are defined by an ignored dependency interface.
     * @param pd the PropertyDescriptor of the bean property
     * @return whether the bean property is excluded
     * @see #ignoreDependencyType(Class)
     * @see #ignoreDependencyInterface(Class)
     */
    protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
        return (AutowireUtils.isExcludedFromDependencyCheck(pd) ||
                this.ignoredDependencyTypes.contains(pd.getPropertyType()) ||
                AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces));
    }

我們繼續(xù)向下看AutowireUtils.isSetterDefinedInInterface()

在isSetterDefinedInInterface方法中

1.bean對(duì)應(yīng)的屬性进每,是否實(shí)現(xiàn)了BeanNameAware汹粤、BeanFactoryAware、BeanClassLoaderAware
2.bean屬性對(duì)應(yīng)的setter方法田晚,在這三個(gè)感知接口中是否也有相同的方法
如果滿足以上兩種情況嘱兼,isSetterDefinedInInterface就會(huì)返回true,spring在自動(dòng)裝配這個(gè)bean時(shí),就不會(huì)為這個(gè)屬性注入值


image.png
  1. 我們還是通過一個(gè)案例來看下
public class BeanNameAwareTest implements BeanNameAware {
    private String beanName;
    public String getBeanName() {
        return beanName;
    }
    @Override
    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }
}

我們將屬性設(shè)置為beanName,且該類實(shí)現(xiàn)了BeanNameAware接口贤徒,這樣芹壕,setBeanName方法即是beanName的setter方法,且在感知接口中也有setBeanName方法
滿足了這兩個(gè)條件之后泞莉,spring就不會(huì)為bean beanNameAwareTest的屬性beanName注入任何值

<?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:context="http://www.springframework.org/schema/context"
       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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

   <bean id="beanNameAwareTest" class="org.springframework.jhxy.BeanNameAwareTest">
        <property name="beanName" value="beanName"/>
    </bean>
</beans>

我們?yōu)閷傩詁eanName設(shè)置了屬性值“beanName”,我們通過測試結(jié)果來看下“beanName”這個(gè)值能否注入到bean beanNameAwareTest對(duì)應(yīng)的beanName屬性中

public static void main(String[] args) {

        XmlBeanFactory xmlBeanFactory =
                new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
        BeanNameAwareTest beanNameAwareTest = (BeanNameAwareTest) xmlBeanFactory.getBean("beanNameAwareTest");
        System.out.println(beanNameAwareTest.getBeanName());
    }

測試結(jié)果
可以看到哪雕,我們設(shè)置的beanName的屬性并沒有變成"beanName",拿到的依舊是beanNameAwareTest鲫趁,所以說斯嚎,如果一個(gè)bean實(shí)現(xiàn)了BeanNameAware、BeanFactoryAware挨厚、BeanClassLoaderAware的話堡僻,并且想通過spring自動(dòng)裝配給屬性賦值,那么屬性的setter方法疫剃,就不能和感知接口中的setter方法相同钉疫。
spring這樣設(shè)計(jì),主要是想巢价,如果實(shí)現(xiàn)了BeanNameAware,對(duì)應(yīng)的beanName屬性值,就應(yīng)該是這個(gè)bean在spring容器中的名字牲阁,此時(shí),如果我們從外部xml或者注解中壤躲,注入一個(gè)新的bean的名稱城菊,spring默認(rèn)就會(huì)忽略掉外部注入的名稱,確保bean的名稱唯一


image.png

OK
我們接著向下看初始化spring容器的邏輯

  1. XmlBeanDefinitionReader如何加載資源,這里我們可以看到碉克,會(huì)將Resource封裝成EncodedResource
/**
     * Load bean definitions from the specified XML file.
     * @param resource the resource descriptor for the XML file
     * @return the number of bean definitions found
     * @throws BeanDefinitionStoreException in case of loading or parsing errors
     */
    @Override
    public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
        //將Resource封裝太EncodedResource
        return loadBeanDefinitions(new EncodedResource(resource));
    }
  1. 我們看下EncodedResource部分關(guān)鍵源碼
public class EncodedResource implements InputStreamSource {

    //這里的resource是跟資源有關(guān)的
    private final Resource resource;
    //編碼
    @Nullable
    private final String encoding;
    //字符集
    @Nullable
    private final Charset charset;


    /**
     * Create a new {@code EncodedResource} for the given {@code Resource},
     * not specifying an explicit encoding or {@code Charset}.
     * @param resource the {@code Resource} to hold (never {@code null})
     */
    //構(gòu)造方法中凌唬,除了資源resource不為空,編碼和字符集都為空
    public EncodedResource(Resource resource) {
        this(resource, null, null);
    }
/**
     * Open a {@code java.io.Reader} for the specified resource, using the specified
     * {@link #getCharset() Charset} or {@linkplain #getEncoding() encoding}
     * (if any).
     * @throws IOException if opening the Reader failed
     * @see #requiresReader()
     * @see #getInputStream()
     */
    //通過上面的構(gòu)造方法可知漏麦,默認(rèn)charset和encoding為null客税,所以getReader(),根據(jù)資源獲取resource的輸入流
    public Reader getReader() throws IOException {
        if (this.charset != null) {
            return new InputStreamReader(this.resource.getInputStream(), this.charset);
        }
        else if (this.encoding != null) {
            return new InputStreamReader(this.resource.getInputStream(), this.encoding);
        }
        else {
            return new InputStreamReader(this.resource.getInputStream());
        }
    }
// 省略部分代碼.....
  1. 接著loadBeanDefinitions繼續(xù)向下看
/**
     * Load bean definitions from the specified XML file.
     * @param encodedResource the resource descriptor for the XML file,
     * allowing to specify an encoding to use for parsing the file
     * @return the number of bean definitions found
     * @throws BeanDefinitionStoreException in case of loading or parsing errors
     */
    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        Assert.notNull(encodedResource, "EncodedResource must not be null");
        if (logger.isTraceEnabled()) {
            logger.trace("Loading XML bean definitions from " + encodedResource);
        }

        Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();

        if (!currentResources.add(encodedResource)) {
            throw new BeanDefinitionStoreException(
                    "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
        }

        //獲取EncodedResource的輸入流
        try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            //正式開始加載資源
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException(
                    "IOException parsing XML document from " + encodedResource.getResource(), ex);
        }
        finally {
            currentResources.remove(encodedResource);
            if (currentResources.isEmpty()) {
                this.resourcesCurrentlyBeingLoaded.remove();
            }
        }
    }

/**
     * Actually load bean definitions from the specified XML file.
     * @param inputSource the SAX InputSource to read from
     * @param resource the resource descriptor for the XML file
     * @return the number of bean definitions found
     * @throws BeanDefinitionStoreException in case of loading or parsing errors
     * @see #doLoadDocument
     * @see #registerBeanDefinitions
     */
    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {

        try {
            //將傳進(jìn)來的inputSource和resource,封裝成Document對(duì)象
            Document doc = doLoadDocument(inputSource, resource);
            //解析document對(duì)象撕贞,并將解析的bean注入到spring中
            int count = registerBeanDefinitions(doc, resource);
            if (logger.isDebugEnabled()) {
                logger.debug("Loaded " + count + " bean definitions from " + resource);
            }
            return count;
        }
        catch (BeanDefinitionStoreException ex) {
            throw ex;
        }
        catch (SAXParseException ex) {
            throw new XmlBeanDefinitionStoreException(resource.getDescription(),
                    "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
        }
        catch (SAXException ex) {
            throw new XmlBeanDefinitionStoreException(resource.getDescription(),
                    "XML document from " + resource + " is invalid", ex);
        }
        catch (ParserConfigurationException ex) {
            throw new BeanDefinitionStoreException(resource.getDescription(),
                    "Parser configuration exception parsing XML from " + resource, ex);
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException(resource.getDescription(),
                    "IOException parsing XML document from " + resource, ex);
        }
        catch (Throwable ex) {
            throw new BeanDefinitionStoreException(resource.getDescription(),
                    "Unexpected exception parsing XML document from " + resource, ex);
        }
    }

/**
     * Actually load the specified document using the configured DocumentLoader.
     * @param inputSource the SAX InputSource to read from
     * @param resource the resource descriptor for the XML file
     * @return the DOM Document
     * @throws Exception when thrown from the DocumentLoader
     * @see #setDocumentLoader
     * @see DocumentLoader#loadDocument
     */
    protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
        return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
                getValidationModeForResource(resource), isNamespaceAware());
    }

spring在加載的過程中更耻,將XmlBeanDefinitionReader委托給DocumentLoader進(jìn)行加載
加載xml時(shí),將會(huì)按照xml規(guī)范和格式進(jìn)行加載xml中 的bean

結(jié)尾

  1. 受限于篇幅問題麻掸,我們下一篇筆記接著學(xué)習(xí)spring加載XmlBeadFactory


    02_spring基礎(chǔ)數(shù)據(jù)準(zhǔn)備.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末酥夭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子脊奋,更是在濱河造成了極大的恐慌熬北,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,744評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诚隙,死亡現(xiàn)場離奇詭異讶隐,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)久又,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門巫延,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人地消,你說我怎么就攤上這事炉峰。” “怎么了脉执?”我有些...
    開封第一講書人閱讀 163,105評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵疼阔,是天一觀的道長。 經(jīng)常有香客問我半夷,道長婆廊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,242評(píng)論 1 292
  • 正文 為了忘掉前任巫橄,我火速辦了婚禮淘邻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘湘换。我一直安慰自己宾舅,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評(píng)論 6 389
  • 文/花漫 我一把揭開白布彩倚。 她就那樣靜靜地躺著筹我,像睡著了一般。 火紅的嫁衣襯著肌膚如雪署恍。 梳的紋絲不亂的頭發(fā)上崎溃,一...
    開封第一講書人閱讀 51,215評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音盯质,去河邊找鬼袁串。 笑死,一個(gè)胖子當(dāng)著我的面吹牛呼巷,可吹牛的內(nèi)容都是我干的囱修。 我是一名探鬼主播,決...
    沈念sama閱讀 40,096評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼王悍,長吁一口氣:“原來是場噩夢啊……” “哼破镰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤鲜漩,失蹤者是張志新(化名)和其女友劉穎源譬,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體孕似,經(jīng)...
    沈念sama閱讀 45,354評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡踩娘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了喉祭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片养渴。...
    茶點(diǎn)故事閱讀 39,745評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖泛烙,靈堂內(nèi)的尸體忽然破棺而出理卑,到底是詐尸還是另有隱情,我是刑警寧澤蔽氨,帶...
    沈念sama閱讀 35,448評(píng)論 5 344
  • 正文 年R本政府宣布藐唠,位于F島的核電站,受9級(jí)特大地震影響孵滞,放射性物質(zhì)發(fā)生泄漏中捆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評(píng)論 3 327
  • 文/蒙蒙 一坊饶、第九天 我趴在偏房一處隱蔽的房頂上張望泄伪。 院中可真熱鬧,春花似錦匿级、人聲如沸蟋滴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽津函。三九已至,卻和暖如春孤页,著一層夾襖步出監(jiān)牢的瞬間尔苦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評(píng)論 1 269
  • 我被黑心中介騙來泰國打工行施, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留允坚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,776評(píng)論 2 369
  • 正文 我出身青樓蛾号,卻偏偏與公主長得像稠项,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鲜结,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評(píng)論 2 354

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