Spring

Spring初始化

--- StandardContext --- //org.apache.catalina.core.StandardContext
startInternal -> listenerStart -> listener.contextInitialized(ServletContextListener.contextInitialized)
--- ContextLoaderListener ---
contextInitialized -> initWebApplicationContext -> createWebApplicationContext(Default:XmlWebApplicationContext) -> configureAndRefreshWebApplicationContext -> refresh
--- AbstractApplicationContext ---
refresh
    //1.create factory and load bean definition.
    obtainFreshBeanFactory
        -> refreshBeanFactory 
        -> createBeanFactory(DefaultListableBeanFactory) 
        -> loadBeanDefinitions  //加載applicationContext文件焊夸,將里面的bean定義轉(zhuǎn)成BeanDefinition肴敛,裝在到BeanFactory beanDefinitionMap
    //2.invoke factory processor: Invoke factory processors registered as beans in the context.
    invokeBeanFactoryPostProcessors
        -> postProcessBeanFactory   //BeanFactoryPostProcessor桶雀,可以修改bean definitions空执,此動(dòng)作在所有bean初始化之前 //All bean definitions will have been loaded, but no beans will have been instantiated yet. This allows for overriding or adding properties even to eager-initializing beans.
    //3.register bean processor: Register bean processors that intercept bean creation. 將BeanPostProcessor類型的bean提前加載勋眯、實(shí)例化初始化婴梧,并注冊(cè)下梢,然后在第4步普通bean創(chuàng)建時(shí)執(zhí)行攔截方法:postProcessBefore/AfterInitialization
    registerBeanPostProcessors
        -> registerBeanPostProcessors
        -> getBean (for (String ppName : postProcessorNames); BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);) //go to AbstractBeanFactory.getBean getBean這里會(huì)實(shí)例化BeanPostProcessor
        -> beanFactory.addBeanPostProcessor(postProcessor);
    //4.instantiate: Instantiate all remaining (non-lazy-init) singletons. 實(shí)例化剩余普通的bean
    finishBeanFactoryInitialization(beanFactory);
        -> preInstantiateSingletons(beanFactory.preInstantiateSingletons()) //List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames); for (String beanName : beanNames) -> getBean(beanName);
        -> getBean  (for (String beanName : beanNames) { getBean(beanName); })  //go to AbstractBeanFactory.getBean

擴(kuò)展

擴(kuò)展原理:
1、init塞蹭,registerBeanDefinitionParser注冊(cè)BeanDefinition解釋器
2孽江、parse:2.1.element 獲取自定義的配置 2.2.registerBeanDefinition 向registry注冊(cè)BeanDefinition
registry其實(shí)就是factory:DefaultListableBeanFactory,registerBeanDefinition 注冊(cè)beanDefinition番电,后續(xù)在finishBeanFactoryInitialization中會(huì)遍歷所有beanDefinition進(jìn)行實(shí)例化岗屏。
這個(gè)注冊(cè)過程其實(shí)就跟手動(dòng)注解@Component一個(gè)意思,注冊(cè)beanDefinition漱办,之后由工廠進(jìn)行初始化这刷。

--- AbstractXmlApplicationContext ---
    loadBeanDefinitions -> XmlBeanDefinitionReader.loadBeanDefinitions -> DefaultBeanDefinitionDocumentReader.registerBeanDefinitions 
    -> DefaultBeanDefinitionDocumentReader.parseBeanDefinitions -> BeanDefinitionParserDelegate.parseCustomElement
--- BeanDefinitionParserDelegate ---
    parseCustomElement -> resolve(String namespaceUri) -> namespaceHandler.init() //NamespaceHandlerSupport -> registerBeanDefinitionParser("xx",new XXBeanDefinitionParser());
                       -> handler.parse -> XXBeanDefinitionParser.parse -> registry.registerBeanDefinition("xxBeanDefinition",xxBeanDefinition);//解析自定義的配置文件,然后一般會(huì)向registry進(jìn)行注冊(cè)registerBeanDefinition   
通過NamespaceHandlerSupport娩井、BeanDefinitionParser完成擴(kuò)展:
public class XXNamespaceHandler extends NamespaceHandlerSupport{
    @Override
    public void init() {
        registerBeanDefinitionParser("annotation-driven",new XXBeanDefinitionParser());
    }
}
//XXBeanDefinitionParser 也可以繼承自AbstractSingleBeanDefinitionParser暇屋、AbstractBeanDefinitionParser,原理是類似的洞辣。
public class XXBeanDefinitionParser implements BeanDefinitionParser{
    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        //element 配置文件的對(duì)象
        RootBeanDefinition xxBeanDefinition = new RootBeanDefinition();
        BeanDefinitionRegistry registry = parserContext.getRegistry();
        registry.registerBeanDefinition("xxx", xxBeanDefinition);
        return xxBeanDefinition;
    }
}

創(chuàng)建Bean

//Parse the elements at the root level in the document: "import", "alias", "bean".
--- AbstractBeanFactory ---
    getBean
    doGetBean
    getSingleton
    createBean  //go to AbstractAutowireCapableBeanFactory.createBean
--- AbstractAutowireCapableBeanFactory ---
    createBean 
    -> resolveBeforeInstantiation -> postProcessBeforeInstantiation (if (bean != null) -> postProcessAfterInitialization)
    -> doCreateBean 
        -> createBeanInstance -> instantiateBean -> BeanUtils.instantiateClass(constructorToUse) -> constructorToUse.newInstance(args)
        -> populateBean(postProcessAfterInstantiation -> autowire -> postProcessPropertyValues -> applyPropertyValues)
        -> initializeBean
            -> invokeAwareMethods(BeanNameAware->setBeanName, BeanClassLoaderAware->setBeanClassLoader, BeanFactoryAware->setBeanFactory)
            -> postProcessBeforeInitialization 
            -> invokeInitMethods(afterPropertiesSet&invokeCustomInitMethod) 
            -> postProcessAfterInitialization

Bean創(chuàng)建關(guān)鍵流程如下:
createBean
-> postProcessBeforeInstantiation -> return null -> createBeanInstance -> postProcessAfterInstantiation -> postProcessBeforeInitialization -> invokeInitMethods -> postProcessAfterInitialization -> return bean
-> postProcessBeforeInstantiation -> not null -> postProcessAfterInitialization -> return bean

從這里看可以看到咐刨,在這個(gè)過程有多個(gè)可以執(zhí)行攔截的地方,這些攔截也正是Spring作為一個(gè)框架的優(yōu)秀之處扬霜,因?yàn)樵跀r截的地方可以進(jìn)行各種增強(qiáng)定鸟,使得其擁有良好的擴(kuò)展性:
InstantiationAwareBeanPostProcessor: postProcessBeforeInstantiation/postProcessAfterInstantiation/postProcessPropertyValues 作用于實(shí)例化階段
BeanPostProcessor: postProcessBeforeInitialization/postProcessAfterInitialization 作用于初始化階段

1、createBean
1.1 resolveBeforeInstantiation
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);    //applyBeanPostProcessorsBeforeInstantiation
if (bean != null) {
    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);      //applyBeanPostProcessorsAfterInitialization
}
...
return bean;

1.2 applyBeanPostProcessorsBeforeInstantiation
//invoking their postProcessBeforeInstantiation methods. 調(diào)用postProcessBeforeInstantiation著瓶,這個(gè)方法在bean實(shí)例化之前執(zhí)行
//Any returned object will be used as the bean instead of actually instantiating the target bean.
//A null return value from the post-processor will result in the target bean being instantiated.
//若返回了非空對(duì)象联予,則直接被當(dāng)做bean,替代后續(xù)真正實(shí)例化的bean材原;若返回是空的沸久,將繼續(xù)調(diào)用實(shí)際的實(shí)例化方法
//即若在這里執(zhí)行攔截返回了非空對(duì)象,后續(xù)bean的實(shí)例化將跳過华糖,直接跳轉(zhuǎn)執(zhí)行bean的初始化后置操作postProcessAfterInitialization麦向,然后直接返回
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);    //InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation

return null;

2瘟裸、doCreateBean
2.1 createBeanInstance(beanName, mbd, args);        //創(chuàng)建對(duì)象(實(shí)例化)
2.2 populateBean(beanName, mbd, instanceWrapper);   //填充對(duì)象屬性
2.3 initializeBean                                  //初始化

2.2 populateBean
2.2.1 postProcessAfterInstantiation 
//This is the ideal callback for performing field injection on the given bean instance. 是一個(gè)執(zhí)行字段注入的回調(diào)方法客叉。若返回false,將不再執(zhí)行后續(xù)的字段注入话告。
//如果返回false兼搏,將不再給bean設(shè)置屬性。此接口目前三個(gè)實(shí)現(xiàn)都是無任何操作沙郭,僅僅只是返回了true佛呻。
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    continueWithPropertyPopulation = false;
    break;
}
if (!continueWithPropertyPopulation) {
    return;
}
2.2.2 autowire
PropertyValues pvs = mbd.getPropertyValues();
autowireByName(beanName, mbd, bw, newPvs);  //加載屬性依賴的bean
autowireByType(beanName, mbd, bw, newPvs);
2.2.3 postProcessPropertyValues
//Post-process the given property values before the factory applies them to the given bean. Also allows for replacing the property values to apply
//對(duì)屬性值進(jìn)行后置處理,允許替換要應(yīng)用的屬性值
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
    return;
}
2.2.4 applyPropertyValues

2.3 initializeBean
2.3.1 invokeAwareMethods
    private void invokeAwareMethods(final String beanName, final Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
            if (bean instanceof BeanClassLoaderAware) {
                ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
            }
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
            }
        }
    }
2.3.2 applyBeanPostProcessorsBeforeInitialization   //postProcessBeforeInitialization
    result = beanProcessor.postProcessBeforeInitialization(result, beanName);
2.3.3 invokeInitMethods     //afterPropertiesSet, invokeCustomInitMethod
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean...) {
        ((InitializingBean) bean).afterPropertiesSet();
    }
    invokeCustomInitMethod
2.3.4 applyBeanPostProcessorsAfterInitialization
    result = beanProcessor.postProcessAfterInitialization(result, beanName);

AOP

核心:AbstractAutoProxyCreator implements SmartInstantiationAwareBeanPostProcessor, InstantiationAwareBeanPostProcessor,
BeanPostProcessor
原理:postProcessBefore/AfterInstantiation, postProcessBefore/AfterInitialization病线,在Bean的創(chuàng)建或初始化的前后攔截吓著,實(shí)現(xiàn)代理鲤嫡。
核心類:AbstractAutoProxyCreator、AnnotationAwareAspectJAutoProxyCreator

1绑莺、配置AspectJ:若需要AspactJ支持暖眼,需要添加配置,其實(shí)現(xiàn)對(duì)應(yīng) AnnotationAwareAspectJAutoProxyCreator纺裁,添加配置有2中方式
1.1 配置文件文件
<aop:aspectj-autoproxy proxy-target-class="true"/>
1.2 AopConfigUtils
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary

2诫肠、構(gòu)建Advisor
AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator

2.1 postProcessBeforeInstantiation 以這個(gè)方法為入口構(gòu)建Advisor(但這里并沒有做攔截)
//AbstractAutoProxyCreator
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    Object cacheKey = getCacheKey(beanClass, beanName);

    if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {  //Advisor所在的類跳過,不執(zhí)行攔截
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }

    // Create proxy here if we have a custom TargetSource.
    // Suppresses unnecessary default instantiation of the target bean:
    // The TargetSource will handle target instances in a custom fashion.
    if (beanName != null) {
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);     //其他類執(zhí)行代理創(chuàng)建欺缘,一般未指定targetSource栋豫,這里都不會(huì)執(zhí)行代理創(chuàng)建
        if (targetSource != null) {
            this.targetSourcedBeans.add(beanName);
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
    }

    return null;                                                                    //未自定義TargetSource的,一般也直接返回null
}

//AspectJAwareAdvisorAutoProxyCreator
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    // TODO: Consider optimization by caching the list of the aspect names
    List<Advisor> candidateAdvisors = findCandidateAdvisors();              //這里會(huì)去查找所有的Advisor谚殊,即找到所有增強(qiáng)方法
    for (Advisor advisor : candidateAdvisors) {
        if (advisor instanceof AspectJPointcutAdvisor) {
            if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {   //Advisor所在的類跳過丧鸯,不執(zhí)行攔截
                return true;
            }
        }
    }
    return super.shouldSkip(beanClass, beanName);
}

2.2 Advisor的構(gòu)造過程
2.2.1 查找所有bean,找出@Aspect切面的bean
buildAspectJAdvisors - BeanFactoryAspectJAdvisorsBuilder
for (String beanName : beanNames) {
    if (this.advisorFactory.isAspect(beanType)) {   //isAspect: hasAspectAnnotation(clazz) && !compiledByAjc(clazz)
        List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
    }
}

2.2.2 找到所有的Advisor方法
getAdvisors - ReflectiveAspectJAdvisorFactory
for (Method method : getAdvisorMethods(aspectClass)) {
    Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
    if (advisor != null) {
        advisors.add(advisor);
    }
}
//獲取所有方法络凿,排除Pointcut注解的方法
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
    final List<Method> methods = new LinkedList<Method>();
    ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
        @Override
        public void doWith(Method method) throws IllegalArgumentException {
            // Exclude pointcuts
            if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
                methods.add(method);
            }
        }
    });
    Collections.sort(methods, METHOD_COMPARATOR);
    return methods;
}
2.2.3 找到帶@Around @Before等注解的方法骡送,并將其包裝成Advisor
getAdvisor -> getPointcut -> findAspectJAnnotationOnMethod
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
        int declarationOrderInAspect, String aspectName) {

    validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

    AspectJExpressionPointcut expressionPointcut = getPointcut(
            candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); 
    if (expressionPointcut == null) {
        return null;
    }

    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
            this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
    Class<?>[] classesToLookFor = new Class<?>[] {
            Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
    for (Class<?> c : classesToLookFor) {
        AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);   //獲取PointCut配置,如@Around("execution(* com.xx.xx.x..*.*(..)) || @annotation(com.xx.xx.xx.XXAnnotation)")
        if (foundAnnotation != null) {
            return foundAnnotation;
        }
    }
    return null;
}

3.3 代理的創(chuàng)建 postProcessAfterInitialization 
再回顧一遍這個(gè)流程:
refresh -> finishBeanFactoryInitialization -> preInstantiateSingletons -> getBean -> doGet.. -> createBean .. -> createBeanInstance(AbstractAutowireCapableBeanFactory) 這里就已經(jīng)實(shí)例化完成絮记,bean已經(jīng)創(chuàng)建了 -> populateBean
-> initializeBean -> applyBeanPostProcessorsAfterInitialization -> beanProcessor.postProcessAfterInitialization(AnnotationAwareAspectJAutoProxyCreator)
-> postProcessAfterInitialization(AbstractAutoProxyCreator) -> wrapIfNecessary -> getAdvicesAndAdvisorsForBean(查找當(dāng)前bean是否需要增強(qiáng)) -> AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass)
-> createProxy -> proxyFactory.getProxy -> createAopProxy(DefaultAopProxyFactory) -> getProxy (CglibAopProxy)

真正代理創(chuàng)建并不是在postProcessBeforeInstantiation摔踱,而是postProcessAfterInitialization,所以真正攔截怨愤,將bean替換成代理對(duì)象是在postProcessAfterInitialization方法做的派敷。
postProcessAfterInitialization 一般的實(shí)現(xiàn),如果不做代理撰洗,就直接返回bean 就可以篮愉。

wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (specificInterceptors != DO_NOT_PROXY) {
        Object proxy = createProxy;
        return proxy;   //返回的代理對(duì)象替換真正的bean
    }
    return bean;
}

DefaultAopProxyFactory
    createAopProxy:
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {   //指定了proxy-target-class=true,或hasNoUserSuppliedProxyInterfaces 即當(dāng)前類沒有實(shí)現(xiàn)接口差导,則使用cglib
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);  //cglib
        }
        else {
            return new JdkDynamicAopProxy(config);      //jdk
        }
    }

CglibAopProxy
    getProxy
    Enhancer enhancer = createEnhancer();
    enhancer.setSuperclass(proxySuperClass);    //targetClass
    enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
    createProxyClassAndInstance
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末试躏,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子设褐,更是在濱河造成了極大的恐慌颠蕴,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件助析,死亡現(xiàn)場(chǎng)離奇詭異犀被,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)外冀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門寡键,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人雪隧,你說我怎么就攤上這事西轩≡倍妫” “怎么了?”我有些...
    開封第一講書人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵藕畔,是天一觀的道長(zhǎng)固灵。 經(jīng)常有香客問我,道長(zhǎng)劫流,這世上最難降的妖魔是什么巫玻? 我笑而不...
    開封第一講書人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮祠汇,結(jié)果婚禮上仍秤,老公的妹妹穿的比我還像新娘。我一直安慰自己可很,他們只是感情好诗力,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著我抠,像睡著了一般苇本。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上菜拓,一...
    開封第一講書人閱讀 51,610評(píng)論 1 305
  • 那天瓣窄,我揣著相機(jī)與錄音,去河邊找鬼纳鼎。 笑死俺夕,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的贱鄙。 我是一名探鬼主播劝贸,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼逗宁!你這毒婦竟也來了映九?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤瞎颗,失蹤者是張志新(化名)和其女友劉穎件甥,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體言缤,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嚼蚀,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年禁灼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了管挟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡弄捕,死狀恐怖僻孝,靈堂內(nèi)的尸體忽然破棺而出导帝,到底是詐尸還是另有隱情,我是刑警寧澤穿铆,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布您单,位于F島的核電站,受9級(jí)特大地震影響荞雏,放射性物質(zhì)發(fā)生泄漏虐秦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一凤优、第九天 我趴在偏房一處隱蔽的房頂上張望悦陋。 院中可真熱鬧,春花似錦筑辨、人聲如沸俺驶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)暮现。三九已至,卻和暖如春楚昭,著一層夾襖步出監(jiān)牢的瞬間栖袋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工抚太, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留栋荸,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓凭舶,卻偏偏與公主長(zhǎng)得像晌块,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子帅霜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355