基于@AspectJ和Schema的AOP

1.Spring對AOP的支持

  • 新增了基于Schema的配置支持籽腕,為AOP專門提供了aop命名空間
  • 新增了對AspectJ切點(diǎn)表達(dá)式語言的支持秕豫,
  • 可以無縫地集成AspectJ

2.Java5.0注解知識快速進(jìn)階

注解是代碼的附屬信息惜浅,它遵循一個(gè)基本原則:注解不能干擾程序代碼的運(yùn)行,無論增加或刪除注解,代碼都能夠正常運(yùn)行。Java語言解釋器會忽略這些注解惭聂,而由第三方工具負(fù)責(zé)對注解進(jìn)行處理。第三方工具可以利用代碼中的注解間接控制程序代碼的運(yùn)行相恃,它們通過Java反射機(jī)制讀取注解的信息辜纲,并根據(jù)這些信息更改目標(biāo)程序的邏輯,而這正是Spring AOP對@AspectJ提供支持所采取的辦法拦耐。

AspectJ實(shí)例的github地址

3.使用@AspectJ

@AspectJ采用注解來描述切點(diǎn)和增強(qiáng)

@Aspect//通過該注解將PreGreetingAspectJ標(biāo)識為一個(gè)切面
public class PreGreetingAspectJ {

    @Before("execution( * *To(..))")//定義切點(diǎn)和增強(qiáng)類型
    public void before() throws Throwable {//增強(qiáng)的橫切邏輯
        System.out.println("How are you! Mr");

    }
}

<?xml version="1.0" encoding="UTF-8"?>
<!-- Configures the Camel Context-->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
  <bean id="waiter" class="com.example.NativeWaiter"/>
  <bean class="com.example.beforeapsectJ.PreGreetingAspectJ"/>
   <!--方法一耕腾、自動代理創(chuàng)建器,自動將@AspectJ注解切面類織入目標(biāo)Bean中-->
  <!--<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/>-->
    <!--方法二杀糯、上面方法使用的是Annotation AspectJAutoProxy Creator能夠?qū)AspectJ注解切面類自動織入目標(biāo)Bean中扫俺,如果使用的是基于Schema的aop
        命名空間進(jìn)行配置,可以使用如下方法進(jìn)行配置-->
    <aop:aspectj-autoproxy/>
</beans>

4.@AspectJ語法基礎(chǔ)

4.1.切點(diǎn)表達(dá)式函數(shù)
  • 方法切點(diǎn)函數(shù):通過描述目標(biāo)類方法的信息定義連接點(diǎn)
  • 方法入?yún)⑶悬c(diǎn)函數(shù):通過描述目標(biāo)類方法入?yún)⒌男畔⒍x連接點(diǎn)
  • 目標(biāo)類切點(diǎn)函數(shù):通過描述目標(biāo)類類型的信息定義連接點(diǎn)
  • 代理類切點(diǎn)函數(shù):通過描述目標(biāo)類的代理類的信息定義連接點(diǎn)
4.2.在函數(shù)入?yún)⒅惺褂猛ㄅ浞?/h5>
    • :匹配任意字符固翰,但它只能匹配上下文中的一個(gè)元素
  • .. :匹配任意字符狼纬,可以匹配上下文中的多個(gè)元素,但在表示類時(shí)骂际,必須和*聯(lián)合使用畸颅,而在表示入?yún)r(shí)則單獨(dú)使用
    • :表示按類型匹配指定類的所有類,必須跟在類后面方援,如com.smart.Car+。繼承或擴(kuò)展指定類的所有類涛癌,同時(shí)還包括指定類本身
4.3.邏輯運(yùn)算符
  • && :與操作符犯戏,相當(dāng)于切點(diǎn)的交集運(yùn)算
  • || :或操作符,相當(dāng)于切點(diǎn)的并集運(yùn)算
  • 拳话! :非操作符先匪,相當(dāng)于切點(diǎn)的反集運(yùn)算
4.4.不同增強(qiáng)類型
  • @Before,前置增強(qiáng),相當(dāng)于BeforeAdvice弃衍,Before注解類擁有兩個(gè)成員

    • value:該成員用于定義切點(diǎn)
    • argNames:由于無法通過Java反射機(jī)制獲取方法入?yún)⒚椒牵匀绻贘ava編譯時(shí)未啟用調(diào)試信息,或者需要在運(yùn)行期解析切點(diǎn)镜盯,就必須通過這個(gè)成員指定注解所標(biāo)注增強(qiáng)方法的參數(shù)名(注意二者名字必須完全相同)岸裙,多個(gè)參數(shù)名用逗號分隔
  • @AfterReturning,后置增強(qiáng)速缆,相當(dāng)于AfterReturningAdvice降允,AfterReturning注解類擁有4個(gè)成員

    • value:該成員用于定義切點(diǎn)
    • pointcut:表示切點(diǎn)的信息,如果顯示指定pointcut值艺糜,那么它將覆蓋value的設(shè)置值剧董,可以將pointcut成員看做value的同義詞
    • returning:將目標(biāo)對象方法的返回值綁定給增強(qiáng)的方法
    • argNames:如上面所述(參數(shù)名)
  • @Around幢尚,環(huán)繞增強(qiáng),相當(dāng)于MethodInterceptor翅楼,Around注解類擁有兩個(gè)成員

    • value:該成員用于定義切點(diǎn)
    • argNames:如上面所述(參數(shù)名)
  • @AfterThrowing,拋出增強(qiáng)尉剩,相當(dāng)于ThrowsAdvice,AfterThrowing注解類擁有4個(gè)成員

    • value:該成員用于定義切點(diǎn)
    • pointcut:表示切點(diǎn)的信息毅臊,如果顯示指定pointcut值理茎,那么它將覆蓋value的設(shè)置值」游ⅲ可以將pointcut成員看作value的同義詞功蜓。
    • throwing:將拋出的異常綁定到增強(qiáng)的方法中
    • argNames:如上面所述(參數(shù)名)
  • @After,F(xiàn)inal增強(qiáng)宠蚂,不管是跑出異常還是正常退出式撼,該增強(qiáng)都會得到執(zhí)行,該增強(qiáng)沒有對應(yīng)的增強(qiáng)接口求厕,可以將它看成ThrowsAdvice和AfterReturningAdvice的混合物著隆,一般用于釋放資源,相當(dāng)于try{}finally{}的控制流呀癣。After注解類擁有兩個(gè)成員

    • value:該成員用于定義切點(diǎn)
    • argNames:如上面所述(參數(shù)名)
  • @DeclareParents,引介增強(qiáng)美浦,相當(dāng)于IntroductionInterceptor,DeclareParents注解類擁有兩個(gè)成員

    • value:該成員用于定義切點(diǎn)项栏,它表示在哪個(gè)目標(biāo)類上添加引介增強(qiáng)
    • defaultImpl:默認(rèn)的接口實(shí)現(xiàn)類

5.切點(diǎn)函數(shù)詳解

5.1.@annotation():表示標(biāo)注了注解的所有方法
@AspectJ
public class TestAspectJ {

    @AfterReturning("@annotation(com.example.annotationAspectJ.Override)")//后置增強(qiáng)切面
    public void needTestFun(){
        System.out.println("needTestFun() executed!");
    }
}

5.2.execution():其語法如下
execution(<修飾符模式>浦辨?<返回類型模式><方法名模式>(<參數(shù)模式>)<異常模式>?)
  • 通過方法簽名定義切點(diǎn)
    • execution(public (..)):匹配所有的目標(biāo)類的public方法,第一個(gè)代表返回
      類型沼沈,第二個(gè)
      代表方法名
    • execution(* TO(..)):匹配目標(biāo)類所有以To為后綴的方法流酬,第一個(gè)代表返回類
      型,而*To代表任意以To為后綴的方法
  • 通過類定義切點(diǎn)
    • execution(* com.example.Waiter.(..)):匹配Waiter接口的所有方法列另,第一個(gè)代表返回任意類型芽腾,com.example.Waiter.*代表接口中的所有方法
    • execution(* com.example.Waiter+.*):匹配Waiter接口及其所有實(shí)現(xiàn)類的方法,
  • 通過類包定義切點(diǎn)
    • execution(* com.example.*(..)):匹配com.example包下所有類的所有方法
    • execution(* com.example..*(..)):匹配com.example包页衙、子孫包下所有類的所有方法
    • execution(* com...Dao.finf*(..)):匹配包名前綴為com的任何包下類名后綴為Dao的方法摊滔,方法名必須以find為前綴
  • 通過方法入?yún)⒍x切點(diǎn)
    • execution(* joke(String,int)):匹配joke(String,int)方法,且joke()方法的第一個(gè)入?yún)⑹荢tring店乐,第二個(gè)入?yún)⑹莍nt艰躺,如果方法中入?yún)㈩愋褪莏ava.lang下的包可以直接使用類名;否則必須使用全限定類名
    • execution(* joke(String,*)):匹配目標(biāo)類中的joke()方法眨八,該方法第一個(gè)入?yún)镾tring,第二個(gè)入?yún)⒖梢允侨我忸愋?/li>
    • execution(* joke(String,..)):匹配目標(biāo)類中的joke()方法描滔,該方法的第一個(gè)入?yún)镾tring,后面可以有任意個(gè)入?yún)⑶胰雲(yún)㈩愋筒幌?/li>
    • execution(* joke(Object+)):匹配目標(biāo)類中的joke()方法踪古,方法擁有一個(gè)入?yún)⒑ぃ胰雲(yún)⑹荗bject類型或該類的子類
5.3.args()和@args()

args()函數(shù)入?yún)⑹穷惷唬鳣args()函數(shù)的入?yún)⒈仨毷亲⒔忸惖念惷km然args()允許在類名后使用"+"通配符拘泞,但該通配符在此處沒有意義纷纫,添加和不添加效果都一樣

  • args():該函數(shù)接收一個(gè)類名,表示目標(biāo)類方法入?yún)ο笫侵付?包含子類)時(shí)陪腌,切點(diǎn)匹配
  • @args():該函數(shù)接收一個(gè)注解類的類名辱魁,當(dāng)方法的運(yùn)行時(shí)入?yún)ο髽?biāo)注了指定的注解時(shí),匹配切點(diǎn)
5.4.within()

通過類匹配模式串聲明切點(diǎn)诗鸭,within()函數(shù)定義的連接點(diǎn)事針對目標(biāo)類而言的染簇,而非針對運(yùn)行期對象而言,within()所指定的連接點(diǎn)最小范圍只能是類强岸。

  • within(com.example.NativeWaiter):匹配目標(biāo)類NativeWaiter所有的方法
  • within(com.example.*):匹配com.example包中所有的類
  • within(com.example.**):匹配com.example包以及子孫包中的類
5.5.@within()和@target()

@within()和@target()只接受注解類名作為參數(shù)入?yún)⒍凸珸target(M)匹配任意標(biāo)注了@M目標(biāo)類,而@within(M)匹配標(biāo)注了@M的類及子孫類蝌箍,要注意青灼,如果標(biāo)注@M的是一個(gè)接口,那么@within和@target都不會起作用妓盲,因?yàn)锧within杂拨,@target以及@annotation函數(shù)都是針對目標(biāo)類而言的,而非針對運(yùn)行時(shí)引用類型而言的悯衬。

5.6.@target()和this()

target()切點(diǎn)函數(shù)通過判斷目標(biāo)類是否按類型匹配指定類來決定連接點(diǎn)是否匹配弹沽,而this()函數(shù)則通過判斷代理類是否按類型匹配指定類來決定是否和切點(diǎn)匹配

  • target():target(M)表示如果目標(biāo)類按類型匹配于M,則目標(biāo)類的所有方法都匹配切點(diǎn)
  • this():如果聲明一個(gè)切點(diǎn)tis(com.example.NativeWaiter),如果不使用CGLib動態(tài)代理筋粗,則生成的對象屬于Waiter類型策橘,而非NaiveWaiter(可以通過instanceof操作符來判斷),但是NaiveWaiter中所有方法都被織入了增強(qiáng)
@Aspect
public class TestAspect {
    //后期增強(qiáng)亏狰,織入任何運(yùn)行期對象為Seller類型的Bean中
    @AfterReturning("this(com.example.SmartSeller)")
    public void thisTest(){
        System.out.println("thisTest() executed()");
    }
}

6.@AspectJ進(jìn)階

@AspectJ可以使用切點(diǎn)函數(shù)定義切點(diǎn),還可以使用邏輯運(yùn)算符對切點(diǎn)進(jìn)行復(fù)合運(yùn)算得到復(fù)合切點(diǎn)偶摔。

6.1.切點(diǎn)復(fù)合運(yùn)算
@Aspect
public class TestAspectJ {

    @After("within(com.example.*)&&execution(* greetTo(..))")
    public void greetTo(){
        System.out.println("--greetToFun() executed!--");
    }

    @Before("!target(com.example.NativeWaiter)&&execution(* serverTo(..))")
    public void notServeInNaiveWaiter(){
        System.out.println("--notServeInNaiveWaiter--");
    }

    @AfterReturning("target(com.example.Waiter)||target(com.example.SmartSeller)")
    public void waiterOrSeller(){
        System.out.println("--waiterOrSell() executed!--");
    }
}
6.2.命名切點(diǎn)

切點(diǎn)可以直接聲明在增強(qiáng)方法處暇唾,這種切點(diǎn)聲明方式成為匿名切點(diǎn),匿名切點(diǎn)只能在聲明處使用辰斋。如果希望在其他地方重用一個(gè)切點(diǎn)策州,則可以通過@Pointcut注解及切面類方法對切點(diǎn)進(jìn)行命名。

public class TestNamePointcut {

    @Pointcut("within(com.example.*)")
    public void inPackage(){}//通過注解方法inPackage()對該切點(diǎn)進(jìn)行命名宫仗,方法可視域修飾符為private够挂,表明該命名切點(diǎn)只能在本切面類中使用

    @Pointcut("execution(* greetTo(..))")
    protected void greetTo(){}//通過注解該方法greetTo()對該切點(diǎn)進(jìn)行命名,方法可視域修飾符protected藕夫,表明該命名切點(diǎn)可以在當(dāng)前包中的切面類孽糖,子切面類中使用

    @Pointcut("inPackage()  greetTo()")
    public void inPkgGreetTo(){}//引用命名切點(diǎn)定義的切點(diǎn)枯冈,本切點(diǎn)也是命名切點(diǎn),它對應(yīng)的可視域?yàn)閜ublic
}

6.3.增強(qiáng)織入的順序

一個(gè)連接點(diǎn)可以同時(shí)匹配多個(gè)切點(diǎn)办悟,切點(diǎn)對應(yīng)的增強(qiáng)在連接點(diǎn)上的織入順序是如何安排呢?

  • 如果增強(qiáng)在同一個(gè)切面類中聲明尘奏,則依照增強(qiáng)在切面類中定義的順序進(jìn)行織入
  • 如果增強(qiáng)位于不同的切面類中,且這些切面類都實(shí)現(xiàn)了org.springframework.core.Ordered接口病蛉,則由接口方法的順序號決定(順序號小的先織入)
  • 如果增強(qiáng)位于不同的切面類中炫加,且這些切面類沒有實(shí)現(xiàn)org.springframework.core.Ordered接口,則織入的順序是不確定的
6.4.訪問連接點(diǎn)信息

AspectJ使用org.aspectj.lang.JointPoint接口表示目標(biāo)類連接點(diǎn)對象铺然。如果是環(huán)繞增強(qiáng)俗孝,則使用org.aspectj.lang.ProceedingJointPoint表示連接點(diǎn)對象,該類是JointPoint的子接口魄健。任何增強(qiáng)方法都可以通過將第一個(gè)入?yún)⒙暶鳛镴ointPoint訪問連接點(diǎn)上下文信息

  • JointPoint

    • java.lang.Object[].getArgs():獲取連接點(diǎn)方法運(yùn)行時(shí)的入?yún)⒘斜?/li>
    • Signature getSignature():獲取連接點(diǎn)的方法簽名對象
    • java.lang.Object getTarget():獲取連接點(diǎn)所在的目標(biāo)對象
    • java.lang.Object getThis():獲取代理對象本身
  • ProceedingJoinPoint

    • java.lang.Object proceed() throw java.lang.Throwable:通過反射執(zhí)行目標(biāo)
      對象連接點(diǎn)處的方法
    • java.lang.Object proceed(java.lang.Object[] args) throws java.lang.
      Throwable:通過反射執(zhí)行目標(biāo)對象連接點(diǎn)處的方法赋铝,不過使用新的參數(shù)替換原來的入?yún)?/li>
@Aspect
public class TestAspectJ {

    @After("within(com.example.*)&&execution(* greetTo(..))")
    public void greetTo(){
        System.out.println("--greetToFun() executed!--");
    }

    @Before("!target(com.example.NativeWaiter)&&execution(* serverTo(..))")
    public void notServeInNaiveWaiter(){
        System.out.println("--notServeInNaiveWaiter--");
    }

    @AfterReturning("target(com.example.Waiter)||target(com.example.SmartSeller)")
    public void waiterOrSeller(){
        System.out.println("--waiterOrSell() executed!--");
    }

    @Before("TestNamePointcut.inPkgGreetTo()")
    public void pkgGreetTo(){//引用TestNamePointcut.inPkgGreetTo()切點(diǎn)
        System.out.println("--pkgGreetTo() executed!--");
    }

    @Before("!target(com.example.NativeWaiter)&&TestNamePointcut.inPkgGreetTo()")
    public void pkgGreetToNoNaiveWaiter(){//在復(fù)合運(yùn)算中使用了命名切點(diǎn)
        System.out.println("--pkgGreetToNotNaiveWaiter() executed!--");
    }

    @Around("execution(* greetTo(..))&&target(com.example.NativeWaiter)")//環(huán)繞增強(qiáng)
    public void joinPointAccess(ProceedingJoinPoint joinPoint) throws Throwable {//聲明連接點(diǎn)入?yún)?        System.out.println("-------joinPointAccess-------");
        System.out.println("args[0]"+joinPoint.getArgs()[0]);
        System.out.println("signature"+joinPoint.getTarget().getClass());
        joinPoint.proceed();
        System.out.println("--------jointPointAccess-----------");


    }

}
6.5.綁定連接點(diǎn)方法入?yún)?/h5>

在介紹切點(diǎn)函數(shù)時(shí)說過args()诀艰、this()柬甥、target()、@args()其垄、@within()苛蒲、@target()和@annotaion()這7個(gè)函數(shù)除了可以指定類名外,還可以指定參數(shù)名绿满,將目標(biāo)對象連接點(diǎn)上的方法入?yún)⒔壎ǖ皆鰪?qiáng)的方法中臂外。

  • args:用于綁定連接點(diǎn)方法的入?yún)?/li>
  • @annotation:用于綁定連接點(diǎn)方法的注解對象
  • @args:用于綁定連接點(diǎn)方法入?yún)⒌淖⒔?/li>
/**
     * 綁定連接點(diǎn)參數(shù),首先args(name,num,..)根據(jù)增強(qiáng)方法入?yún)⒄业?     * name和num對應(yīng)的類型以得到真實(shí)的切點(diǎn)表達(dá)式喇颁,其次漏健,在該增強(qiáng)方
     * 法織入目標(biāo)連接點(diǎn)時(shí),增強(qiáng)方法可以通過num和name訪問到連接點(diǎn)的方法入?yún)?     * @param num
     * @param name
     */
    @Before("target(com.example.NativeWaiter)&&args(name,num,..)")

    public void bindJoinPointParams(int num,String name){//增強(qiáng)方法接受連接點(diǎn)的參數(shù)
        System.out.println("----bindJoinPointParams()----");
        System.out.println("name:"+name);
        System.out.println("num"+num);
        System.out.println("------bindJoinPointParams()---");
    }

6.6.綁定代理對象

使用this()或target()函數(shù)可綁定被代理對象實(shí)例橘霎,在通過類實(shí)例名綁定對象時(shí)蔫浆,依然具有原來連接點(diǎn)匹配的功能,只不過類名是通過增強(qiáng)方法中同名入?yún)⒌念愋烷g接決定罷了姐叁。

/**
     * 通過2處查找出waiter對應(yīng)的Waiter瓦盛,因而切點(diǎn)表達(dá)式為this(Waiter)
     * 當(dāng)增強(qiáng)方法織入目標(biāo)連接點(diǎn)時(shí),增強(qiáng)方法通過waiter入?yún)⒔壎繕?biāo)對象
     * @param waiter
     */
    @Before("this(waiter)")
    public void bindProxyObj(Waiter waiter){//2
        System.out.println("----bindProxyObj()----");
        System.out.println(waiter.getClass().getName());
        System.out.println("-----bindProxyObj()------");
    }

6.7.綁定類注解對象

@within()和@target()函數(shù)可以將目標(biāo)類的注解對象綁定到增強(qiáng)方法中

/**
     * 通過2處查找出n對應(yīng)NeedTest注解外潜,因而真實(shí)的切點(diǎn)表達(dá)式為@within(NeedTest)原环。
     * 當(dāng)增強(qiáng)方法織入目標(biāo)連接點(diǎn)時(shí),增強(qiáng)方法通過n入?yún)⒖梢砸玫竭B接點(diǎn)
     * @param n
     */
    @Before("@within(n)")
    public void bindTypeAnnoObject(NeedTest n){//2
        System.out.println("----bindTypeAnnoObject()----");
        System.out.println(n.getClass().getName());
        System.out.println("-----bindTypeAnnoObject()------");
    }
6.8.綁定返回值

在后置增強(qiáng)中处窥,可以通過returning綁定連接點(diǎn)方法的返回值

 @AfterReturning(value = "target(com.example.Waiter))",returning = "retVal")
    public void bindReturnValue(int retVal){
        System.out.println("--bindReturnValue--");
        System.out.println("returnValue"+retVal);
        System.out.println("--bindReturnValue--");
    }
6.9.綁定拋出的異常

和通過切點(diǎn)函數(shù)綁定連接點(diǎn)信息不同嘱吗,連接點(diǎn)拋出的異常必須使用AfterThrowing注解的throwing成員進(jìn)行綁定

@AfterThrowing(value = "target(com.example.Waiter))",throwing = "iae")
    public void bindException(IllegalArgumentException iae){
        System.out.println("--bindException--");
        System.out.println("exception:"+iae.getMessage());
        System.out.println("--bindException--");
    }

7.基于Schema配置切面

7.1.一個(gè)簡單切面的配置

  <aop:config proxy-target-class="true">
    <aop:aspect ref="adviceMethods">
      <aop:before pointcut="target(com.example.Waiter)) " method="preGreeting"/>
    </aop:aspect>

  </aop:config>
  <bean id="naiveWaiter" class="com.example.NativeWaiter"></bean>
  <bean id="adviceMethods" class="com.example.schemaAspectJ.AdviceMethods"></bean>
  
  public class AdviceMethods {

    public void preGreeting(){//該方法通過配置被用作增強(qiáng)的方法
        System.out.println("--how are you!--");
    }
}

7.2.配置命名切點(diǎn)
<aop:aspect ref="adviceMethods">
      <aop:before pointcut="target(com.example.Waiter)) and execution(* *(..))" method="preGreeting"/>
</aop:aspect>
<!--上面定義的是匿名切點(diǎn)-->

<aop:aspect ref="adviceMethods">
      <aop:pointcut id="greetpointcut" expression="target(com.example.Waiter)) and execution(* *(..))"/>
      <aop:before pointcut-ref="greetpointcut" method="preGreeting"/>
</aop:aspect>
<!--命名式切點(diǎn)的配置-->

8.混合切面類型

  • 基于@AspectJ注解方式
  • 基于<aop:aspect>的方式
  • 基于<aop:advisor>的方式
  • 基于Advisor類的方式

AspectJ實(shí)例的github地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市滔驾,隨后出現(xiàn)的幾起案子谒麦,更是在濱河造成了極大的恐慌俄讹,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弄匕,死亡現(xiàn)場離奇詭異颅悉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)迁匠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門剩瓶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人城丧,你說我怎么就攤上這事延曙。” “怎么了亡哄?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵枝缔,是天一觀的道長。 經(jīng)常有香客問我蚊惯,道長愿卸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任截型,我火速辦了婚禮趴荸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘宦焦。我一直安慰自己发钝,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布波闹。 她就那樣靜靜地躺著酝豪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪精堕。 梳的紋絲不亂的頭發(fā)上孵淘,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天,我揣著相機(jī)與錄音歹篓,去河邊找鬼瘫证。 笑死,一個(gè)胖子當(dāng)著我的面吹牛滋捶,可吹牛的內(nèi)容都是我干的痛悯。 我是一名探鬼主播余黎,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼重窟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了惧财?” 一聲冷哼從身側(cè)響起巡扇,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤扭仁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后厅翔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乖坠,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年刀闷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了熊泵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,703評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡甸昏,死狀恐怖顽分,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情施蜜,我是刑警寧澤卒蘸,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站翻默,受9級特大地震影響缸沃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜修械,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一趾牧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧祠肥,春花似錦武氓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至剂桥,卻和暖如春忠烛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背权逗。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工美尸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人斟薇。 一個(gè)月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓师坎,卻偏偏與公主長得像,于是被迫代替她去往敵國和親堪滨。 傳聞我的和親對象是個(gè)殘疾皇子胯陋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評論 2 353

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

  • AOP實(shí)現(xiàn)可分為兩類(按AOP框架修改源代碼的時(shí)機(jī)): 靜態(tài)AOP實(shí)現(xiàn):AOP框架在編譯階段對程序進(jìn)行修改遏乔,即實(shí)現(xiàn)...
    數(shù)獨(dú)題閱讀 2,317評論 0 22
  • 一义矛、增強(qiáng)類 1 前置增強(qiáng)(MethodBeforeAdvice)重寫before(Method method,Ob...
    Q南南南Q閱讀 1,210評論 0 0
  • 作者簡介:ASCE1885盟萨, 《Android 高級進(jìn)階》作者凉翻。本文由于潛在的商業(yè)目的,未經(jīng)授權(quán)不開放全文轉(zhuǎn)載許可...
    asce1885閱讀 2,384評論 0 7
  • 本章內(nèi)容: 面向切面編程的基本原理 通過POJO創(chuàng)建切面 使用@AspectJ注解 為AspectJ切面注入依賴 ...
    謝隨安閱讀 3,146評論 0 9
  • 測試同情心 文/趙元波 為了測試人們的同情心捻激,警察局讓一名兒童演員扮演的流浪男孩在人流如織的人行道旁的垃圾桶里不停...
    趙元波閱讀 230評論 0 0