Spring中涉及的設(shè)計模式總結(jié)

Spring中涉及的設(shè)計模式總結(jié)

1.簡單工廠(非23種設(shè)計模式中的一種)

  • 實現(xiàn)方式:BeanFactory隆夯。Spring中的BeanFactory就是簡單工廠模式的體現(xiàn)插爹,根據(jù)傳入一個唯一的標識來獲得Bean對象,但是否是在傳入?yún)?shù)后創(chuàng)建還是傳入?yún)?shù)前創(chuàng)建這個要根據(jù)具體情況來定吐根。

  • 實質(zhì):由一個工廠類根據(jù)傳入的參數(shù)正歼,動態(tài)決定應該創(chuàng)建哪一個產(chǎn)品類。

  • 實現(xiàn)原理:

    • bean容器的啟動階段:

      • 讀取bean的xml配置文件,將bean元素分別轉(zhuǎn)換成一個BeanDefinition對象拷橘。

      • 然后通過BeanDefinitionRegistry將這些bean注冊到beanFactory中局义,保存在一個名為beanDefinitionMap的ConcurrentHashMap中。

      • 將BeanDefinition注冊到了beanFactory之后冗疮,在這里Spring為我們提供了一個擴展的切口萄唇,允許我們通過實現(xiàn)接口BeanFactoryPostProcessor 在此處來插入我們定義的代碼。典型的例子就是:PropertyPlaceholderConfigurer术幔,我們一般在配置數(shù)據(jù)庫的dataSource時使用到的占位符的值另萤,就是它注入進去的。

    • 容器中bean的實例化階段:

  • 實例化階段主要是通過反射或者CGLIB對bean進行實例化诅挑,在這個階段Spring又給我們暴露了很多的擴展點:

      • 各種的Aware接口四敞,比如 BeanFactoryAware,對于實現(xiàn)了這些Aware接口的bean拔妥,在實例化bean時Spring會幫我們注入對應的BeanFactory的實例忿危。

      • BeanPostProcessor接口,實現(xiàn)了BeanPostProcessor接口的bean没龙,在實例化bean時Spring會幫我們調(diào)用接口中的方法铺厨。

      • InitializingBean接口,實現(xiàn)了InitializingBean接口的bean兜畸,在實例化bean時Spring會幫我們調(diào)用接口中的方法努释。

      • DisposableBean接口,實現(xiàn)了BeanPostProcessor接口的bean咬摇,在該bean死亡時Spring會幫我們調(diào)用接口中的方法伐蒂。

  • 設(shè)計意義:

    • 松耦合倒脓≈豆簦可以將原來硬編碼的依賴,通過Spring這個beanFactory這個工長來注入依賴,也就是說原來只有依賴方和被依賴方咖驮,現(xiàn)在我們引入了第三方——spring這個beanFactory,由它來解決bean之間的依賴問題笼痛,達到了松耦合的效果.

    • bean的額外處理捞奕。通過Spring接口的暴露,在實例化bean的階段我們可以進行一些額外的處理桥狡,這些額外的處理只需要讓bean實現(xiàn)對應的接口即可搅裙,那么spring就會在bean的生命周期調(diào)用我們實現(xiàn)的接口來處理該bean。[非常重要]

2.工廠方法

  • 實現(xiàn)方式:FactoryBean接口裹芝。

  • 實現(xiàn)原理:實現(xiàn)了FactoryBean接口的bean是一類叫做factory的bean部逮。其特點是,spring會在使用getBean()調(diào)用獲得該bean時嫂易,會自動調(diào)用該bean的getObject()方法兄朋,所以返回的不是factory這個bean,而是這個bean.getOjbect()方法的返回值怜械。

  • 例子:

    • 典型的例子有spring與mybatis的結(jié)合颅和。

    • 代碼示例

圖片
  • 說明:我們看上面該bean,因為實現(xiàn)了FactoryBean接口缕允,所以返回的不是 SqlSessionFactoryBean 的實例峡扩,而是她的 SqlSessionFactoryBean.getObject() 的返回值。

3.單例模式

  • Spring依賴注入Bean實例默認是單例的障本。

  • Spring的依賴注入(包括lazy-init方式)都是發(fā)生在AbstractBeanFactory的getBean里有额。getBean的doGetBean方法調(diào)用getSingleton進行bean的創(chuàng)建。

  • 分析getSingleton()方法

    <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n352" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit;">public Object getSingleton(String beanName){
    //參數(shù)true設(shè)置標識允許早期依賴
    return getSingleton(beanName,true);
    }
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //檢查緩存中是否存在實例
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    //如果為空彼绷,則鎖定全局變量并進行處理巍佑。
    synchronized (this.singletonObjects) {
    //如果此bean正在加載,則不處理
    singletonObject = this.earlySingletonObjects.get(beanName);
    if (singletonObject == null && allowEarlyReference) {
    //當某些方法需要提前初始化的時候則會調(diào)用addSingleFactory 方法將對應的ObjectFactory初始化策略存儲在singletonFactories
    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
    if (singletonFactory != null) {
    //調(diào)用預先設(shè)定的getObject方法
    singletonObject = singletonFactory.getObject();
    //記錄在緩存中寄悯,earlysingletonObjects和singletonFactories互斥
    this.earlySingletonObjects.put(beanName, singletonObject);
    this.singletonFactories.remove(beanName);
    }
    }
    }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }</pre>

  • getSingleton()過程圖 ps:spring依賴注入時萤衰,使用了 雙重判斷加鎖 的單例模式

圖片
    • 總結(jié)

    • 單例模式定義:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點猜旬。

    • spring對單例的實現(xiàn):spring中的單例模式完成了后半句話脆栋,即提供了全局的訪問點BeanFactory。但沒有從構(gòu)造器級別去控制單例洒擦,這是因為spring管理的是任意的java對象椿争。

4. 適配器模式

  • 實現(xiàn)方式:SpringMVC中的適配器HandlerAdatper。

  • 實現(xiàn)原理:HandlerAdatper根據(jù)Handler規(guī)則執(zhí)行不同的Handler熟嫩。

  • 實現(xiàn)過程:DispatcherServlet根據(jù)HandlerMapping返回的handler秦踪,向HandlerAdatper發(fā)起請求,處理Handler。HandlerAdapter根據(jù)規(guī)則找到對應的Handler并讓其執(zhí)行椅邓,執(zhí)行完畢后Handler會向HandlerAdapter返回一個ModelAndView柠逞,最后由HandlerAdapter向DispatchServelet返回一個ModelAndView。

  • 實現(xiàn)意義:HandlerAdatper使得Handler的擴展變得容易景馁,只需要增加一個新的Handler和一個對應的HandlerAdapter即可板壮。因此Spring定義了一個適配接口,使得每一種Controller有一種對應的適配器實現(xiàn)類合住,讓適配器代替controller執(zhí)行相應的方法绰精。這樣在擴展Controller時,只需要增加一個適配器類就完成了SpringMVC的擴展了透葛。

5.裝飾器模式

  • 實現(xiàn)方式:Spring中用到的包裝器模式在類名上有兩種表現(xiàn):一種是類名中含有Wrapper茬底,另一種是類名中含有Decorator。

  • 實質(zhì):

    • 動態(tài)地給一個對象添加一些額外的職責获洲。

    • 就增加功能來說,Decorator模式相比生成子類更為靈活殿如。

6.代理模式

  • 實現(xiàn)方式:AOP底層贡珊,就是動態(tài)代理模式的實現(xiàn)。

    • 動態(tài)代理:在內(nèi)存中構(gòu)建的涉馁,不需要手動編寫代理類

    • 靜態(tài)代理:需要手工編寫代理類门岔,代理類引用被代理對象。

  • 實現(xiàn)原理:切面在應用運行的時刻被織入烤送。一般情況下寒随,在織入切面時,AOP容器會為目標對象創(chuàng)建動態(tài)的創(chuàng)建一個代理對象帮坚。SpringAOP就是以這種方式織入切面的妻往。 織入:把切面應用到目標對象并創(chuàng)建新的代理對象的過程。

7.觀察者模式

  • 實現(xiàn)方式:spring的事件驅(qū)動模型使用的是 觀察者模式 试和,Spring中Observer模式常用的地方是listener的實現(xiàn)讯泣。

  • 具體實現(xiàn): 事件機制的實現(xiàn)需要三個部分,事件源,事件,事件監(jiān)聽器

    • ApplicationEvent抽象類**事件**

      • 繼承自jdk的EventObject,所有的事件都需要繼承ApplicationEvent,并且通過構(gòu)造器參數(shù)source得到事件源.

      • 該類的實現(xiàn)類ApplicationContextEvent表示ApplicaitonContext的容器事件.

      • 代碼:

        <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n418" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit;">public abstract class ApplicationEvent extends EventObject {
        private static final long serialVersionUID = 7099057708183571937L;
        private final long timestamp;
        public ApplicationEvent(Object source) {
        super(source);
        this.timestamp = System.currentTimeMillis();
        }
        public final long getTimestamp() {
        return this.timestamp;
        }
        }</pre>

    • ApplicationListener接口事件監(jiān)聽器

      • 繼承自jdk的EventListener,所有的監(jiān)聽器都要實現(xiàn)這個接口。

      • 這個接口只有一個onApplicationEvent()方法,該方法接受一個ApplicationEvent或其子類對象作為參數(shù),在方法體中,可以通過不同對Event類的判斷來進行相應的處理阅悍。

      • 當事件觸發(fā)時所有的監(jiān)聽器都會收到消息好渠。

      • 代碼:

        <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n433" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit;"> public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
        void onApplicationEvent(E event);
        } </pre>

    • ApplicationContext接口事件源****

      • ApplicationContext是spring中的全局容器,翻譯過來是”應用上下文”。

      • 實現(xiàn)了ApplicationEventPublisher接口节视。

      • 職責:負責讀取bean的配置文檔,管理bean的加載,維護bean之間的依賴關(guān)系,可以說是負責bean的整個生命周期,再通俗一點就是我們平時所說的IOC容器拳锚。

      • 代碼:

        <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n450" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit;">public interface ApplicationEventPublisher {
        void publishEvent(ApplicationEvent event);
        }
        ?
        public void publishEvent(ApplicationEvent event) {
        Assert.notNull(event, "Event must not be null");
        if (logger.isTraceEnabled()) {
        logger.trace("Publishing event in " + getDisplayName() + ": " + event);
        }
        getApplicationEventMulticaster().multicastEvent(event);
        if (this.parent != null) {
        this.parent.publishEvent(event);
        }
        }</pre>

    • ApplicationEventMulticaster抽象類事件源中publishEvent方法需要調(diào)用其方法getApplicationEventMulticaster

      • 屬于事件廣播器,它的作用是把Applicationcontext發(fā)布的Event廣播給所有的監(jiān)聽器.

      • 代碼

        <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n459" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit;">public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext, DisposableBean {
        private ApplicationEventMulticaster applicationEventMulticaster;
        protected void registerListeners() {
        // Register statically specified listeners first.
        for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
        }
        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let post-processors apply to them!
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String lisName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(lisName);
        }
        }
        }</pre>

8.策略模式

  • 實現(xiàn)方式:Spring框架的資源訪問Resource接口 。該接口提供了更強的資源訪問能力寻行,Spring 框架本身大量使用了 Resource 接口來訪問底層資源霍掺。

  • Resource 接口介紹

    • source 接口是具體資源訪問策略的抽象,也是所有資源訪問類所實現(xiàn)的接口。

    • Resource 接口主要提供了如下幾個方法:

      • getInputStream():定位并打開資源抗楔,返回資源對應的輸入流棋凳。每次調(diào)用都返回新的輸入流。調(diào)用者必須負責關(guān)閉輸入流连躏。

      • exists():返回 Resource 所指向的資源是否存在剩岳。

      • isOpen():返回資源文件是否打開,如果資源文件不能多次讀取入热,每次讀取結(jié)束應該顯式關(guān)閉拍棕,以防止資源泄漏。

      • getDescription():返回資源的描述信息勺良,通常用于資源處理出錯時輸出該信息绰播,通常是全限定文件名或?qū)嶋H URL。

      • getFile:返回資源對應的 File 對象尚困。

      • getURL:返回資源對應的 URL 對象蠢箩。 最后兩個方法通常無須使用,僅在通過簡單方式訪問無法實現(xiàn)時事甜,Resource 提供傳統(tǒng)的資源訪問的功能谬泌。

    • Resource 接口本身沒有提供訪問任何底層資源的實現(xiàn)邏輯,針對不同的底層資源逻谦,Spring 將會提供不同的 Resource 實現(xiàn)類掌实,不同的實現(xiàn)類負責不同的資源訪問邏輯。

    • Spring 為 Resource 接口提供了如下實現(xiàn)類:

      • UrlResource:訪問網(wǎng)絡(luò)資源的實現(xiàn)類邦马。

      • ClassPathResource:訪問類加載路徑里資源的實現(xiàn)類贱鼻。

      • FileSystemResource:訪問文件系統(tǒng)里資源的實現(xiàn)類。

      • ServletContextResource:訪問相對于 ServletContext 路徑里的資源的實現(xiàn)類.

      • InputStreamResource:訪問輸入流資源的實現(xiàn)類滋将。

      • ByteArrayResource:訪問字節(jié)數(shù)組資源的實現(xiàn)類邻悬。 這些 Resource 實現(xiàn)類,針對不同的的底層資源随闽,提供了相應的資源訪問邏輯拘悦,并提供便捷的包裝,以利于客戶端程序的資源訪問橱脸。

9.模版方法模式

  • 經(jīng)典模板方法定義:

    • 父類定義了骨架(調(diào)用哪些方法及順序)础米,某些特定方法由子類實現(xiàn)

    • 最大的好處:代碼復用,減少重復代碼添诉。除了子類要實現(xiàn)的特定方法屁桑,其他方法及方法調(diào)用順序都在父類中預先寫好了。

    • 所以父類模板方法中有兩類方法:

      • 共同的方法:所有子類都會用到的代碼

      • 不同的方法:子類要覆蓋的方法栏赴,分為兩種:

        • 抽象方法:父類中的是抽象方法蘑斧,子類必須覆蓋

        • 鉤子方法:父類中是一個空方法,子類繼承了默認也是空的 注:為什么叫鉤子,子類可以通過這個鉤子(方法)竖瘾,控制父類沟突,因為這個鉤子實際是父類的方法(空方法)!

  • Spring模板方法模式實質(zhì): 是模板方法模式和回調(diào)模式的結(jié)合捕传,是Template Method不需要繼承的另一種實現(xiàn)方式惠拭。Spring幾乎所有的外接擴展都采用這種模式。

  • 具體實現(xiàn):JDBC的抽象和對Hibernate的集成庸论,都采用了一種理念或者處理方式职辅,那就是模板方法模式與相應的Callback接口相結(jié)合。

  • 采用模板方法模式是為了以一種統(tǒng)一而集中的方式來處理資源的獲取和釋放聂示,以JdbcTempalte為例:

    <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n536" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit;">public abstract class JdbcTemplate {
    public final Object execute(String sql){
    Connection con=null;
    Statement stmt=null;
    try{
    con=getConnection();
    stmt=con.createStatement();
    Object retValue=executeWithStatement(stmt,sql);
    return retValue;
    }catch(SQLException e){
    ...
    }finally{
    closeStatement(stmt);
    releaseConnection(con);
    }
    }
    protected abstract Object executeWithStatement(Statement stmt, String sql);
    } </pre>

  • 引入回調(diào)原因:

    • JdbcTemplate是抽象類域携,不能夠獨立使用,我們每次進行數(shù)據(jù)訪問的時候都要給出一個相應的子類實現(xiàn),這樣肯定不方便鱼喉,所以就引入了回調(diào) 秀鞭。

    • 回調(diào)代碼

      <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n545" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit;">public interface StatementCallback{
      Object doWithStatement(Statement stmt);
      } </pre>

    • 利用回調(diào)方法重寫JdbcTemplate方法

      <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n548" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit;">public class JdbcTemplate {
      public final Object execute(StatementCallback callback){
      Connection con=null;
      Statement stmt=null;
      try{
      con=getConnection();
      stmt=con.createStatement();
      Object retValue=callback.doWithStatement(stmt);
      return retValue;
      }catch(SQLException e){
      ...
      }finally{
      closeStatement(stmt);
      releaseConnection(con);
      }
      }
      ?
      ...//其它方法定義
      } </pre>

    • Jdbc使用方法如下:

      <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n551" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit;">JdbcTemplate jdbcTemplate=...;
      final String sql=...;
      StatementCallback callback=new StatementCallback(){
      public Object=doWithStatement(Statement stmt){
      return ...;
      }
      }
      jdbcTemplate.execute(callback); </pre>

  • 為什么JdbcTemplate沒有使用繼承?因為這個類的方法太多扛禽,但是我們還是想用到JdbcTemplate已有的穩(wěn)定的锋边、公用的數(shù)據(jù)庫連接,那么我們怎么辦呢旋圆?我們可以把變化的東西抽出來作為一個參數(shù)傳入JdbcTemplate的方法中。但是變化的東西是一段代碼麸恍,而且這段代碼會用到JdbcTemplate中的變量灵巧。怎么辦?那我們就用回調(diào)對象吧抹沪。在這個回調(diào)對象中定義一個操縱JdbcTemplate中變量的方法刻肄,我們?nèi)崿F(xiàn)這個方法,就把變化的東西集中到這里了融欧。然后我們再傳入這個回調(diào)對象到JdbcTemplate敏弃,從而完成了調(diào)用。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末噪馏,一起剝皮案震驚了整個濱河市麦到,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌欠肾,老刑警劉巖瓶颠,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異刺桃,居然都是意外死亡粹淋,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來桃移,“玉大人屋匕,你說我怎么就攤上這事〗杞埽” “怎么了过吻?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長第步。 經(jīng)常有香客問我疮装,道長,這世上最難降的妖魔是什么粘都? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任廓推,我火速辦了婚禮,結(jié)果婚禮上翩隧,老公的妹妹穿的比我還像新娘樊展。我一直安慰自己,他們只是感情好堆生,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布专缠。 她就那樣靜靜地躺著,像睡著了一般淑仆。 火紅的嫁衣襯著肌膚如雪涝婉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天蔗怠,我揣著相機與錄音墩弯,去河邊找鬼。 笑死寞射,一個胖子當著我的面吹牛渔工,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播桥温,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼引矩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了侵浸?” 一聲冷哼從身側(cè)響起旺韭,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎掏觉,沒想到半個月后茂翔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡履腋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年珊燎,在試婚紗的時候發(fā)現(xiàn)自己被綠了惭嚣。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡悔政,死狀恐怖晚吞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谋国,我是刑警寧澤槽地,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站芦瘾,受9級特大地震影響捌蚊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜近弟,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一缅糟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧祷愉,春花似錦窗宦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至订讼,卻和暖如春髓窜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背欺殿。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工寄纵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人祈餐。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓擂啥,卻偏偏與公主長得像哄陶,于是被迫代替她去往敵國和親帆阳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

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