论坛首页 Java企业应用论坛

谁能说说@AspectJ中this和target这两个切点标识符的具体区别

浏览 5725 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-01-23  
   Spring Reference对这两个切点标识符的用法描述得不太清楚:
引用
this - limits matching to join points (the execution of methods when using Spring AOP) where the bean
reference (Spring AOP proxy) is an instance of the given type
• target - limits matching to join points (the execution of methods when using Spring AOP) where the target
object (application object being proxied) is an instance of the given type

   似乎看不出两者的具体区别,我试着做了一个测试:
   切面定义类:

package com.baobaotao.expression;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class PreGreetingAspect{
	@Before("target(com.baobaotao.expression.NaiveWaiter)")
	public void beforeGreeting(){
		System.out.println("How are you");
	}
}

目标类接口:
package com.baobaotao.expression;

public interface Waiter {
	public void greetTo(String name);	
	public void serveTo(String name);
}

目标接口实现类:
package com.baobaotao.expression;

public class NaiveWaiter implements Waiter {
	public void greetTo(String name) {
		System.out.println("greet to "+name+"...");
	}	
	public void serveTo(String name){
		System.out.println("serving "+name+"...");
                   foo(name);
	}
	public void foo(String name){
		System.out.println("foo "+name+"...");
	}	
}


然后是配置:
<aop:aspectj-autoproxy />
<bean id="waiter" class="com.baobaotao.expression.NaiveWaiter" />
<bean id="greetingAfter" class="com.baobaotao.expression.PreGreetingAspect" />	

最后是测试:
package com.baobaotao.expression;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.baobaotao.expression.Waiter;
public class TestExpression {
	public static void main(String[] args) {
		String configPath = "com/baobaotao/expression/beans.xml";
		ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
		Waiter waiter = (Waiter)ctx.getBean("waiter");
		waiter.greetTo("John");
		waiter.serveTo("John");
	}
}

输出以下信息:
How are you
greet to John...
How are you
serving John...

将切点定义换成:
@Before("this(com.baobaotao.expression.Waiter)")
输出的效果是完全一样的。
  我的分析:
我本来以为NaiveWaiter的foo()方法在使用@Before("target(com.baobaotao.expression.NaiveWaiter)")应该也可以织入切面,但是发现不管采用哪种方式只能为Waiter接口织入切面。
   请问这两个切点表示符到底有什么区别,我现在看到的是两者好象完全一样。

   发表时间:2007-01-23  
this标示调用方,target标示被调用方.
0 请登录后投票
   发表时间:2007-01-23  
谢谢partech是回答
partech 写道
this标示调用方,target标示被调用方.

可是,象我的例子中Waiter是引用类型,而NaiveWaiter是被调用类型,但以下四种方式定义的切面效果都是一样的:


    @Before("target(com.baobaotao.expression.NaiveWaiter)")
    @Before("target(com.baobaotao.expression.Waiter)")
    @Before("this(com.baobaotao.expression.NaiveWaiter)")
    @Before("this(com.baobaotao.expression.Waiter)")

 
不知道this和target究竟应用场合有什么区别,我们怎么看到它们不同的效果?
0 请登录后投票
   发表时间:2007-01-23  
this和target通常用来限定切点的作用域,单独使用,俺想不出场景,你在pointcut上加个call试一下。
0 请登录后投票
   发表时间:2007-01-23  
越分析,越觉得两者越没有区别,假设我有二个类,他们分别实现一个接口:
  Waiter
    |_NaiveWaiter
    |_NaughtWaiter
我以下的切点定义都是等效的:
           this(Waiter) 
    <==> target(Waiter) 
    <==> target(NaiveWaiter) || target(NaughtWaiter)
    <==> this(NaiveWaiter)   || this(NaughtWaiter)

Spring中配置的:
引用

<bean id="waiter1" class="com.baobaotao.expression.NaiveWaiter" />
<bean id="waiter2" class="com.baobaotao.expression.NaughtyWaiter" />

这两个Bean的方法都会被代理。

   我都快要疯了  ,难道真的没有区别吗?应该是不会的,可是到底如何分辨呢,难,难,难!
0 请登录后投票
   发表时间:2007-01-23  
目前我的结论是:this这个切点标识符是Spring的一个Bug。开发文档上说this用于指定代理对象的类型,而实际上它用于指示代理目标类的类型,所以完全和target一样了。这是我的实验结果,不知道大家有何高见。
0 请登录后投票
   发表时间:2007-01-23  
是不是spring的bug,我就不清楚了。
附件是直接使用aspectj的验证。
输出:
C1.f1
before thisC1PointCut
before targetC2PointCut
C2.f1
0 请登录后投票
   发表时间:2007-01-23  
   TMD,终于搞定了,是这样的:
   @Before"this(com.baobaotao.Seller)"
   void test(){}
   表示这样的情况,某个目标类如 NaiveWaiter所生成的代理对象是Seller类型,则NaiveWaiter上的所有方法织入test()方法,这种情况一般用于引入增强的情况,引入可以为目标类添加某一个接口的实现,如:

package com.baobaotao.expression;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.DeclareParents;
@Aspect
public class PreGreetingAspect {
	@DeclareParents(value = "com.baobaotao.expression.*", defaultImpl = GoodSeller.class)
	public static Seller seller;
	@Before(" execution(* greetTo(..)) && this(com.baobaotao.expression.Seller)")
	public void recordUsage() {
		System.out.println("Haha");
	}
}


为com.baobaotao.expression包下的所有类引入Seller接口的实现,这样代理对象就都是Seller类型了,因此
@Before(" execution(* greetTo(..)) && this(com.baobaotao.expression.Seller)")
匹配目标类的所有greetTo()方法,这里,要是我们把它改为:
@Before(" execution(* greetTo(..)) && target(com.baobaotao.expression.Seller)")

目标类的greetTo()方法就得不到增强了。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics