背景 我们有一个使用 Maven 作为构建工具的 Java 项目。项目结构有一个 Parent POM,然后是各种 Child POM。
我正在创建一个子 POM 项目,我想在其中定义一组可在现有子项目中使用的方面。
我在 - http://www.mojohaus.org/aspectj-maven-plugin/examples/libraryJars.html#
的帮助下让它工作问题 - 如果我想记录方法执行的运行时参数值,那么如何在库中执行此操作而不依赖于任何其他子 POM 项目?
例如:
父项目:
Child-1 的课程:
package org.example;
class Item {
// fileds, getters, setters
}
package org.example;
class Business {
public void logic(Item b) {
// logic
}
}
AspectJ-Library 中的类
package org.example;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class LoggingAspect {
@Before("execution(* org.example.Business.logic(..))") // Will be moving this to annotation based PointCut
public void logBeforeAllMethods(JoinPoint joinPoint)
{
// How to log values of various fields of object of class Item?
}
}
如何在上面的
logBeforeAllMethods
方法中记录Item类对象的各个字段的值?
您的问题与 Maven 模块或 AspectJ Maven 插件无关。如果我理解正确,您只是想知道如何记录被拦截方法的参数详细信息。通过
args()
使用参数绑定怎么样?
package de.scrum_master.app;
public class Item {
private int id;
private String name;
public Item(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
package de.scrum_master.app;
public class Business {
public void logic(Item item) {}
public static void main(String[] args) {
new Business().logic(new Item(11, "Jane"));
new Business().logic(new Item(22, "John"));
}
}
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import de.scrum_master.app.Item;
@Aspect
public class LoggingAspect {
@Before("execution(* de.scrum_master.app.Business.logic(..)) && args(item)")
public void logBeforeAllMethods(JoinPoint joinPoint, Item item) {
System.out.println(joinPoint);
System.out.println(" Item[id=" + item.getId() + ", name=" + item.getName() + "]");
}
}
控制台日志:
execution(void de.scrum_master.app.Business.logic(Item))
Item[id=11, name=Jane]
execution(void de.scrum_master.app.Business.logic(Item))
Item[id=22, name=John]
如果您有更通用的想法,那么您的示例代码没有清楚地表达它,您的问题描述也没有清楚地表达出来。
也许您注意到我的 aspetc 已经负责收集
Item
的字符串表示形式。更好的方法是为 toString()
创建一个有意义的 Item
方法(或其他合适的字符串表示方法),并在方面简单地使用它。当然,您可以在方面中使用反射来确定字段及其值,但这真的是方面的工作吗?
另外,你为什么要写这个?
// Will be moving this to annotation based PointCut
你为什么要这么做?最好使用描述您想要记录的类、方法、参数等类型的切入点来拦截方法。如果没有其他方法来编写切入点,则仅将标记注释作为最后的手段。 AOP 的标记注释被开发人员过度使用,而没有考虑其他方法来定义他们希望拦截的连接点集。标记注释看起来很简单,因为使用它们时不需要考虑太多。但使用它们的后果是你用切面相关的信息污染了整个代码库,这正是 AOP 努力避免的事情。