Spring AOP target()vs this()

时间:2012-08-12 18:28:44

标签: spring spring-aop

来自Spring Documentation

  • 代理所在的任何连接点(仅在Spring AOP中执行的方法) 实现AccountService接口:

    this(com.xyz.service.AccountService)
    
  • 目标所在的任何连接点(仅在Spring AOP中执行的方法) object实现AccountService接口:

    target(com.xyz.service.AccountService)
    

我不明白“目标对象”和表达式target(...)是什么意思。

targetthis的区别如何?

5 个答案:

答案 0 :(得分:21)

this(AType)表示this instanceof AType为真的所有加入点。所以这意味着,在您的情况下,一旦调用达到AccountService this instanceof AccountService的任何方法都将为真。

target(AType)表示anObject instanceof AType所有加入点。如果要在对象上调用方法,并且该对象是AccountService的实例,那么它将是一个有效的连接点。

总结一种不同的方式 - this(AType)来自接收者的角度,target(AType)来自呼叫者的角度。

答案 1 :(得分:10)

我知道这是一篇很老的帖子,但我在没有使用AspectJ时遇到了这个和目标之间的重要区别。

考虑以下介绍方面:

@Aspect
public class IntroductionsAspect {

    @DeclareParents(value="a.b.c.D", defaultImpl=XImpl.class)
    public static X x;

    @After("execution(* a.b.c.D.*(..)) && this(traceable)")
    public void x(Traceable traceable) {
        traceable.increment();
    }

}

简而言之,这方面做了两件事:

  1. 使a.b.c.D类实现X接口。
  2. traceable.increment()的每个方法之前添加对a.b.c.D的调用。
  3. 重要的部分是"execution(* a.b.c.D.*(..)) && this(traceable)"。请注意,我使用,而不是目标

    如果您使用目标,则尝试匹配原始类a.b.c.D,而不是引入的接口X。所以Spring AOP在a.b.c.D中找不到任何连接点。

    总结:

    - 检查代理类型或引入的类型。 目标 - 检查声明的类型。

答案 2 :(得分:6)

来自官方文件:

  

Spring AOP是一个基于代理的系统,它区分代理对象本身(绑定到'这个')和代理背后的目标对象(绑定到' target')。

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-pointcuts-designators

答案 3 :(得分:0)

我试图给出目标和这个切入点指示符的外行代码。已经为时已晚,但希望对某人有所帮助。

方面的课程

package com.opensource.kms;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class SecurityService {

    @Pointcut("target(com.opensource.kms.FooDao)")
    public void myPointCut1() {}

    @Pointcut("this(com.opensource.kms.SooDao)")
    public void myPointCut2() {}

    @Before("myPointCut1()")
    public void beforeMethodTarget() {
        System.out.println("beforeMethodTarget myPointCut1");
    }

    @Before("myPointCut2()")
    public void beforeMethodThis() {
        System.out.println("beforeMethodThis myPointCut2");
    }
}

FooDao类:JDK动态代理

package com.opensource.kms;
import org.springframework.stereotype.Component;

interface BarDao {
    String m();
}

@Component
public class FooDao implements BarDao {

    public String m() {
        System.out.println("implementation of m");
        return "This is return value";
    }
}

SooDao类:CGLIB代理

package com.opensource.kms;
import org.springframework.stereotype.Component;

@Component
public class SooDao {

    public String m() {
        System.out.println("implementation of m : SooDao");
        return "This is return value";
    }
}

主应用

    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
    SooDao ob1 = ctx.getBean("sooDao", SooDao.class);
    System.out.println("Data using this ->"+ob1.m());
    System.out.println("********************");
    BarDao ob2 = ctx.getBean("fooDao", BarDao.class);
    System.out.println("Data using target -> "+ob2.m());

输出

beforeMethodThis myPointCut2
implementation of m : SooDao
Data using this ->This is return value
********************
beforeMethodTarget myPointCut1
implementation of m
Data using target -> This is return value

答案 4 :(得分:0)

当涉及到 AOP 编程时,这个话题常常是一个混乱的来源。我在网上找到了一个很好的摘录解释,总结了差异:

<块引用>

this 限制匹配连接点,其中 bean 引用是给定类型的实例,而 target 限制匹配连接 目标对象是给定类型的实例的点。这 前者在 Spring AOP 创建基于 CGLIB 的代理时起作用,而 后者在创建基于 JDK 的代理时使用。

假设目标类实现了一个接口:

public class FooDao implements BarDao {
    ...
}

在这种情况下,Spring AOP 将使用基于 JDK 的代理,您应该 使用目标 PCD,因为代理对象将是 代理类并实现BarDao接口:

@Pointcut("target(com.baeldung.pointcutadvice.dao.BarDao)")

另一方面,如果 FooDao 没有实现任何接口或 proxyTargetClass 属性设置为 true 则代理对象将 是 FooDao 的子类,可以使用这个 PCD:

@Pointcut("this(com.baeldung.pointcutadvice.dao.FooDao)")

您可以通过以下链接了解更多信息:

Introduction to Pointcut Expressions in Spring