spring-beans深入源碼之BeanPostProcessors(含循環(huán)依賴的解決方式)

BeanPostProcessor

public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(
                  Object bean, String beanName) throws BeansException;
      Object postProcessAfterInitialization(
                  Object bean, String beanName) throws BeansException;

BeanPostProcessor 接口定義bean初始化時(shí)的回調(diào)贾费,我們可以實(shí)現(xiàn)自己的邏輯依賴解析等。我們可以自己實(shí)現(xiàn)該接口從而在spring的容器完成初始化配置也可以實(shí)現(xiàn)類似plugin的方式上岗。我們可以定義多個(gè)類實(shí)現(xiàn)該接口江滨,然后定義一下執(zhí)行的優(yōu)先級(jí) spring文檔中叫order,這樣就會(huì)按我們?cè)O(shè)定的order執(zhí)行你定義的多個(gè)類。
ApplicationContext 可以自動(dòng)檢測(cè)到任何實(shí)現(xiàn)了BeanPostProcessor接口的bean和注冊(cè)這些bean作為post-processors梅肤。在bean創(chuàng)建的過程中調(diào)用。
在<em>spring-beans module</em>中有<em>FactoryBeanTests</em>這個(gè)類邑茄,找到第七個(gè)測(cè)試方法<b>testFactoryBeansWithIntermediateFactoryBeanAutowiringFailure</b>

@Test
    public void testCircularReferenceWithPostProcessor() {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        new XmlBeanDefinitionReader(factory).loadBeanDefinitions(CIRCULAR_CONTEXT);

        CountingPostProcessor counter = new CountingPostProcessor();
        factory.addBeanPostProcessor(counter);

        BeanImpl1 impl1 = factory.getBean(BeanImpl1.class);
        assertNotNull(impl1);
        assertNotNull(impl1.getImpl2());
        assertNotNull(impl1.getImpl2());
        assertSame(impl1, impl1.getImpl2().getImpl1());
        assertEquals(1, counter.getCount("bean1"));
        assertEquals(1, counter.getCount("bean2"));
    }

該方法讀取的是

FactoryBeanTests-circular.xml

<i>CountingPostProcessor</i>實(shí)現(xiàn)了<i>BeanPostProcessor</i>接口姨蝴,我們?cè)谄渲械膬蓚€(gè)方法中加上日志

public static class CountingPostProcessor implements BeanPostProcessor {

        private final Map<String, AtomicInteger> count = new HashMap<String, AtomicInteger>();

        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) {
            System.out.println("源碼閱讀debug postProcessBeforeInitialization:"+bean);
            return bean;
        }

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) {
            System.out.println("源碼閱讀debug postProcessAfterInitialization:"+bean);
            if (bean instanceof FactoryBean) {
                return bean;
            }
            AtomicInteger c = count.get(beanName);
            if (c == null) {
                c = new AtomicInteger(0);
                count.put(beanName, c);
            }
            c.incrementAndGet();
            return bean;
        }

        public int getCount(String beanName) {
            AtomicInteger c = count.get(beanName);
            if (c != null) {
                return c.intValue();
            }
            else {
                return 0;
            }
        }
    }

我們找到<em>FactoryBeanTests-circular.xml</em>查看其內(nèi)容

<?xml version="1.0" encoding="ISO-8859-1"?>
<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
                       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="bean1" class="org.springframework.beans.factory.FactoryBeanTests$PassThroughFactoryBean" primary="true">
      <constructor-arg value="org.springframework.beans.factory.FactoryBeanTests$BeanImpl1"/>
      <property name="instanceName" value="beanImpl1"/>
   </bean>

   <bean id="beanImpl1" class="org.springframework.beans.factory.FactoryBeanTests$BeanImpl1">
      <property name="impl2" ref="bean2"/>
   </bean>

   <bean id="bean2" class="org.springframework.beans.factory.FactoryBeanTests$PassThroughFactoryBean" primary="true">
      <constructor-arg value="org.springframework.beans.factory.FactoryBeanTests$BeanImpl2"/>
      <property name="instanceName" value="beanImpl2"/>
   </bean>

   <bean id="beanImpl2" class="org.springframework.beans.factory.FactoryBeanTests$BeanImpl2">
      <property name="impl1" ref="bean1"/>
   </bean>

</beans>

其中的兩個(gè)bean比較簡單

public static class BeanImpl1 {

        private BeanImpl2 impl2;

        public BeanImpl2 getImpl2() {
            return impl2;
        }

        public void setImpl2(BeanImpl2 impl2) {
            this.impl2 = impl2;
        }
    }


    public static class BeanImpl2 {

        private BeanImpl1 impl1;

        public BeanImpl1 getImpl1() {
            return impl1;
        }

        public void setImpl1(BeanImpl1 impl1) {
            this.impl1 = impl1;
        }
    }

<b>但是注意</b>這兩個(gè)bean存在循環(huán)依賴關(guān)系 這個(gè)待會(huì)再說,先看CountingPostProcessor implements BeanPostProcessor 的兩個(gè)方法的執(zhí)行情況肺缕,跑一下junit測(cè)試 debug

debug-loadbean

在load的時(shí)候會(huì)解析xml并實(shí)例化bean 實(shí)例化得過程會(huì)調(diào)用到這兩個(gè)方法

debug-postProcessAfterInitialization

跑完看一下consle打印的日志
對(duì)了先說一下怎么開啟spring源碼的日志
其實(shí)很簡單


log4j.png
# Set root logger level to Debug and its only appender to A1
log4j.rootLogger=ALL,A1
log4j.category.org.springframework=DEBUG

# A1 is set to be ConsoleAppender
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p [%t] - %m%n




其中l(wèi)og4j配置下一篇再補(bǔ)充一下
ALL是最小的 就是所有有關(guān)的日志都會(huì)打印左医,設(shè)置成<b>ALL</b>即可

log4j-all.png

還有一步要做就是加入編譯環(huán)境
項(xiàng)目右鍵<b>Build path</b>

config-buildpath.png

這樣就可以打日志了
看一下剛剛debug輸出的日志

2016-08-30 15:16:16 DEBUG [main] - Adding [systemProperties] PropertySource with lowest search precedence
2016-08-30 15:16:16 DEBUG [main] - Adding [systemEnvironment] PropertySource with lowest search precedence
2016-08-30 15:16:16 DEBUG [main] - Initialized StandardEnvironment with PropertySources [systemProperties,systemEnvironment]
2016-08-30 15:16:16 INFO [main] - Loading XML bean definitions from class path resource [org/springframework/beans/factory/FactoryBeanTests-circular.xml]
2016-08-30 15:16:16 DEBUG [main] - Using JAXP provider [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl]
2016-08-30 15:16:16 DEBUG [main] - Loading schema mappings from [META-INF/spring.schemas]
2016-08-30 15:16:16 DEBUG [main] - Loaded schema mappings: {http://www.springframework.org/schema/beans/spring-beans-4.2.xsd=org/springframework/beans/factory/xml/spring-beans-4.2.xsd, http://www.springframework.org/schema/beans/spring-beans-3.2.xsd=org/springframework/beans/factory/xml/spring-beans-3.2.xsd, http://www.springframework.org/schema/util/spring-util-3.0.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd, http://www.springframework.org/schema/util/spring-util-4.1.xsd=org/springframework/beans/factory/xml/spring-util-4.1.xsd, http://www.springframework.org/schema/util/spring-util-2.0.xsd=org/springframework/beans/factory/xml/spring-util-2.0.xsd, http://www.springframework.org/schema/util/spring-util-2.5.xsd=org/springframework/beans/factory/xml/spring-util-2.5.xsd, http://www.springframework.org/schema/tool/spring-tool-3.0.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd, http://www.springframework.org/schema/tool/spring-tool-4.1.xsd=org/springframework/beans/factory/xml/spring-tool-4.1.xsd, http://www.springframework.org/schema/tool/spring-tool-2.0.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd, http://www.springframework.org/schema/util/spring-util-3.2.xsd=org/springframework/beans/factory/xml/spring-util-3.2.xsd, http://www.springframework.org/schema/beans/spring-beans-4.1.xsd=org/springframework/beans/factory/xml/spring-beans-4.1.xsd, http://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd, http://www.springframework.org/schema/tool/spring-tool-2.5.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd, http://www.springframework.org/schema/beans/spring-beans-3.1.xsd=org/springframework/beans/factory/xml/spring-beans-3.1.xsd, http://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd, http://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-4.2.xsd, http://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-4.2.xsd, http://www.springframework.org/schema/tool/spring-tool-3.2.xsd=org/springframework/beans/factory/xml/spring-tool-3.2.xsd, http://www.springframework.org/schema/util/spring-util-4.0.xsd=org/springframework/beans/factory/xml/spring-util-4.0.xsd, http://www.springframework.org/schema/tool/spring-tool-4.0.xsd=org/springframework/beans/factory/xml/spring-tool-4.0.xsd, http://www.springframework.org/schema/util/spring-util-3.1.xsd=org/springframework/beans/factory/xml/spring-util-3.1.xsd, http://www.springframework.org/schema/beans/spring-beans-4.0.xsd=org/springframework/beans/factory/xml/spring-beans-4.0.xsd, http://www.springframework.org/schema/util/spring-util-4.2.xsd=org/springframework/beans/factory/xml/spring-util-4.2.xsd, http://www.springframework.org/schema/beans/spring-beans-3.0.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd, http://www.springframework.org/schema/tool/spring-tool-3.1.xsd=org/springframework/beans/factory/xml/spring-tool-3.1.xsd, http://www.springframework.org/schema/util/spring-util.xsd=org/springframework/beans/factory/xml/spring-util-4.2.xsd, http://www.springframework.org/schema/tool/spring-tool-4.2.xsd=org/springframework/beans/factory/xml/spring-tool-4.2.xsd}
2016-08-30 15:16:16 DEBUG [main] - Found XML schema [http://www.springframework.org/schema/beans/spring-beans-3.0.xsd] in classpath: org/springframework/beans/factory/xml/spring-beans-3.0.xsd
2016-08-30 15:16:16 DEBUG [main] - Loading bean definitions
2016-08-30 15:16:27 DEBUG [main] - Creating shared instance of singleton bean 'bean1'
2016-08-30 15:16:27 DEBUG [main] - Creating instance of bean 'bean1'
2016-08-30 15:16:27 DEBUG [main] - Eagerly caching bean 'bean1' to allow for resolving potential circular references
源碼閱讀debug postProcessBeforeInitialization:org.springframework.beans.factory.FactoryBeanTests$PassThroughFactoryBean@659a969b
源碼閱讀debug postProcessAfterInitialization:org.springframework.beans.factory.FactoryBeanTests$PassThroughFactoryBean@659a969b
2016-08-30 15:18:13 DEBUG [main] - Finished creating instance of bean 'bean1'
2016-08-30 15:18:13 DEBUG [main] - Creating shared instance of singleton bean 'beanImpl1'
2016-08-30 15:18:13 DEBUG [main] - Creating instance of bean 'beanImpl1'
2016-08-30 15:18:16 DEBUG [main] - Eagerly caching bean 'beanImpl1' to allow for resolving potential circular references
2016-08-30 15:18:16 DEBUG [main] - Creating shared instance of singleton bean 'bean2'
2016-08-30 15:18:16 DEBUG [main] - Creating instance of bean 'bean2'
2016-08-30 15:18:16 DEBUG [main] - Eagerly caching bean 'bean2' to allow for resolving potential circular references
源碼閱讀debug postProcessBeforeInitialization:org.springframework.beans.factory.FactoryBeanTests$PassThroughFactoryBean@49b0b76
源碼閱讀debug postProcessAfterInitialization:org.springframework.beans.factory.FactoryBeanTests$PassThroughFactoryBean@49b0b76
2016-08-30 15:18:19 DEBUG [main] - Finished creating instance of bean 'bean2'
2016-08-30 15:18:19 DEBUG [main] - Creating shared instance of singleton bean 'beanImpl2'
2016-08-30 15:18:19 DEBUG [main] - Creating instance of bean 'beanImpl2'
2016-08-30 15:18:21 DEBUG [main] - Eagerly caching bean 'beanImpl2' to allow for resolving potential circular references
2016-08-30 15:18:21 DEBUG [main] - Returning cached instance of singleton bean 'bean1'
2016-08-30 15:18:21 DEBUG [main] - Returning eagerly cached instance of singleton bean 'beanImpl1' that is not fully initialized yet - a consequence of a circular reference
源碼閱讀debug postProcessAfterInitialization:org.springframework.beans.factory.FactoryBeanTests$BeanImpl1@769f71a9
源碼閱讀debug postProcessBeforeInitialization:org.springframework.beans.factory.FactoryBeanTests$BeanImpl2@4c9f8c13
源碼閱讀debug postProcessAfterInitialization:org.springframework.beans.factory.FactoryBeanTests$BeanImpl2@4c9f8c13
2016-08-30 15:18:23 DEBUG [main] - Finished creating instance of bean 'beanImpl2'
源碼閱讀debug postProcessAfterInitialization:org.springframework.beans.factory.FactoryBeanTests$BeanImpl2@4c9f8c13
源碼閱讀debug postProcessBeforeInitialization:org.springframework.beans.factory.FactoryBeanTests$BeanImpl1@769f71a9
源碼閱讀debug postProcessAfterInitialization:org.springframework.beans.factory.FactoryBeanTests$BeanImpl1@769f71a9
2016-08-30 15:18:25 DEBUG [main] - Finished creating instance of bean 'beanImpl1'
2016-08-30 15:18:25 DEBUG [main] - Returning cached instance of singleton bean 'beanImpl1'
2016-08-30 15:18:25 DEBUG [main] - Returning cached instance of singleton bean 'bean1'

可以看到日志已經(jīng)輸出授帕,其實(shí)仔細(xì)讀日志基本的初始化過程也可以了解,
接下來看下spring怎么處理兩個(gè)bean之間的循環(huán)依賴的炒辉。
其中日志中有幾條這樣的輸出
Eagerly caching bean 'bean1' to allow for resolving potential circular references
2016-08-30 15:18:16 DEBUG [main] - Eagerly caching bean 'beanImpl1' to allow for resolving potential circular references
2016-08-30 15:18:21 DEBUG [main] - Eagerly caching bean 'beanImpl2' to allow for resolving potential circular references
2016-08-30 15:18:21 DEBUG [main] - Returning eagerly cached instance of singleton bean 'beanImpl1' that is not fully initialized yet
最后出現(xiàn)的這條日志其實(shí)就是 返回了之前的引用
找到輸出這條日志的類<em>AbstractBeanFactory</em>的<em>doGetBean方法</em> 有isSingletonCurrentlyInCreation的判斷

if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }

點(diǎn)進(jìn)去找到源頭是<b>DefaultSingletonBeanRegistry</b>
該類實(shí)現(xiàn)了spring-core中的接口 這個(gè)后續(xù)再分析豪墅,先看本類聲明了需要存儲(chǔ)的屬性

/** Cache of singleton objects: bean name --> bean instance */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);

    /** Cache of singleton factories: bean name --> ObjectFactory */
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

    /** Cache of early singleton objects: bean name --> bean instance */
    private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

    /** Set of registered singletons, containing the bean names in registration order */
    private final Set<String> registeredSingletons = new LinkedHashSet<String>(64);

    /** Names of beans that are currently in creation */
    private final Set<String> singletonsCurrentlyInCreation =
            Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));

    /** Names of beans currently excluded from in creation checks */
    private final Set<String> inCreationCheckExclusions =
            Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));

    /** List of suppressed Exceptions, available for associating related causes */
    private Set<Exception> suppressedExceptions;

    /** Flag that indicates whether we're currently within destroySingletons */
    private boolean singletonsCurrentlyInDestruction = false;

    /** Disposable bean instances: bean name --> disposable instance */
    private final Map<String, Object> disposableBeans = new LinkedHashMap<String, Object>();

    /** Map between containing bean names: bean name --> Set of bean names that the bean contains */
    private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<String, Set<String>>(16);

    /** Map between dependent bean names: bean name --> Set of dependent bean names */
    private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<String, Set<String>>(64);

    /** Map between depending bean names: bean name --> Set of bean names for the bean's dependencies */
    private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<String, Set<String>>(64);

大概瀏覽下里面的方法
看到有對(duì)屬性對(duì)象的remove和add等操作
其實(shí)

singletonFactories,用于存儲(chǔ)在spring內(nèi)部所使用的beanName->對(duì)象工廠的引用黔寇,一旦最終對(duì)象被創(chuàng)建(通過objectFactory.getObject())偶器,此引用信息將刪除
earlySingletonObjects,用于存儲(chǔ)在創(chuàng)建Bean早期對(duì)創(chuàng)建的原始bean的一個(gè)引用缝裤,注意這里是原始bean屏轰,即使用工廠方法或構(gòu)造方法創(chuàng)建出來的對(duì)象,一旦對(duì)象最終創(chuàng)建好憋飞,此引用信息將刪除

最終創(chuàng)建完成bean后這兩個(gè)對(duì)象中都不會(huì)存在bean 即size為0
debug發(fā)現(xiàn)為了完成最原始得bean注入意思是
bean1 注入的是最原始得bean2 (此時(shí)的bean2不包括屬性bean1)
bean2注入的也是最原始得bean1(此時(shí)的bean1不包括屬性bean2)
會(huì)放到cached
<em>FactoryBeanRegistrySupport</em>中
該類擁有屬性

/** Cache of singleton objects created by FactoryBeans: FactoryBean name --> object */
    private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<String, Object>(16);

兩者的循環(huán)依賴是基于Setter的依賴注入
基于Setter的依賴注入霎苗,是在Bean完成實(shí)例化之后,容器調(diào)用Bean的setter方法來完成的榛做。
這樣的話就解決了循環(huán)依賴問題唁盏。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市检眯,隨后出現(xiàn)的幾起案子厘擂,更是在濱河造成了極大的恐慌,老刑警劉巖锰瘸,帶你破解...
    沈念sama閱讀 223,126評(píng)論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刽严,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡避凝,警方通過查閱死者的電腦和手機(jī)舞萄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來管削,“玉大人倒脓,你說我怎么就攤上這事『迹” “怎么了把还?”我有些...
    開封第一講書人閱讀 169,941評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵,是天一觀的道長茸俭。 經(jīng)常有香客問我,道長安皱,這世上最難降的妖魔是什么调鬓? 我笑而不...
    開封第一講書人閱讀 60,294評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮酌伊,結(jié)果婚禮上腾窝,老公的妹妹穿的比我還像新娘缀踪。我一直安慰自己,他們只是感情好虹脯,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評(píng)論 6 398
  • 文/花漫 我一把揭開白布驴娃。 她就那樣靜靜地躺著,像睡著了一般循集。 火紅的嫁衣襯著肌膚如雪唇敞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,874評(píng)論 1 314
  • 那天咒彤,我揣著相機(jī)與錄音疆柔,去河邊找鬼。 笑死镶柱,一個(gè)胖子當(dāng)著我的面吹牛旷档,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播歇拆,決...
    沈念sama閱讀 41,285評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼鞋屈,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了故觅?” 一聲冷哼從身側(cè)響起厂庇,我...
    開封第一講書人閱讀 40,249評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎逻卖,沒想到半個(gè)月后宋列,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,760評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡评也,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評(píng)論 3 343
  • 正文 我和宋清朗相戀三年炼杖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盗迟。...
    茶點(diǎn)故事閱讀 40,973評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡坤邪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出罚缕,到底是詐尸還是另有隱情艇纺,我是刑警寧澤,帶...
    沈念sama閱讀 36,631評(píng)論 5 351
  • 正文 年R本政府宣布邮弹,位于F島的核電站黔衡,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏腌乡。R本人自食惡果不足惜盟劫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望与纽。 院中可真熱鬧侣签,春花似錦塘装、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至猴娩,卻和暖如春阴幌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背胀溺。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評(píng)論 1 275
  • 我被黑心中介騙來泰國打工裂七, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人仓坞。 一個(gè)月前我還...
    沈念sama閱讀 49,431評(píng)論 3 379
  • 正文 我出身青樓背零,卻偏偏與公主長得像,于是被迫代替她去往敵國和親无埃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子徙瓶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評(píng)論 2 361

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