构建使用 AspectJ 的库

问题描述 投票:0回答:1

背景 我们有一个使用 Maven 作为构建工具的 Java 项目。项目结构有一个 Parent POM,然后是各种 Child POM。

我正在创建一个子 POM 项目,我想在其中定义一组可在现有子项目中使用的方面。

我在 - http://www.mojohaus.org/aspectj-maven-plugin/examples/libraryJars.html#

的帮助下让它工作

问题 - 如果我想记录方法执行的运行时参数值,那么如何在库中执行此操作而不依赖于任何其他子 POM 项目?

例如:

父项目:

  • 儿童 1
  • 儿童2
  • AspectJ-图书馆

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类对象的各个字段的值?

java aop aspectj
1个回答
0
投票

您的问题与 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 努力避免的事情。

© www.soinside.com 2019 - 2024. All rights reserved.