使用方面记录

时间:2012-10-31 11:48:31

标签: java spring aop aspectj

使用Facade图层,服务图层和Dao图层建立RESTful web-serice。 尝试记录所有类的方法的所有调用,用注释@Log

标记
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
}

这是方面代码:

public class LoggingAspect {
  @Around("@target(Log)")
  public Object log(ProceedingJoinPoint pjp) throws Throwable {
    log.debug("Start " + pjp.getSignature().getName());
    Object result = pjp.proceed();
    log.debug("End " + pjp.getSignature().getName());
    return result;
  }
}

Facade,Service和Dao标有@Log。 一些例子:

public Obj Facade.createObj(String name){ //1
  return service.createObj(name);
}

public Obj Service.createObj(String name){ //2
  return dao.createObj(name);
}

public Obj Dao.createObj(String name){ //3
  Long idOfCreatedObj = /*code that creates an object and returns it's ID*/;
  return loadObjById(idOfCreatedObj); /* load the created object by id */
}

public Obj Dao.loadObjById(Long id){ //4
  return /* code that loads the object by it's id */;
}

在此示例中,方法1,2,3成功记录。但是不会记录嵌套的dao方法(loadObjById)。

为什么?

P.S。在spring-config.xml中有     <aop:aspectj-autoproxy proxy-target-class="true"/>

1 个答案:

答案 0 :(得分:2)

问题是自我调用(this.methodcall())绕过Spring创建的动态/ cglib代理来处理交叉问题。

修复要么使用完整的Aspectj(编译时间或加载时间编织),要么通过获取代理来进行调用(而不是联合this.methodCall(),使用proxy.methodCall()

您可以通过这种方式获取代理:

<aop:aspectj-autoproxy expose-proxy="true"/>

在您的代码中:AopContext.currentProxy()会为您提供代理的引用。如果您有兴趣,请参阅以下一篇博客文章 - http://www.java-allandsundry.com/2012/07/reference-to-dynamic-proxy-in-proxied.html