轉(zhuǎn)-AOP動(dòng)態(tài)代理解析3-增強(qiáng)方法的獲取

https://www.cnblogs.com/wade-luffy/p/6076823.html

對(duì)于指定bean的增強(qiáng)方法的獲取一定是包含兩個(gè)步驟的:

  1. 獲取所有的增強(qiáng)
  2. 尋找所有增強(qiáng)中使用于bean的增強(qiáng)并應(yīng)用

那么findCandidateAdvisors與findAdvisorsThatCanApply便是做了這兩件事情。當(dāng)然,如果無(wú)法找到對(duì)便返回DO_NOT_PROXY晦譬,其中DO_NOT_PROXY=null.

protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource)  
{  
    List advisors = findEligibleAdvisors(beanClass, beanName);  
    if(advisors.isEmpty())  
        return DO_NOT_PROXY;  
    else  
        return advisors.toArray();  
}  
protected List findEligibleAdvisors(Class beanClass, String beanName)  
{  
  //獲取所有的增強(qiáng)器
    List candidateAdvisors = findCandidateAdvisors();  
  //獲取適合beanname的增強(qiáng)器
    List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);  
    extendAdvisors(eligibleAdvisors);  
    if(!eligibleAdvisors.isEmpty())  
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);  
    return eligibleAdvisors;  
}  

所有增強(qiáng)器的獲取

由于分析的是使用注解進(jìn)行的AOP了罪,所以對(duì)于findCandidateAdvisors的實(shí)現(xiàn)其實(shí)是由AnnotationAwareAspectJAutoProxyCreator類完成的狮暑,我們繼續(xù)跟蹤AnnotationAwareAspectJAutoProxyCreator的findCandidateAdvisors方法艰躺。

protected List findCandidateAdvisors()  {  
    //當(dāng)使用注解方式配置AOP的時(shí)候并不是丟棄了對(duì)XML配置的支持侄泽。  
    //在這里調(diào)用父類方法加載配置文件中的AOP聲明  
    List advisors = super.findCandidateAdvisors();  
    //Build Advisors for all AspectJ aspects in the bean factory  
    advisors.addAll(aspectJAdvisorsBuilder.buildAspectJAdvisors());  
    return advisors;  
}

AnnotationAwareAspectJAutoProxyCreator間接繼承了AbstractAdvisorAutoProxyCreator绍撞,在實(shí)現(xiàn)獲取增強(qiáng)的方法中除了保留父類的獲取配置文件中定義的增強(qiáng)外正勒,同時(shí)添加了獲取Bean的注解增強(qiáng)的功能,那么其實(shí)現(xiàn)正是由this.aspectJAdvisorsBuilder.buildAspectJAdvisors()來(lái)實(shí)現(xiàn)的傻铣。
(1)獲取所有beanName章贞,這一步驟中所有在beanFactory中注冊(cè)的Bean都會(huì)被提取出來(lái)。
(2)遍歷所有beanName非洲,并找出聲明AspectJ注解的類鸭限,進(jìn)行進(jìn)一步的處理就谜。
(3)對(duì)標(biāo)記為AspectJ注解的類進(jìn)行增強(qiáng)器的提取。
(4)將提取結(jié)果加入緩存里覆。

提取Advisor

現(xiàn)在來(lái)看看函數(shù)實(shí)現(xiàn)丧荐,對(duì)Spirng中所有的類進(jìn)行分析,提取Advisor喧枷。

public List buildAspectJAdvisors()  
    {  
        List aspectNames = null;  
        synchronized(this){  
        aspectNames = aspectBeanNames;  
        if(aspectNames == null)  
        {  
            List advisors = new LinkedList();  
            aspectNames = new LinkedList();  
            //獲取所有的beanName  
            String beanNames[] = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, java/lang/Object, true, false);  
            //循環(huán)所有的beanName找出對(duì)應(yīng)的增強(qiáng)方法  
            for(String beanName : beanNames)  
            {  
                //不合法的bean則略過(guò)虹统,由子類定義規(guī)則,默認(rèn)返回true  
               if(!isEligibleBean(beanName))  
                    continue;  
                //獲取對(duì)應(yīng)的bean的類型  
                Class beanType = beanFactory.getType(beanName);  
                //如果存在Aspect注解  
               if(beanType == null || !advisorFactory.isAspect(beanType))  
                    continue;  
                aspectNames.add(beanName);  
                AspectMetadata amd = new AspectMetadata(beanType, beanName);  
                MetadataAwareAspectInstanceFactory factory;  
                if(amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON)  
                {  
                    factory = new BeanFactoryAspectInstanceFactory(beanFactory, beanName);  
                    //解析標(biāo)記AspectJ注解中的增強(qiáng)方法  
                    List classAdvisors = advisorFactory.getAdvisors(factory);  
                    if(beanFactory.isSingleton(beanName))  
                        advisorsCache.put(beanName, classAdvisors);  
                    else  
                        aspectFactoryCache.put(beanName, factory);  
                    advisors.addAll(classAdvisors);  
                    continue;  
                }  
                if(beanFactory.isSingleton(beanName))  
                    throw new IllegalArgumentException((
                    new StringBuilder()).append("Bean with name '")
                                .append(beanName)
                                .append("' is a singleton, but aspect instantiation model is not singleton")
                                .toString());  
                factory = new PrototypeAspectInstanceFactory(beanFactory, beanName);  
                aspectFactoryCache.put(beanName, factory);  
                advisors.addAll(advisorFactory.getAdvisors(factory));  
            }  
  
            aspectBeanNames = aspectNames;  
            return advisors;  
         
    } 

至此隧甚,已經(jīng)完成了Advisor的提取车荔。

切點(diǎn)信息的獲取

在上面的步驟中最為重要也最為繁雜的就是增強(qiáng)器的獲取,而這一切功能委托給了getAdvisors方法去實(shí)現(xiàn)(this.advisorFactory.getAdvisors(factory))戚扳。

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {
     //獲取標(biāo)記為AspectJ的類 
        final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();
     //獲取標(biāo)記為AspectJ的name
        final String aspectName = maaif.getAspectMetadata().getAspectName();
     //驗(yàn)證
        validate(aspectClass);
        final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
                new LazySingletonAspectInstanceFactoryDecorator(maaif);
        final List<Advisor> advisors = new LinkedList<Advisor>();
        for (Method method : getAdvisorMethods(aspectClass)) {
            Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
            if (advisor != null) {
                advisors.add(advisor);
            }
        }
     //如果尋找的增強(qiáng)器不為空而且又配置了增強(qiáng)延遲初始化那么需要在首位加入同步實(shí)例化增強(qiáng)器
        if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
            Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
            advisors.add(0, instantiationAdvisor);
        }
     //對(duì)DeclareParents注解的獲取
        for (Field field : aspectClass.getDeclaredFields()) {
            Advisor advisor = getDeclareParentsAdvisor(field);
            if (advisor != null) {
                advisors.add(advisor);
            }
        }
        return advisors;
    }

函數(shù)中首先完成了增強(qiáng)器的獲取忧便,包括獲取注解以及根據(jù)注解生成增強(qiáng)的步驟,然后考慮到在配置中可能會(huì)將增強(qiáng)配置成延遲初始化帽借,那么需要在首位加入同步實(shí)例化增強(qiáng)器以保證增強(qiáng)使用之前的實(shí)例化珠增,最后是對(duì)DeclareParents注解的獲取。

普通增強(qiáng)器的獲取邏輯通過(guò)getAdvisor方法實(shí)現(xiàn)砍艾,實(shí)現(xiàn)步驟包括對(duì)切點(diǎn)的注解的獲取及根據(jù)注解信息生成增強(qiáng)蒂教。

(1)切點(diǎn)信息的獲取。所謂獲取切點(diǎn)信息就是指定注解的表達(dá)式信息的獲取脆荷,如@Before("test()")

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName)  
{  
    validate(aif.getAspectMetadata().getAspectClass());  
    //切點(diǎn)信息的獲取  
    AspectJExpressionPointcut ajexp = getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass());  
    if(ajexp == null)  
        return null;  
    else  
        //根據(jù)切點(diǎn)信息生成增強(qiáng)器  
        return new InstantiationModelAwarePointcutAdvisorImpl(this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName);  
}  

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
    //獲取方法上的注解  
    AspectJAnnotation<?> aspectJAnnotation =
            AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    if (aspectJAnnotation == null) {
        return null;
    }
    //使用AspectJExpressionPointcut實(shí)例封裝獲取的信息
    AspectJExpressionPointcut ajexp =
            new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]);
    //提取得到的注解中的表達(dá)式如:@Pointcut("execution(* *.*test*(..))")中的execution(* *.*test*(..))
    ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
    return ajexp;
}

protected static AspectJAnnotation findAspectJAnnotationOnMethod(Method method) {
    //設(shè)置敏感的注解類
    Class<? extends Annotation>[] classesToLookFor = new Class[] {
            Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
    for (Class<? extends Annotation> c : classesToLookFor) {
        AspectJAnnotation foundAnnotation = findAnnotation(method, c);
        if (foundAnnotation != null) {
            return foundAnnotation;
        }
    }
    return null;
}
//獲取指定方法上的注解并使用AspectJAnnotation封裝
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
    A result = AnnotationUtils.findAnnotation(method, toLookFor);
    if (result != null) {
        return new AspectJAnnotation<A>(result);
    }
    else {
        return null;
    }
}

(2)根據(jù)切點(diǎn)信息生成增強(qiáng)凝垛。所有的增強(qiáng)都有Advisor實(shí)現(xiàn)類InstantiationModelAwarePontcutAdvisorImpl統(tǒng)一封裝。

public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp,
        MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) {

    this.declaredPointcut = ajexp;
    this.method = method;
    this.atAspectJAdvisorFactory = af;
    this.aspectInstanceFactory = aif;
    this.declarationOrder = declarationOrderInAspect;
    this.aspectName = aspectName;

    if (aif.getAspectMetadata().isLazilyInstantiated()) {
        Pointcut preInstantiationPointcut =
                Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
        this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aif);
        this.lazy = true;
    }
    else {
        this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
        this.pointcut = declaredPointcut;
        this.lazy = false;
    }
}

封裝過(guò)程只是簡(jiǎn)單地將信息封裝在類的實(shí)例中蜓谋,所有的信息單純地復(fù)制梦皮。在實(shí)例初始化的過(guò)程中還完成了對(duì)于增強(qiáng)器的初始化。因?yàn)椴煌脑鰪?qiáng)所體現(xiàn)的邏輯是不同的桃焕,比如@Before(“test()”)與After(“test()”)標(biāo)簽的不同就是增強(qiáng)器增強(qiáng)的位置不同剑肯,所以就需要不同的增強(qiáng)器來(lái)完成不同的邏輯,而根據(jù)注解中的信息初始化對(duì)應(yīng)的增強(qiáng)器就是在instantiateAdvice函數(shù)中實(shí)現(xiàn)的覆旭。

private Advice instantiateAdvice(AspectJExpressionPointcut pcut)  
{  
    return atAspectJAdvisorFactory.getAdvice(method, pcut, aspectInstanceFactory, declarationOrder, aspectName);  
}  
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp, 
          MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName)  
    {  
        Class candidateAspectClass = aif.getAspectMetadata().getAspectClass();  
        validate(candidateAspectClass);  
        AbstractAspectJAdvisorFactory.AspectJAnnotation aspectJAnnotation = 
              AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);  
        if(aspectJAnnotation == null)  
            return null;  
       if(!isAspect(candidateAspectClass))  
            throw new AopConfigException(
            (new StringBuilder())
                  .append("Advice must be declared inside an aspect type: Offending method '")
                  .append(candidateAdviceMethod)
                  .append("' in class [")
                  .append(candidateAspectClass.getName())
                  .append("]").toString());  
        if(logger.isDebugEnabled())  
            logger.debug((new StringBuilder()).append("Found AspectJ method: ").append(candidateAdviceMethod).toString());  
        AbstractAspectJAdvice springAdvice;  
        switch(SwitchMap.org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory.AspectJAnnotationType
            [aspectJAnnotation.getAnnotationType().ordinal()])  
        {  
        case 1: // '\001'  
            springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);  
            break;  
  
        case 2: // '\002'  
            springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);  
            break;  
  
        case 3: // '\003'  
            springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif);  
            AfterReturning afterReturningAnnotation = (AfterReturning)aspectJAnnotation.getAnnotation();  
            if(StringUtils.hasText(afterReturningAnnotation.returning()))  
                springAdvice.setReturningName(afterReturningAnnotation.returning());  
            break;  
  
        case 4: // '\004'  
            springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif);  
            AfterThrowing afterThrowingAnnotation = (AfterThrowing)aspectJAnnotation.getAnnotation();  
            if(StringUtils.hasText(afterThrowingAnnotation.throwing()))  
                springAdvice.setThrowingName(afterThrowingAnnotation.throwing());  
            break;  
  
        case 5: // '\005'  
            springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);  
            break;  
  
        case 6: // '\006'  
            if(logger.isDebugEnabled())  
                logger.debug(
              (new StringBuilder()).append("Processing pointcut '")
                           .append(candidateAdviceMethod.getName())
                           .append("'").toString());  
            return null;  
  
        default:  
            throw new UnsupportedOperationException(
            (new StringBuilder()).append("Unsupported advice type on method ")
                         .append(candidateAdviceMethod).toString());  
        }  
        springAdvice.setAspectName(aspectName);  
        springAdvice.setDeclarationOrder(declarationOrderInAspect);  
        String argNames[] = parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);  
        if(argNames != null)  
            springAdvice.setArgumentNamesFromStringArray(argNames);  
        springAdvice.calculateArgumentBindings();  
        return springAdvice;  
    }  
}

從函數(shù)中可以看到退子,Spring會(huì)根據(jù)不同的注解生成不同的增強(qiáng)器岖妄,例如AtBefore會(huì)對(duì)應(yīng)AspectJMethodBeforeAdvice型将。

增加同步實(shí)例化增強(qiáng)器

如果尋找的增強(qiáng)器不為空而且又配置了增強(qiáng)延遲初始化,那么就需要在首位加入同步實(shí)例化增強(qiáng)器荐虐。

 protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {
        public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
            super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() {
                @Override
                public void before(Method method, Object[] args, Object target) {
                    // Simply instantiate the aspect
                    aif.getAspectInstance();
                }
            });
        }
    }

獲取DeclareParents注解

DeclareParents主要用于引介增強(qiáng)的注解形式的實(shí)現(xiàn)七兜,而其實(shí)現(xiàn)方式馭普通增強(qiáng)很類似,只不過(guò)使用DeclareParentsAdvisor對(duì)功能進(jìn)行封裝福扬。

引介是一種特殊的增強(qiáng)腕铸,它為類添加一些屬性和方法惜犀。這樣,即使一個(gè)業(yè)務(wù)類原本沒(méi)有實(shí)現(xiàn)某個(gè)接口狠裹,通過(guò)引介功能虽界,可以動(dòng)態(tài)的未該業(yè)務(wù)類添加接口的實(shí)現(xiàn)邏輯,讓業(yè)務(wù)類成為這個(gè)接口的實(shí)現(xiàn)類涛菠。

private Advisor getDeclareParentsAdvisor(Field introductionField)  
{  
    DeclareParents declareParents = (DeclareParents)introductionField.getAnnotation(org/aspectj/lang/annotation/DeclareParents);  
    if(declareParents == null)  
        return null;  
    if("org/aspectj/lang/annotation/DeclareParents".equals(declareParents.defaultImpl()))  
        throw new IllegalStateException("defaultImpl must be set on DeclareParents");  
    else  
        return new DeclareParentsAdvisor(introductionField.getType(), declareParents.value(), declareParents.defaultImpl());  
}  

至此已經(jīng)完成了所有增強(qiáng)器的解析莉御,但是對(duì)于所有增強(qiáng)器來(lái)講,并不一定都適用于當(dāng)前的Bean俗冻,還要挑取除適合的增強(qiáng)器礁叔,也就是滿足我們配置的通配符的增強(qiáng)器。具體的實(shí)現(xiàn)在findAdvisorsThatCanApply中迄薄。

獲取合適的增強(qiáng)器

findAdvisorsThatCanApply函數(shù)的主要功能是尋找所有增強(qiáng)器中適用于當(dāng)前class的增強(qiáng)器琅关。對(duì)于真是的匹配在canApply中實(shí)現(xiàn)。

protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class beanClass, String beanName) {
    ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    try {
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    }
    finally {
        ProxyCreationContext.setCurrentProxiedBeanName(null);
    }
}
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
    if (candidateAdvisors.isEmpty()) {
        return candidateAdvisors;
    }
    List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
    //首先處理引介增強(qiáng)
    for (Advisor candidate : candidateAdvisors) {
        if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
            eligibleAdvisors.add(candidate);
        }
    }
    boolean hasIntroductions = !eligibleAdvisors.isEmpty();
    for (Advisor candidate : candidateAdvisors) {
        if (candidate instanceof IntroductionAdvisor) {
            continue;
        }
        //對(duì)于普通bean的處理  
        if (canApply(candidate, clazz, hasIntroductions)) {
            eligibleAdvisors.add(candidate);
        }
    }
    return eligibleAdvisors;
}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
    Assert.notNull(pc, "Pointcut must not be null");
    if (!pc.getClassFilter().matches(targetClass)) {
        return false;
    }
    MethodMatcher methodMatcher = pc.getMethodMatcher();
    IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
    if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
        introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
    }
    Set<Class> classes = new LinkedHashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
    classes.add(targetClass);
    for (Class<?> clazz : classes) {
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            if ((introductionAwareMethodMatcher != null &&
                    introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
                    methodMatcher.matches(method, targetClass)) {
                return true;
            }
        }
    }
    return false;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末讥蔽,一起剝皮案震驚了整個(gè)濱河市涣易,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌冶伞,老刑警劉巖都毒,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異碰缔,居然都是意外死亡账劲,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門金抡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)瀑焦,“玉大人,你說(shuō)我怎么就攤上這事梗肝¢晃停” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵巫击,是天一觀的道長(zhǎng)禀晓。 經(jīng)常有香客問(wèn)我,道長(zhǎng)坝锰,這世上最難降的妖魔是什么粹懒? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮顷级,結(jié)果婚禮上凫乖,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好帽芽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布删掀。 她就那樣靜靜地躺著,像睡著了一般导街。 火紅的嫁衣襯著肌膚如雪披泪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,573評(píng)論 1 305
  • 那天搬瑰,我揣著相機(jī)與錄音付呕,去河邊找鬼。 笑死跌捆,一個(gè)胖子當(dāng)著我的面吹牛徽职,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播佩厚,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼姆钉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了抄瓦?” 一聲冷哼從身側(cè)響起潮瓶,我...
    開(kāi)封第一講書(shū)人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎钙姊,沒(méi)想到半個(gè)月后毯辅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡煞额,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年思恐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片膊毁。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡胀莹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出婚温,到底是詐尸還是另有隱情描焰,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布栅螟,位于F島的核電站荆秦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏力图。R本人自食惡果不足惜步绸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望搪哪。 院中可真熱鬧靡努,春花似錦、人聲如沸晓折。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)漓概。三九已至漾月,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胃珍,已是汗流浹背梁肿。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留觅彰,地道東北人吩蔑。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像填抬,于是被迫代替她去往敵國(guó)和親烛芬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355