0

我正在尝试使用 aspectJ 访问参数的名称,但我总是得到arg0而不是真实名称。我发现我应该在AspectJ JoinPoint 问题中使用 -g 参数激活 java 调试选项,但这对我不起作用......

这是我的java代码:

private Set<Collection<String>> s;
private Collection<String> c;

public HashCodeProperty() {
    s = new HashSet<Collection<String>>();
    c = new ArrayList<String>();
}

/**
 * method that satisfy property
 */
public void satisfy() {
    c.add("this is ok");
    s.add(c);
    System.out.println("Collection is in Set: " + s.contains(c));
}

/**
 * method that violate the property
 */
public void violate() {
    c.add("this is ok");
    s.add(c);
    c.add("don't do this");
    System.out.println("Collection is in Set: " +s.contains(c));
}

这是我的 AspectJ 代码:

pointcut addElementsToHashCodeSet() : call (* Set.add(..));

declare warning: addElementsToHashCodeSet(): "pointcut: addElementsToHashCode()";

after(): addElementsToHashCodeSet() { 
    monitorHashCode.addElementsToHashCode((MethodSignature)thisJoinPoint.getSignature());



public void addElementsToHashCode(MethodSignature methodSignature) { 
    System.out.println("\naddElementsToHashCode.");

    // We need to access to real PARAMETER NAME
    // Then we will concatenate with method and full class name
    String firstParameterName = methodSignature.getParameterNames()[0];
    // Add firstParameterName to an array that will contain all 
    // the name of the collections inserted into the HasSet 
    System.out.println("\nfirstParameterName: "+firstParameterName);
}

电流输出:

第一个参数名称:arg0

我需要作为输出:

第一个参数名称:c

我有这两个选择:

Java 编译器选项

AspectJ 编译器选项

我还需要激活什么?

非常感谢 !

4

2 回答 2

1

我找到了一种更好的方法来了解变量的名称(标识符),方法如下:

before(Collection c): addElementsToHashCodeSet() && args(c)

通过这种方式,我们可以获得对变量c的直接引用。

不需要在 Eclipse 中激活调试符号。

可以使用以下代码实现所需的解决方案:

仪表师:

package fr.imag.ufrima.tat.tp6.aspects;

import java.util.Collection;
import java.util.Set;

import fr.imag.ufrima.tat.tp6.aspects.monitor.MonitorHashCode;

/**
 * Techniques Avancées de Test
 * 
 * @author Rodmar CONDE
 *
 * Instrumentator for validation of HashSet classes.
 * 
 * Secures the usage of HashSet that include Collections in preventing 
 * more elements to be added to the collections once they are added. 
 * 
 * Monitor code is provided in a separate class: MonitorHashCode.
 */
public aspect InstrumentationHashCode {

    private MonitorHashCode monitorHashCode;

    public InstrumentationHashCode() {
        monitorHashCode = new MonitorHashCode();
    }

    pointcut addElementsToHashCodeSet() : call (* Set.add(..));

    declare warning: addElementsToHashCodeSet(): "pointcut: addElementsToHashCode()";

    before(Collection c): addElementsToHashCodeSet() && args(c) { 
        monitorHashCode.addElementsToHashCode(c);                   
    }

    pointcut addElementsToCollection() : call (* Collection.add(..));

    declare warning: addElementsToCollection(): "pointcut: addElementsToCollection()";

    after(String s): addElementsToCollection() && args(s) {
        monitorHashCode.addElementsToCollection(thisJoinPoint.getTarget());     
    }

}

监视器:

package fr.imag.ufrima.tat.tp6.aspects.monitor;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 
 * @author Rodmar CONDE
 * 
 * Monitor used to prevent adding elements to a collection that has already been added to a HashMap
 *
 */
public class MonitorHashCode {
    /**
     *  Stores the system identity hashcode of the collections that are added to the monitored HashCode 
     */
    private List<Integer> collectionsAddedToHashSet;

    public MonitorHashCode() {
        System.out.println("Monitor created.");
        collectionsAddedToHashSet = new ArrayList<Integer>();
    }

    /**
     * Adds the system identity hashcode of the passed collection to the list
     * 
     * @param c Collection to be added to the list
     */
    public void addElementsToHashCode(Collection c) { 
        System.out.println("\naddElementsToHashCode.");

        collectionsAddedToHashSet.add(System.identityHashCode(c));
        System.out.println("\nCollection has been added to HashMap.");
    }

    /**
     * 
     * Before adding the element, search if the collection exists already
     * in the list, if so print an error.
     *
     * @param pointCutTarget
     */
    public void addElementsToCollection(Object pointCutTarget) { 
        System.out.println("\naddElementsToCollection.");

        int systemIdentityHashCode = System.identityHashCode(pointCutTarget);
        boolean isContained = collectionsAddedToHashSet.contains(systemIdentityHashCode);
        System.out.println(String.format("currentCollection: %s systemIdentityHashCode: %d - isContained: %s", pointCutTarget, systemIdentityHashCode, isContained));
        if (isContained) {
            System.out.println("Error: you have already added this collection into a hashmap, you can not add more elements into it!");
        }
    }

}
于 2013-03-26T10:28:17.660 回答
0

我阅读它的方式是询问 Set.add(..) 方法的第一个参数的(内部)名称。这永远不会是您定义的名称,因为它是 Java-API 的一部分。您想要的是传递给该参数的值的名称。

这些值应该可以通过JoinPoint.getArgs()-method作为 Object[] 使用,但我不确定如何获取它们的名称。不过应该可以通过反射来实现。

于 2013-03-25T10:52:43.470 回答