Spring系列之Bean 生命周期分析

前言

Spring 很復(fù)雜因篇,很多東西都很難完全深入了解泞辐,這里寫下Bean 的初始化的分析笔横,主要是為了解SpringBoot 與Shiro 整合時(shí),引起的事務(wù)失敗問題咐吼,網(wǎng)上很多說是初始化順序引起沒有生成事務(wù)代理類而導(dǎo)致失敗吹缔。為了知其然知其所以然的原則,決定了解了解厢塘。

以下分析基于Spring 5.1.9.RELEASE、shiro1.4.0

一肌幽、Bean 初始化過程

1. Bean初始化入口:ApplicationContext

Application 繼承結(jié)構(gòu)圖


ApplicationContext-Level.png
ApplicationContext-Level.png

2. Bean 的生命周期圖示

bean_lifecycle.png
bean_lifecycle.png

生命周期相關(guān)步驟解析:

注意: Spring 只幫我們管理單例模式 Bean 的完整生命周期,對于 prototype 的 bean 喂急,Spring 在創(chuàng)建好交給使用者之后則不會再管理后續(xù)的生命周期。

  1. 通過構(gòu)造函數(shù)實(shí)例化Bean
  2. 依賴注入推薦使用setter 方法(主要注入方法:setter注入 煮岁、 constructor構(gòu)造器注入)
  3. 當(dāng)依賴注入完成讥蔽,以下接口方法將會回調(diào):BeanNameAware.setBeanName(String name);該方法是在Bean Factory 創(chuàng)建bean 時(shí)画机,設(shè)置Bean的名稱
  4. 然后調(diào)用: BeanClassLoaderAware.setBeanClassLoader(), 設(shè)置類加載器加載Bean 實(shí)例
  5. 然后調(diào)用: BeanFactoryAware.setBeanFactory(BeanFactory beanFactory) 步氏,為當(dāng)前的Bean 設(shè)置Bean Factory
  6. 容器調(diào)用: BeanPostProcessor.postProcessBeforeInitialization, 回調(diào)該方法荚醒,可將原始bean包裝成任意成對像返回
  7. 然后如果方法上有注解@PostConstruct 則會被調(diào)用(注意:這里需要開啟組件掃描芋类,以便對注解進(jìn)行處理)
  8. 在注解@PostConstruct 方法調(diào)用后,回調(diào)接口方法InitializingBean.afterPropertiesSet()
  9. 調(diào)用在xml 配置中bean 標(biāo)簽屬性init-method 定義的方法
  10. 然后調(diào)用 BeanPostProcessor.postProcessAfterInitialization()界阁, 調(diào)用該方法侯繁,用于包裝原始bean
  11. 到目前為止,bean已經(jīng)初始化贮竟,可以使用了
  12. 當(dāng)ApplicationContext 銷毀鉤子registerShutdownHook() 調(diào)用(調(diào)用后不是會立即銷毀), 有注解@PreDestroy 等銷毀方法會被調(diào)用
  13. 然后接著調(diào)用Bean 實(shí)現(xiàn)接口 DisposableBean.destroy() 方法
  14. 然后調(diào)用在xml 配置中bean 標(biāo)簽屬性 destroy-method 的方法
  15. 垃圾回收器會自動(dòng)調(diào)用Object 類的finalize() 方法銷毀對象

初始化回調(diào)的方法

  1. 接口InitializingBean 的afterPropertiesSet() 方法咕别,Spring 不推薦使用
  2. 注解@PostConstruct的方法
  3. xml配置中bean標(biāo)簽屬性 init-method 指定的方法 或 JavaConfig 注解@Bean 中屬性initMethod 指定的方法
  4. 如果以上上三種方法都使用了,則按以下順序執(zhí)行
  5. 先調(diào)用注解@PostConstruct的方法
  6. 再調(diào)用 接口InitializingBean 的afterPropertiesSet() 方法
  7. 然后才調(diào)用 xml 配置的 init-method 指定方法 或 Java配置中的initMethod 指定的方法

銷毀回調(diào)的方法

  1. 接口DisposableBean的 destroy()惰拱, Spring 不推薦使用
  2. 推薦使用 注解@PreDestroy標(biāo)識的方法 或 在xml 配置 bean 標(biāo)簽屬性destroy-method 定義的方法(Java 配置中,注解@Bean 屬性destroyMethod 定義的方法)
  3. 如果以上方法都配置偿短,則按以下順序執(zhí)行
  4. 注解@PreDestroy 標(biāo)識的方法先執(zhí)行
  5. 然后執(zhí)行在xml 配置 bean 標(biāo)簽屬性destroy-method 定義的方法(Java 配置中欣孤,注解@Bean 屬性destroyMethod 定義的方法)
  6. 最后執(zhí)行接口DisposableBean的 destroy()

二翔冀、例子

1. 創(chuàng)建Maven 項(xiàng)目

添加Spring 依賴

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
     <version>5.1.9.RELEASE</version>
</dependency>

2. 創(chuàng)建Student 類导街,并實(shí)現(xiàn)相關(guān)接口

public class Student implements InitializingBean, DisposableBean, 
                                    BeanFactoryAware, BeanNameAware {

    private String name;
    private Integer age;
    public Student() {
        System.out.println("初始化構(gòu)造函數(shù)");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @PostConstruct
    public void springPostConstruct() {
        System.out.println("---@PostConstruct--- 執(zhí)行");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("---InitializingBean.afterPropertiesSet---");
    }
    public void myInitMethod() {
        System.out.println("---init-method---");
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    @Override
    public void setBeanName(String name) {
        System.out.println("---BeanNameAware.setBeanName---");
    }
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("---BeanFactoryAware.setBeanFactory---");
    }
    @PreDestroy
    public void springPreDestroy(){
        System.out.println("-----@PreDestroy-----");
    }
    @Override
    public void destroy() throws Exception {
        System.out.println("-----DisposableBean.destroy()------");
    }
    public void myDestroyMethod(){
        System.out.println("---destroy-method---");
    }
}

3. 創(chuàng)建BeanPostProcessor 自定義實(shí)現(xiàn)類

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("BeanPostProcessor.postProcessAfterInitialization");
        return bean;
    }
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("BeanPostProcessor.postProcessBeforeInitialization");
        return bean;
    }
}

4. 使用xml配置Bean

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

    <!--組件掃描-->
    <context:component-scan base-package="cn.hdj"/>
    <!--配置bean,  加載的順序由上到下,先定義的Bean先初始化-->
    <bean id="student" class="cn.hdj.entity.Student" init-method="myInitMethod" destroy-method="myDestroyMethod"/>
    
    <bean id="myBeanPostProcessor" class="cn.hdj.MyBeanPostProcessor"/>
</beans>

5. 實(shí)例化上下文

public static void main(String[] args) {
    AbstractApplicationContext context = new ClassPathXmlApplicationContext("classpath:application-Context.xml");
    Student bean = context.getBean(Student.class);
    System.out.println(bean);
    context.registerShutdownHook();
}

6. 啟動(dòng)項(xiàng)目款票,輸出結(jié)果

初始化構(gòu)造函數(shù)
---BeanNameAware.setBeanName---
---BeanFactoryAware.setBeanFactory---
BeanPostProcessor.postProcessBeforeInitialization
---@PostConstruct--- 執(zhí)行
---InitializingBean.afterPropertiesSet---
---init-method---
BeanPostProcessor.postProcessAfterInitialization
Student{name='null', age=null}
-----@PreDestroy-----
-----DisposableBean.destroy()------
---destroy-method---

以上就是Bean 初始化的過程,如果說我們想要對Bean 初始化過程中艾少,對Bean 做一些處理,那么接下來我們需要了解一下缚够,Spring 為我們提供的擴(kuò)展點(diǎn)接口幔妨。

三谍椅、Aware 接口

*Aware 接口可以用于在初始化 bean 時(shí)獲得 Spring 中的一些對象,如獲取 Spring 上下文等雏吭。
以下為Spring 提供的*Aware接口

Aware 接口 實(shí)現(xiàn)的方法 作用(在Bean 構(gòu)造函數(shù)初始后回調(diào)锁施,但在初始化回調(diào)方法前調(diào)用)
ApplicationContextAware void setApplicationContext(ApplicationContext applicationContext) throws BeansException; Interface to be implemented by any object that wishes to be notified of the ApplicationContext that it runs in.
ApplicationEventPublisherAware void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher); Set the ApplicationEventPublisher that this object runs in.
BeanClassLoaderAware void setBeanClassLoader (ClassLoader classLoader); Callback that supplies the bean class loader to a bean instance.
BeanFactoryAware void setBeanFactory (BeanFactory beanFactory) throws BeansException; Callback that supplies the owning factory to a bean instance.
BeanNameAware void setBeanName(String name); Set the name of the bean in the bean factory that created this bean.
BootstrapContextAware void setBootstrapContext (BootstrapContext bootstrapContext); Set the BootstrapContext that this object runs in.
LoadTimeWeaverAware void setLoadTimeWeaver (LoadTimeWeaver loadTimeWeaver); Set the LoadTimeWeaver of this object’s containing ApplicationContext.
MessageSourceAware void setMessageSource (MessageSource messageSource); Set the MessageSource that this object runs in.
NotificationPublisherAware void setNotificationPublisher(NotificationPublisher notificationPublisher); Set the NotificationPublisher instance for the current managed resource instance.
PortletConfigAware void setPortletConfig (PortletConfig portletConfig); Set the PortletConfig this object runs in.
PortletContextAware void setPortletContext (PortletContext portletContext); Set the PortletContext that this object runs in.
ResourceLoaderAware void setResourceLoader (ResourceLoader resourceLoader); Set the ResourceLoader that this object runs in.
ServletConfigAware void setServletConfig (ServletConfig servletConfig); Set the ServletConfig that this object runs in.
ServletContextAware void setServletContext (ServletContext servletContext); Set the ServletContext that this object runs in.

四悉抵、增強(qiáng)處理器

種類

  1. BeanPostProcessor
  2. BeanFactoryPostProcessor (不在Bean 生命周期內(nèi))

增強(qiáng)處理器處理過程

bpp.png

增強(qiáng)處理器的特點(diǎn)

  • BeanFactoryPostProcessor是加載Bean定義后執(zhí)行
  • BeanPostProcessor 則是在Bean 初始化和依賴注入后執(zhí)行
  • 如果你在一個(gè)容器內(nèi)定義了增強(qiáng)處理器,它就只作用于這個(gè)容器內(nèi)的bean姥饰,即使其它容器與該容器有相同的層級關(guān)系
  • 想要控制多個(gè)處理器的處理順序,可以實(shí)現(xiàn)Order 接口來控制媳否,數(shù)值越小,優(yōu)先級越大

BeanFactoryPostProcessor的接口定義

public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory);
}

BeanPostProcessor 的接口定義

public interface BeanPostProcessor {
    //前置處理
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
    //后置處理
    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

BeanPostProcessor 的注冊過程荆秦?

//用于實(shí)例化和注冊BeanPostProcessor
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

public static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

        // Register BeanPostProcessorChecker that logs an info message when
        // a bean is created during BeanPostProcessor instantiation, i.e. when
        // a bean is not eligible for getting processed by all BeanPostProcessors.
        int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
        beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

        // 區(qū)分不同優(yōu)先級的BeanPostProcessor
        //優(yōu)先級分別有:PriorityOrdered,Ordered和其他的
        List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                //實(shí)現(xiàn)了接口PriorityOrdered的BeanPostProcessor
                //會優(yōu)先實(shí)例化
                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                priorityOrderedPostProcessors.add(pp);
                if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
                }
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // 首先對實(shí)現(xiàn)了接口 PriorityOrdered.的BeanPostProcessor進(jìn)行排序
        //然后注冊
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

        // 接著對實(shí)現(xiàn)了接口 Ordered.的BeanPostProcessor進(jìn)行排序
        //然后注冊
        List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
        for (String ppName : orderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            orderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, orderedPostProcessors);

        // 再接著對普通的BeanPostProcessor進(jìn)行排序
        //然后注冊
        List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
        for (String ppName : nonOrderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            nonOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

        //最后對內(nèi)部定義的BeanPostProcessor進(jìn)行排序掺逼,然后注冊
        sortPostProcessors(internalPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, internalPostProcessors);

        //重新注冊用于將內(nèi)部bean檢測為ApplicationListener的后處理器,
        //將其移到處理器鏈的末尾(for picking up proxies etc)吕喘。
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    }

BeanPostProcessor按優(yōu)先級分為PriorityOrdered赘那,Ordered和其他的氯质,對他們分別進(jìn)行以下操作募舟。

  • 先beanFactory.getBean進(jìn)行實(shí)例化闻察,
  • 再使用sortPostProcessors() 進(jìn)行排序
  • 最后registerBeanPostProcessors()進(jìn)行注冊拱礁。

所以辕漂,優(yōu)先級高Bpp的先被實(shí)例化呢灶,而優(yōu)先級低的Bpp在實(shí)例化時(shí)可以應(yīng)用優(yōu)先級高的(不過同級或優(yōu)先級低的不行钉嘹,因?yàn)檫€沒初始化)

那問題來了,BeanPostProcessor依賴的Bean, 導(dǎo)致其提前初始化跋涣,有什么后果缨睡?<br />根據(jù)BeanPostProcessor 的注冊過程陈辱,我們可以知道如果Bean 被優(yōu)先級高的Bpp依賴而導(dǎo)致提前初始化奖年,那么這個(gè)Bean 就不會在被其他優(yōu)先級低的Bpp處理(Bpp還沒初始化)性置; 例如典型的例子就是 auto-proxy拾并,因?yàn)?lt;br />AutowiredAnnotationBeanPostProcessor(用于處理依賴注入的Bpp)的優(yōu)先級是PriorityOrdered, 而AnnotationAwareAspectJAutoProxyCreator(用于 auto-proxy)的優(yōu)先級是Ordered嗅义, 如果Bean 在AnnotationAwareAspectJAutoProxyCreator注冊前實(shí)例化,那么這個(gè)Bean依賴注入時(shí)之碗,就不會以代理類(JDK代理或CGlib代理)的形式注入

解決的方法:  1. 對依賴的Bean 添加@Lazy(懶加載注解),2. 使用注解@DependsOn

五季希、Spring 整合Shiro 引起事務(wù)失敗問題解答

1.問題原因

  • 在DbShiroRealm 中注入U(xiǎn)serService時(shí),未加懶加載注解@Lazy 式塌,打印的Bean 實(shí)例化順序
image.png
image.png
  • Shiro 的配置
@Configuration
public class ShiroConfig {

    /**
     * 驗(yàn)證過濾器
     *
     * @return
     */
    @Bean
    public JwtAuthFilter jwtAuthFilter() {
        JwtAuthFilter authFilter = new JwtAuthFilter();
        return authFilter;
    }

    /**
     * 不加入Servlet Filter中
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(jwtAuthFilter());
        filterRegistrationBean.setEnabled(false);
        return filterRegistrationBean;
    }


    @Bean
    public Realm dbShiroRealm() {
        DbShiroRealm myShiroRealm = new DbShiroRealm();
        myShiroRealm.setCredentialsMatcher(new HashedCredentialsMatcher(Sha256Hash.ALGORITHM_NAME));
        return myShiroRealm;
    }

    @Bean
    public Realm jwtShiroRealm() {
        JwtShiroRealm myShiroRealm = new JwtShiroRealm();
        myShiroRealm.setCredentialsMatcher(new JwtCredentialsMatcher());
        return myShiroRealm;
    }


    /**
     * 關(guān)閉session
     *
     * @return
     */
    @Bean
    public SessionStorageEvaluator sessionStorageEvaluator() {
        DefaultWebSessionStorageEvaluator sessionStorageEvaluator = new DefaultWebSessionStorageEvaluator();
        sessionStorageEvaluator.setSessionStorageEnabled(false);
        return sessionStorageEvaluator;
    }

    /**
     * 驗(yàn)證器
     *
     * @return
     */
    @Bean
    public Authenticator authenticator() {
        MyModularRealmAuthenticator authenticator = new MyModularRealmAuthenticator();
        return authenticator;
    }

    /**
     * 設(shè)置過濾器鏈
     */
    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {

        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        //設(shè)置登陸的url
        factoryBean.setLoginUrl("/api/admin/user/signIn");


        factoryBean.setSecurityManager(securityManager);
        //設(shè)置過濾器
        Map<String, Filter> filters = factoryBean.getFilters();
        filters.put("authToken", jwtAuthFilter());
        factoryBean.setFilters(filters);


        // 自定義url規(guī)則使用LinkedHashMap有序Map
        Map<String, String> filterMap = new LinkedHashMap<>();
        // 兩個(gè)url規(guī)則都可以匹配同一個(gè)url,只執(zhí)行第一個(gè)
        filterMap.put("/api/admin/user/signIn", "anon");
        filterMap.put("/api/admin/**", "authToken");
        factoryBean.setFilterChainDefinitionMap(filterMap);
        return factoryBean;
    }
}

  • 說明
  1. ShiroFilterFactoryBean 是FactoryBean偏窝,且實(shí)現(xiàn)了BeanPostProcessor接口
  2. 在實(shí)例化時(shí),依賴securityManager
  3. 而SecurityManager 在Shiro自動(dòng)化配置中祭往,又依賴于Realm 類的
  4. 所以實(shí)例化的順序?yàn)椋篠hiroFilterFactoryBean > securityManager > dbShiroRealm > userServiceImpl
  5. 此時(shí)代理事務(wù)配置 ProxyTransactionManagementConfiguration還沒實(shí)例化

2.解決方法

  1. 采用懶加載的方式
    @Lazy
    @Autowired
    private UserService userService;    
  1. 使用注解@DependsOn

說明:
既然我們再創(chuàng)建dbShiroRealm時(shí)伦意,需要依賴注入userServiceImpl而且希望注入的是事務(wù)代理增強(qiáng)類硼补,但是事務(wù)代理增強(qiáng)的配置在 ProxyTransactionManagementConfiguration類中,那么我們在實(shí)例化dbShiroRealm時(shí)已骇,先讓配置類實(shí)例化离钝,這樣就可以享受到事務(wù)代理了疾捍。

//@DependsOn中的Bean 名稱可以在ProxyTransactionManagementConfiguration中找
@Bean
@DependsOn("org.springframework.transaction.config.internalTransactionAdvisor")
public Realm dbShiroRealm() {
    DbShiroRealm myShiroRealm = new DbShiroRealm();
    myShiroRealm.setCredentialsMatcher(new HashedCredentialsMatcher(Sha256Hash.ALGORITHM_NAME));
    return myShiroRealm;
}

六 奈辰、參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乱豆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子吊趾,更是在濱河造成了極大的恐慌,老刑警劉巖论泛,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異屁奏,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)坟瓢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來折联,“玉大人粒褒,你說我怎么就攤上這事诚镰∞确兀” “怎么了清笨?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長抠艾。 經(jīng)常有香客問我苛萎,道長,這世上最難降的妖魔是什么首懈? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮究履,結(jié)果婚禮上滤否,老公的妹妹穿的比我還像新娘最仑。我一直安慰自己藐俺,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布泥彤。 她就那樣靜靜地躺著,像睡著了一般吟吝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上剑逃,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天浙宜,我揣著相機(jī)與錄音蛹磺,去河邊找鬼粟瞬。 笑死萤捆,一個(gè)胖子當(dāng)著我的面吹牛裙品,可吹牛的內(nèi)容都是我干的市怎。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼焰轻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了昆雀?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤狞膘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后挽封,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體已球,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年智亮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阔蛉。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡弃舒,死狀恐怖状原,靈堂內(nèi)的尸體忽然破棺而出聋呢,到底是詐尸還是另有隱情颠区,我是刑警寧澤削锰,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布毕莱,位于F島的核電站器贩,受9級特大地震影響央串,放射性物質(zhì)發(fā)生泄漏磨澡。R本人自食惡果不足惜碗啄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望稚字。 院中可真熱鬧,春花似錦胆描、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽短绸。三九已至车吹,卻和暖如春醋闭,著一層夾襖步出監(jiān)牢的瞬間窄驹,已是汗流浹背证逻。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工乐埠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人丈咐。 一個(gè)月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓瑞眼,卻偏偏與公主長得像棵逊,于是被迫代替她去往敵國和親负拟。 傳聞我的和親對象是個(gè)殘疾皇子歹河,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

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