AspectJ - 未调用方法@around
AspectJ - method @around not called
我想使用 AspetcJ
插入位于 org.apache.log4j.Category.java
文件中的 log4J
方法。
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>
示例 java class 应在我 运行 JUnit 测试时调用 - 其中清楚地看到执行了这行代码:
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{
...
}
...
我的 classes 并不总是标记为 @Component
,我想保持这种状态。
JUnit VM arguments
-javaagent:C:\aspectjWeaver\spring-instrument-3.0.4.jar
问题是我如何才能实现我的目标并让我的方面在我想要的时候被调用?
您实际上至少存在以下问题:
- 您没有阅读 Spring AOP 文档。 (抱歉,忍不住。)
- 您正在使用 Spring AOP,而不是完整的 AspectJ。不同之处在于前者仅适用于 Spring 组件,而 Log4J 不是 Spring 组件。因此,如果你想让它工作,你需要按照 Spring 手册第 11.8 章第 Using AspectJ with Spring applications.
节所述,通过加载时编织使用完整的 AspectJ
- 即使在使用完整的 AspectJ 时,您也需要知道您无法挂钩 JDK 方法的执行,因为这些方法在方面编织器实例化之前已经加载。因此,您应该通过
call(* println(..))
挂钩方法调用,而不是方法执行。
我不明白的是你为什么要连接到 Log4J 和 JDK 方法中。您想将呼叫重定向到其他频道吗?也许描述你真正想要实现的 what 会更好,而不是 how你觉得问题应该解决了
我想使用 AspetcJ
插入位于 org.apache.log4j.Category.java
文件中的 log4J
方法。
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>
示例 java class 应在我 运行 JUnit 测试时调用 - 其中清楚地看到执行了这行代码:
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{
...
}
...
我的 classes 并不总是标记为 @Component
,我想保持这种状态。
JUnit VM arguments
-javaagent:C:\aspectjWeaver\spring-instrument-3.0.4.jar
问题是我如何才能实现我的目标并让我的方面在我想要的时候被调用?
您实际上至少存在以下问题:
- 您没有阅读 Spring AOP 文档。 (抱歉,忍不住。)
- 您正在使用 Spring AOP,而不是完整的 AspectJ。不同之处在于前者仅适用于 Spring 组件,而 Log4J 不是 Spring 组件。因此,如果你想让它工作,你需要按照 Spring 手册第 11.8 章第 Using AspectJ with Spring applications. 节所述,通过加载时编织使用完整的 AspectJ
- 即使在使用完整的 AspectJ 时,您也需要知道您无法挂钩 JDK 方法的执行,因为这些方法在方面编织器实例化之前已经加载。因此,您应该通过
call(* println(..))
挂钩方法调用,而不是方法执行。
我不明白的是你为什么要连接到 Log4J 和 JDK 方法中。您想将呼叫重定向到其他频道吗?也许描述你真正想要实现的 what 会更好,而不是 how你觉得问题应该解决了