AspectJ - 方法@around未调用

时间:2017-03-13 14:51:24

标签: java logging aspectj aspect

我想使用AspetcJ插入位于log4J文件中的org.apache.log4j.Category.java方法。

protected void forcedLog(String fqcn, Priority level, Object message, Throwable t) {
    callAppenders(new LoggingEvent(fqcn, this, level, message, t));
  }

最后那个

@Around("execution(protected void org.apache.log4j.Category.*(..))

会起作用。

我有什么问题?

我的方面不会被召唤。

所以我做了更简单的例子 - 它也没有被调用。

core.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans 
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"    
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- <aop:aspectj-autoproxy /> -->

    <context:load-time-weaver/>


    <!-- Aspect -->
    <!--  
    <bean id="beanName"  class="class.sth.ClazzName" />
    <bean id="beanName2"  class="class.sth.Clazz2Name" />
    -->

<!-- other beans - not aspects -->
    </beans>

aop.xml

<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>

    <weaver>
        <!-- only weave classes in our application-specific packages -->
         <include within="*"/>
    <exclude within="org.jibx*"/>
    </weaver>

    <aspects>
        <!-- weave in just this aspect -->
        <aspect name="class.sth.ClazzName"/>
        <aspect name="class.sth.Clazz2Name"/>
    </aspects>

</aspectj>

当我运行JUnit测试时应调用的示例java类 - 其中我明显看到这行代码被执行:

System.out.println("test");

我仍然没有看到我的方面被调用。

@Aspect
@Order(3)
public class ClazzName {

    @Around("call(* *println(..))")
    public void testMethod(ProceedingJoinPoint joinPoint) {
        Object o = joinPoint.getArgs();
        System.out.println("test");
    }
}

在同一JUnit test其他方面的我的应用程序中被调用。 这可以告诉我们,我们在项目中有很好的依赖关系。

@Aspect
@Order(2)
public class Clazz2Name {


    @Around("@annotation(loggable)")
    public Object doStuff(ProceedingJoinPoint joinPoint, Clazz2Name log) throws Throwable{
        ...
    }

    ...

我的课程并不总是标记为@Component,我希望保持这种状态。

JUnit VM arguments

-javaagent:C:\aspectjWeaver\spring-instrument-3.0.4.jar

问题是如何实现我的目标并让我的方面在我想要的时候被调用?

1 个答案:

答案 0 :(得分:1)

您实际上至少存在以下问题:

  1. 您没有阅读Spring AOP文档。 (对不起,无法抗拒。)
  2. 您正在使用Spring AOP,而不是完整的AspectJ。不同之处在于前者仅适用于Spring组件,但Log4J不是Spring组件。因此,如果您想使其工作,您需要通过加载时编织使用完整的AspectJ,如Spring手册第11.8节所述,secsion Using AspectJ with Spring applications
  3. 即使使用完整的AspectJ,您也需要知道您无法挂钩执行JDK方法,因为在实例化方面编织器之前已经加载了这些方法。因此,您应该通过call(* println(..))挂钩方法调用,而不是方法执行。
  4. 我不明白为什么你想要挂钩到Log4J和JDK方法。您想将呼叫重定向到其他频道吗?也许最好描述您实际想要实现的 ,而不是 您认为问题应该是什么解决。