spring容器加载分析 二容器刷新

容器刷新是容器加载的核心方法,包括:BeanFactory的设置、Configuration类解析、Bean实例化、属性和依赖注入、事件监听器注册。都是由此方法展开的。

本着先理解脉络在搞懂细节的原则,为不干扰对容器刷新过程理解,对Configuration类解析部分和Bean实例化部分只做了总结性说明,后续会专门分析。

容器刷新方法在AbstractApplicationContext类中实现,所以不管是ClassPathXmlApplicationContext、AnnotationConfigApplicationContext、 AnnotationConfigWebApplicationContext等各种具体的容器都是这个方法。

容器刷新方法:

public void refresh() throws BeansException, IllegalStateException {
    // refresh过程只能一个线程处理,不允许并发执行。
    synchronized (this.startupShutdownMonitor) {
        prepareRefresh();// step 1
        // 获取BeanFactory,容器初始化的时候已实例化
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        prepareBeanFactory(beanFactory); // step 2
        try {
            postProcessBeanFactory(beanFactory); // step 3
            invokeBeanFactoryPostProcessors(beanFactory); // step 4
            registerBeanPostProcessors(beanFactory);// step 5
            initMessageSource();// step 6
            initApplicationEventMulticaster();// step 7
            onRefresh();// step8
            registerListeners();// step 9
            finishBeanFactoryInitialization(beanFactory);// step 10
            finishRefresh();// step 11
        } catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }
            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();
            // Reset 'active' flag.
            cancelRefresh(ex);
            // Propagate exception to caller.
            throw ex;
        } finally {
            resetCommonCaches();
        }
    }
}

step 1 prepareRefresh()
在刷新容器操作之前做些准备的工作,包括:

1、设置Spring容器的启动时间,撤销关闭状态,开启活跃状态。

2、初始化属性源信息(Property)。

3、验证环境信息里一些必须存在的属性。

代码较为简单没贴源码,请自行查看。

step 2 prepareBeanFactory()
beanFactory预处理

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 设置beanFactory的ClassLoader为当前的ClassLoader
    beanFactory.setBeanClassLoader(getClassLoader());
    // 设置表达式解析器(解析bean定义中的一些表达式)
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    // 添加属性编辑注册器(注册属性编辑器),属性编辑器实际上是属性的类型转换器,
    // 因为bean的属性配置都是字符串类型的 实例化的时候要将这些属性转换为实际类型 
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    // 添加BeanPostProcessor(Bean后置处理器):ApplicationContextAwareProcessor
    // 在BEAN初始化之前,调用ApplicationContextAwareProcessor的postProcessBeforeInitialization
    // 处理所有的Aware接口,进行如下操作:
    // 如果bean实现了EnvironmentAware接口,调用bean.setEnvironment
    // 如果bean实现了EmbeddedValueResolverAware接口,调用bean.setEmbeddedValueResolver
    // 如果bean实现了ResourceLoaderAware接口,调用bean.setResourceLoader
    // 如果bean实现了ApplicationEventPublisherAware接口,调用bean.setApplicationEventPublisher
    // 如果bean实现了MessageSourceAware接口,调用bean.setMessageSource
    // 如果bean实现了ApplicationContextAware接口,调用bean.setApplicationContext
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 取消ResourceLoaderAware
    // 、ApplicationEventPublisherAware
    // 、MessageSourceAware
    // 、ApplicationContextAware
    // 、EnvironmentAware这5个接口的自动注入
    // 因为ApplicationContextAwareProcessor把这5个接口的实现工作做了
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    // 设置几个自动装配的特殊规则
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    // 添加BeanPostProcessor(后置处理器):ApplicationListenerDetector
    // 在Bean初始化后检查是否实现了ApplicationListener接口,
    // 是则加入当前的applicationContext的applicationListeners列表
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
    // 检查容器中是否包含名称为loadTimeWeaver的bean,实际上是增加Aspectj的支持
    // AspectJ采用编译期织入、类加载期织入两种方式进行切面的织入
    // 类加载期织入简称为LTW(Load Time Weaving),通过特殊的类加载器来代理JVM默认的类加载器实现
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        // 添加BEAN后置处理器:LoadTimeWeaverAwareProcessor
        // 在BEAN初始化之前检查BEAN是否实现了LoadTimeWeaverAware接口,
        // 如果是,则进行加载时织入,即静态代理。
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        // Set a temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
    // Register default environment beans.
    // 注入一些其它信息的bean,比如environment、systemProperties等
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

对beanFactory进行了如下操作:

1、设置了ClassLoader

2、设置了表达式解析器

3、设置了属性编辑器

4、添加了一个BeanPostProcessor实现:ApplicationContextAwareProcessor,它是用来处理并回调实现了各种Aware接口的Bean,比如获取ApplicationContext的ApplicationContextAware接口。

5、取消了一个工作接口,添加了一些特殊的Bean

6、添加BeanPostProcessor实现:ApplicationListenerDetector,它是用来将实现了ApplicationListener接口的Bean添加到容器的监听器列表。

7、如果beanFactory中包含名称为loadTimeWeaver的Bean,则添加BeanPostProcessor实现:LoadTimeWeaverAwareProcessor,它是用来处理AspectJ类加载期织入LTW(Load Time Weaving)的。

8、注入environment、systemProperties、systemEnvironment三个Bean

step 3 postProcessBeanFactory()

beanFactory后置处理,是一个模板方法,交由不同的ApplicationContext实现自己处理逻辑,做一些特有的操作。
比如GenericWebApplicationContext容器会在BeanFactory中添加ServletContextAwareProcessor用于处理ServletContextAware类型的bean初始化的时候调用setServletContext或者setServletConfig方法。

step 4 invokeBeanFactoryPostProcessors()
调用BeanFactoryPostProcessor

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 调用BeanFactoryPostProcessors
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    // 再次检查使用存在LoadTimeWeaverBean,如果进行LWT的处理
    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

getBeanFactoryPostProcessors()是获取直接添加到容器中的BeanFactoryPostProcessor,如下面这样添加的:

public static void main(String[] args) {
    AnnotationConfigApplicationContext context 
        = new AnnotationConfigApplicationContext(StartupConfig.class);
    context.addBeanFactoryPostProcessor(new TestBeanFactoryPostProcessor());
}

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()方法中的处理逻辑是,查找到容器中注册的BeanFactoryPostProcessors连同直接添加的BeanFactoryPostProcessors进行排序,排序的依据的@Order注解,然后依次调用,限于篇幅没贴源码,请自行查看。

在容器初始化时注册到容器中注册的ConfigurationClassPostProcessor会被排到最前面,它的作用是解析包含JavaConfig注解的类或者被@Configuration注解的类,称之为配置类ConfigurationClass。
一些BeanFactoryPostProcessor实例是通过ConfigurationClass注册的,如果不优先执行ConfigurationClassPostProcessor这些Processor实例就不会被注册到容器,也就得不到执行。
ConfigurationClassPostProcessor中使用ConfigurationClassParser来解析ConfigurationClass中的配置,解析的过程:
1、处理@PropertySources注解,解析属性文件
2、处理@ComponentScan注解,通过ComponentScanAnnotationParser扫描Bean定义
3、处理@Import注解,递归解析Import进来的Bean定义
4、处理@Bean注解,获取被@Bean注解修饰的方法,然后添加到配置类的beanMethods属性中
解析完毕使用ClassBeanDefinitionReader来注册解析出来的BeanDefinition。
因为解析过程复杂,为了不影响对容器刷新过程脉络的理解,没有在此分析,详细解析和注册过程请参见:spring容器加载分析 三Configuration类解析

step 5 registerBeanPostProcessors()
注册BeanPostProcessor,从Spring容器中找出的实现了BeanPostProcessor接口的Bean,并设置到BeanFactory中,之后bean被实例化的时候会调用这些BeanPostProcessor。

public static void registerBeanPostProcessors(
        ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    //从beng工厂中找出所有BeanPostProcessor类型的实例
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    // BeanPostProcessorChecker是一个普通的打印信息
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

    // Separate between BeanPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
    List<String> orderedPostProcessorNames = new ArrayList<String>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    for (String ppName : postProcessorNames) {
        //先找出实现了PriorityOrdered接口的BeanPostProcessor并排序后加到BeanFactory的BeanPostProcessor集合中
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        //找出实现了Ordered接口的BeanPostProcessor并排序后加到BeanFactory的BeanPostProcessor集合中
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }
    // 第一步, 注册所有实现了PriorityOrdered接口的BeanPostProcessor
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
    // 第二部, 注册所有实现了Ordered接口的BeanPostProcessor
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
    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);
    // 第三步, 注册所有无序的BeanPostProcessors.
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    // 第四步, 注册所有MergedBeanDefinitionPostProcessor类型的BeanPostProcessors.
    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);
    // 添加ApplicationListener探测器
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

step 6 initMessageSource()
初始化国际化(I18N)信息

step 7 initApplicationEventMulticaster();
初始化Spring事件广播器用于事件的发布,这个事件广播器允许用户自己定义。

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 如果有用户自定义的事件广播器(名称为:applicationEventMulticaster的bean)
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
                beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isDebugEnabled()) {
            logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    }
    // 如果有用户没有自定义的事件广播器(名称为:applicationEventMulticaster的bean),
    // 使用系统默认的SimpleApplicationEventMulticaster
    else {
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                    APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                    "': using default [" + this.applicationEventMulticaster + "]");
        }
    }
}

通常情况很少有用户自定义事件广播的,SimpleApplicationEventMulticaster的核心功能是根据事件和事件类型从容器中找出符合的事件监听器,依次调用。

@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        Executor executor = getTaskExecutor();
        if (executor != null) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    invokeListener(listener, event);
                }
            });
        }
        else {
            invokeListener(listener, event);
        }
    }
}

step 8 onRefresh()
这是一个模板方法,交由不同的子类实现处理自己的逻辑。比如web程序的容器AnnotationConfigEmbeddedWebApplicationContext中会调用createEmbeddedServletContainer方法去创建内置的Servlet容器。

step 9 registerListeners()
注册事件监听器,把直接添加到容器内的事件监听器和beanFactory中的事件监听器都添加的事件广播器ApplicationEventMulticaster中。

protected void registerListeners() {
    // 直接添加到容器中的事件监听器
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }
    // 从beanFactory中获取所有实现了ApplicationListener接口的事件监听器
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }
    // 如果存在earlyApplicationEvents,直接广播出去
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

step 10 finishBeanFactoryInitialization()
初始化非延迟加载的单例Bean, 实例化BeanFactory中已经被注册但是未实例化的所有实例(@Lazy注解的Bean不在此实例化)。
invokeBeanFactoryPostProcessors方法中根据各种注解解析出来的类,在这个时候都会被初始化。实例化的过程各种BeanPostProcessor开始起作用。
实例化的过程也是巨复杂的过程,为了不影响对容器刷新过程脉络的理解,没有在此分析,详细解析和注册过程请参见:spring容器加载分析 四Bean实例化

step 11 finishRefresh()
refresh结束之前需要做善后工作。包括生命周期组件LifecycleProcessor的初始化和调用、事件发布、JMX组件的处理等。

protected void finishRefresh() {
    // Initialize lifecycle processor for this context.
    initLifecycleProcessor();
    // Propagate refresh to lifecycle processor first.
    getLifecycleProcessor().onRefresh();
    // Publish the final event.
    publishEvent(new ContextRefreshedEvent(this));
    // Participate in LiveBeansView MBean, if active.
    LiveBeansView.registerApplicationContext(this);
}

1、initLifecycleProcessor()
初始化容器的LifecycleProcessor。
Lifecycle接口为Bean提供了生命周期的回调方法,会在ApplicationContext启动(start)和停止(stop)的时候通知Bean做出响应。
它有两个扩展接口LifecycleProcessor和SmartLifecycle,LifecycleProcessor增加了onRefresh和onClose另个方法分别对应ApplicationContext的刷新和关闭。
而SmartLifecycle接口可以通过getPhase()方法来控制Bean启动和销毁的顺序,getPhase返回的数字越小则Bean启动的越早销毁的越晚,getPhase返回的数字越大则Bean启动的越晚销毁的越早。
容器中对Lifecycle接口的处理是委托给LifecycleProcessor实现的,通常都是DefaultLifecycleProcessor ,LifecycleProcessor初始化过程:

protected void initLifecycleProcessor() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 如果beanFactory包含名称为lifecycleProcessor的Bean,直接获取
    if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
        this.lifecycleProcessor =
                beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
    }
    else {// 使用默认的lifecycleProcessor
        DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
        defaultProcessor.setBeanFactory(beanFactory);
        this.lifecycleProcessor = defaultProcessor;
        beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
    }
}

2、getLifecycleProcessor().onRefresh()
DefaultLifecycleProcessor 会从beanFactory中查找所有实现了LifecycleProcessor接口的Bean,然后一次调用其onRefresh方法。
3、publishEvent(new ContextRefreshedEvent(this))
广播ContextRefreshedEvent事件,通过事件广播器ApplicationEventMulticaster向所有监听了ContextRefreshedEvent事件的监听器进行通知。
4、LiveBeansView.registerApplicationContext(this)
向MBeanServer注册LiveBeansView,可以通过JMX来监控此ApplicationContext。

至此容器就已经全部加载完毕,进入工作状态。

码字不易,转载请保留原文连接https://www.jianshu.com/p/5836d3d6dc72

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