讨论AspectJ之target、this、within关键字差异性

今天学习了一下AspectJ,查看了官方文档,查阅了很多其他技术博客,发现大部分人对关键字target、this、within之间差异不是特别清楚,所以引入本文来详细讨论它们之间的区别。特别介绍http://blog.csdn.net/zl3450341/article/details/7673979此文,本片验证思路来源于此并做了扩充说明。

 

1.首先,AspectJ官方怎么描述这三个关键字:

this(SomeType):when the object currently executing (i.e. this) is of type SomeType

当前执行对象是否是某种类型

target(SomeType):when the target object is of type SomeType

目标对象是否是某种类型

within(MyClass):when the executing code belongs to class MyClass

当前执行代码是否属于某个类

此处需要注意的是"对象是否是某种类型"A和“执行代码属于某个类的区别”B,描述A应该具有面向对象特性(继承)。

 

2.其次,关于call与execution两个关键字

execution(void Point.setX(int)):when a particular method body executes

当特定方法体执行时

call(void Point.setX(int)):when a method is called

当一个方法被调用时

此处不同的切点类型对后面使用this与within时的语义理解有影响

 

3.测试验证

基础类

public interface Animal

{

    public void move();

}

 

public class Snake implements Animal

{

 

    @Override

    public void move()

    {

        System.out.println("snake is crawling.");

        System.out.println();

    }

}

 

public class Bird implements Animal

{

 

    @Override

    public void move()

    {

        System.out.println("bird is flying.");

        System.out.println();

    }

}

 

public class TestDifferentBetweenThisTargetWithin

{

    private List<Animal> animals = new ArrayList<Animal>();

 

    @Before

    public void setUp()

    {

        animals.clear();

        animals.add(new Bird());

        animals.add(new Snake());

    }

 

    public void move()

    {

        for (Animal a : animals)

        {

            a.move();

        }

    }

 

    @Test

    public void testDifferent()

    {

        move();

    }

}

 

AspectJ相关

public aspect AspectDifferent

{

 pointcut moveCall():call(public void move()) 

 pointcut moveExecution():execution(public void move())

 

before() :moveCall()

    {

        System.out.println();

        System.out.println("thisJoinPoint:" + thisJoinPoint);

        System.out.println("Kind:" + thisJoinPoint.getKind());

        System.out.println("Target:" + thisJoinPoint.getTarget().getClass());

        System.out.println("This:" + thisJoinPoint.getThis().getClass());

        System.out.println("SourceLineNumber:" + thisJoinPoint.getSourceLocation());

    }

 

before() :moveExecution()

    {

        System.out.println();

        System.out.println("thisJoinPoint:" + thisJoinPoint);

        System.out.println("Kind:" + thisJoinPoint.getKind());

        System.out.println("Target:" + thisJoinPoint.getTarget().getClass());

        System.out.println("This:" + thisJoinPoint.getThis().getClass());

        System.out.println("SourceLineNumber:" + thisJoinPoint.getSourceLocation());

    }

 

4.测试结果(有点多,看起来有点花眼,请仔细看target object与this object的信息,特别是使用call与execution对this的影响):

 

1 pointcut moveCall():call(public void move());拦截到的方法数为3

切点语义描述:所有调用公开的没有返回值的名为move的方法

输出结果:

thisJoinPoint:call(void aspectJ.test.TestDifferentBetweenThisTargetWithin.move())

Kind:method-call

Target:class aspectJ.test.TestDifferentBetweenThisTargetWithin

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

 

thisJoinPoint:call(void aspectJ.Animal.move())

Kind:method-call

Target:class aspectJ.Bird

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

bird is flying.

 

thisJoinPoint:call(void aspectJ.Animal.move())

Kind:method-call

Target:class aspectJ.Snake

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

snake is crawling.

 

2 pointcut moveCall():call(public void move()) && target(Animal);方法数2

语义描述:所有调用公开的没有返回值的名为move的方法并且目标对象是Animal类型

输出结果:

thisJoinPoint:call(void aspectJ.Animal.move())

Kind:method-call

Target:class aspectJ.Bird

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

bird is flying.

 

 

thisJoinPoint:call(void aspectJ.Animal.move())

Kind:method-call

Target:class aspectJ.Snake

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

snake is crawling.

 

3 pointcut moveCall():call(public void move()) && target(Bird);方法数1

语义描述:所有调用公开的没有返回值的名为move的方法并且目标对象是Bird类型

输出结果:

thisJoinPoint:call(void aspectJ.Animal.move())

Kind:method-call

Target:class aspectJ.Bird

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

bird is flying.

 

snake is crawling.

 

4 pointcut moveCall():call(public void move()) && target(Snake);方法数1

语义描述:所有调用公开的没有返回值的名为move的方法并且目标对象是Snake类型

输出结果:

bird is flying.

 

 

thisJoinPoint:call(void aspectJ.Animal.move())

Kind:method-call

Target:class aspectJ.Snake

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

snake is crawling.

 

5 pointcut moveCall():call(public void move()) && target(TestDifferentBetweenThisTargetWithin);方法数1

语义描述:所有调用公开的没有返回值的名为move的方法并且目标对象是TestDifferentBetweenThisTargetWithin类型

输出结果:

thisJoinPoint:call(void aspectJ.test.TestDifferentBetweenThisTargetWithin.move())

Kind:method-call

Target:class aspectJ.test.TestDifferentBetweenThisTargetWithin

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

 

bird is flying.

 

snake is crawling.

 

6 pointcut moveCall():call(public void move()) && this(Animal);方法数0

语义描述:所有调用公开的没有返回值的名为move的方法并且当前执行调用对象是Animal类型

输出结果:

bird is flying.

 

snake is crawling.

 

7 pointcut moveCall():call(public void move()) && this(Bird); 方法数0

语义描述:所有调用公开的没有返回值的名为move的方法并且当前执行调用对象是Bird类型

输出结果:

bird is flying.

 

snake is crawling.

 

8 pointcut moveCall():call(public void move()) && this(Snake);方法数0

语义描述:所有调用公开的没有返回值的名为move的方法并且当前执行调用对象是Snake类型

输出结果:

bird is flying.

 

snake is crawling.

 

9 pointcut moveCall():call(public void move()) && this(TestDifferentBetweenThisTargetWithin);方法数3

语义描述:所有调用公开的没有返回值的名为move的方法并且当前执行调用对象是TestDifferentBetweenThisTargetWithin类型

输出结果:

thisJoinPoint:call(void aspectJ.test.TestDifferentBetweenThisTargetWithin.move())

Kind:method-call

Target:class aspectJ.test.TestDifferentBetweenThisTargetWithin

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

 

 

thisJoinPoint:call(void aspectJ.Animal.move())

Kind:method-call

Target:class aspectJ.Bird

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

bird is flying.

 

 

thisJoinPoint:call(void aspectJ.Animal.move())

Kind:method-call

Target:class aspectJ.Snake

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

snake is crawling.

 

10 pointcut moveCall():call(public void move()) && within(Animal);方法数0

语义描述:所有调用公开的没有返回值的名为move的方法并且当前执行调用的代码属于Animal类

输出结果:

bird is flying.

 

snake is crawling.

 

11 pointcut moveCall():call(public void move()) && within(Bird);方法数0

语义描述:所有调用公开的没有返回值的名为move的方法并且当前执行调用的代码属于Bird类

输出结果:

bird is flying.

 

snake is crawling.

 

12 pointcut moveCall():call(public void move()) && within(Snake);方法数0

语义描述:所有调用公开的没有返回值的名为move的方法并且当前执行调用的代码属于Snake类

输出结果:

bird is flying.

 

snake is crawling.

 

13 pointcut moveCall():call(public void move()) && within(TestDifferentBetweenThisTargetWithin);方法数3

语义描述:所有调用公开的没有返回值的名为move的方法并且当前执行调用的代码属于TestDifferentBetweenThisTargetWithin类

输出结果:

thisJoinPoint:call(void aspectJ.test.TestDifferentBetweenThisTargetWithin.move())

Kind:method-call

Target:class aspectJ.test.TestDifferentBetweenThisTargetWithin

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

 

 

thisJoinPoint:call(void aspectJ.Animal.move())

Kind:method-call

Target:class aspectJ.Bird

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

bird is flying.

 

 

thisJoinPoint:call(void aspectJ.Animal.move())

Kind:method-call

Target:class aspectJ.Snake

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

snake is crawling.

 

14 pointcut moveExecution():execution(public void move());方法数3

语义描述:所有公开的没有返回值的名为move的执行方法体

输出结果:

thisJoinPoint:execution(void aspectJ.test.TestDifferentBetweenThisTargetWithin.move())

Kind:method-execution

Target:class aspectJ.test.TestDifferentBetweenThisTargetWithin

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

 

 

thisJoinPoint:execution(void aspectJ.Bird.move())

Kind:method-execution

Target:class aspectJ.Bird

This:class aspectJ.Bird

bird is flying.

 

 

thisJoinPoint:execution(void aspectJ.Snake.move())

Kind:method-execution

Target:class aspectJ.Snake

This:class aspectJ.Snake

snake is crawling.

 

15 pointcut moveExecution():execution(public void move()) && target(Animal); 方法数2

语义描述:所有公开的没有返回值的名为move的执行方法体并且目标对象是Animal

输出结果:

thisJoinPoint:execution(void aspectJ.Bird.move())

Kind:method-execution

Target:class aspectJ.Bird

This:class aspectJ.Bird

bird is flying.

 

 

thisJoinPoint:execution(void aspectJ.Snake.move())

Kind:method-execution

Target:class aspectJ.Snake

This:class aspectJ.Snake

snake is crawling.

 

16 pointcut moveExecution():execution(public void move()) && target(Bird); 方法数1

语义描述:所有公开的没有返回值的名为move的执行方法体并且目标对象是Bird

输出结果:

thisJoinPoint:execution(void aspectJ.Bird.move())

Kind:method-execution

Target:class aspectJ.Bird

This:class aspectJ.Bird

bird is flying.

 

snake is crawling.

 

17 pointcut moveExecution():execution(public void move()) && target(Snake); 方法数1

语义描述:所有公开的没有返回值的名为move的执行方法体并且目标对象是Snake

输出结果:

bird is flying.

 

 

thisJoinPoint:execution(void aspectJ.Snake.move())

Kind:method-execution

Target:class aspectJ.Snake

This:class aspectJ.Snake

snake is crawling.

 

18 pointcut moveExecution():execution(public void move()) && target(TestDifferentBetweenThisTargetWithin);方法数1

语义描述:所有公开的没有返回值的名为move的执行方法体并且目标对象是TestDifferentBetweenThisTargetWithin

输出结果:

thisJoinPoint:execution(void aspectJ.test.TestDifferentBetweenThisTargetWithin.move())

Kind:method-execution

Target:class aspectJ.test.TestDifferentBetweenThisTargetWithin

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

 

bird is flying.

 

snake is crawling.

 

19 pointcut moveExecution():execution(public void move()) && this(Animal);方法数2

语义描述:所有公开的没有返回值的名为move的执行方法体并且执行这个执行方法体动作的对象是Animal类型,也就是说当前实例方法体的实例主体是Animal类型

输出结果:

thisJoinPoint:execution(void aspectJ.Bird.move())

Kind:method-execution

Target:class aspectJ.Bird

This:class aspectJ.Bird

bird is flying.

 

 

thisJoinPoint:execution(void aspectJ.Snake.move())

Kind:method-execution

Target:class aspectJ.Snake

This:class aspectJ.Snake

snake is crawling.

 

20 pointcut moveExecution():execution(public void move()) && this(Bird);方法数1

语义描述:所有公开的没有返回值的名为move的执行方法体并且执行这个执行方法体动作的对象是Bird类型,也就是说当前实例方法体的实例主体是Bird类型

输出结果:

thisJoinPoint:execution(void aspectJ.Bird.move())

Kind:method-execution

Target:class aspectJ.Bird

This:class aspectJ.Bird

bird is flying.

 

snake is crawling.

 

21 pointcut moveExecution():execution(public void move()) && this(Snake); 方法数1

语义描述:所有公开的没有返回值的名为move的执行方法体并且执行这个执行方法体动作的对象是Snake类型,也就是说当前实例方法体的实例主体是Snake类型

输出结果:

bird is flying.

 

 

thisJoinPoint:execution(void aspectJ.Snake.move())

Kind:method-execution

Target:class aspectJ.Snake

This:class aspectJ.Snake

snake is crawling.

 

22 pointcut moveExecution():execution(public void move()) && this(TestDifferentBetweenThisTargetWithin);方法数1

语义描述:所有公开的没有返回值的名为move的执行方法体并且执行这个执行方法体动作的对象是TestDifferentBetweenThisTargetWithin类型,也就是说当前实例方法体的实例主体是TestDifferentBetweenThisTargetWithin类型

输出结果:

thisJoinPoint:execution(void aspectJ.test.TestDifferentBetweenThisTargetWithin.move())

Kind:method-execution

Target:class aspectJ.test.TestDifferentBetweenThisTargetWithin

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

 

bird is flying.

 

snake is crawling.

 

23 pointcut moveExecution():execution(public void move()) && within(Animal);方法数0

语义描述:所有公开的没有返回值的名为move的执行方法体并且这个方法体执行代码是属于Animal类

输出结果:

bird is flying.

 

snake is crawling.

 

24 pointcut moveExecution():execution(public void move()) && within(Bird); 方法数1

语义描述:所有公开的没有返回值的名为move的执行方法体并且这个方法体执行代码是属于Bird类

输出结果:

thisJoinPoint:execution(void aspectJ.Bird.move())

Kind:method-execution

Target:class aspectJ.Bird

This:class aspectJ.Bird

bird is flying.

 

snake is crawling.

 

25 pointcut moveExecution():execution(public void move()) && within(Snake); 方法数1

语义描述:所有公开的没有返回值的名为move的执行方法体并且这个方法体执行代码是属于Snake类

输出结果:

bird is flying.

 

 

thisJoinPoint:execution(void aspectJ.Snake.move())

Kind:method-execution

Target:class aspectJ.Snake

This:class aspectJ.Snake

snake is crawling.

 

26 pointcut moveExecution():execution(public void move()) && within(TestDifferentBetweenThisTargetWithin);方法数1

语义描述:所有公开的没有返回值的名为move的执行方法体并且这个方法体执行代码是属于TestDifferentBetweenThisTargetWithin类

输出结果:

thisJoinPoint:execution(void aspectJ.test.TestDifferentBetweenThisTargetWithin.move())

Kind:method-execution

Target:class aspectJ.test.TestDifferentBetweenThisTargetWithin

This:class aspectJ.test.TestDifferentBetweenThisTargetWithin

 

bird is flying.

 

snake is crawling.

 

5.测试结论:

无论是使用call还是execution类型pointcut,target对象均不会受影响,target可以理解为拥有move方法(move方法在某个类中定义)的实例是什么类型。(所以2,15;3,16;4,17;5,18结果相同)

 

使用call类型 pointcut时,this可以理解为调用move这个方法的实例是什么类型。(上面测试中所有call的this object都是TestDifferentBetweenThisTargetWithin,所以6,7,8均没有拦截到方法,9拦截数量为3)

 

使用execution类型 pointcut时,this可以理解为拥有move方法(move方法在某个类中定义)的实例是什么类型,与target相同(19,20,21,22)。

 

Target与this均支持继承(描述都是“是什么类型“),within不支持(描述是”代码属于哪个类“)。

 

上面测试中所有调用move方法都是TestDifferentBetweenThisTargetWithin,所以10,11,12拦截数为0, 13拦截数为3

 

上面测试用所有move方法的执行都是在各自类中,所以23拦截数为0, 24,25,26拦截数分别为1

 

以上所有欢迎讨论。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值