【问题标题】:Reading class property name and value in Aspectj advice在 Aspectj 建议中读取类属性名称和值
【发布时间】:2020-07-12 20:57:04
【问题描述】:

是否可以在将属性作为切入点的同时读取 Aspectj 建议中的类属性名称和值。 下面是代码 sn -p 。

JAVA代码:

package com.test;

public class Test {
    static List<String> list;
    static List<String> removeList;
    public static void main(String[] args) {
        list = new ArrayList<String>();
        list.add("ashish");
        removeList = new ArrayList<String>();
        removeList.add("kumar");
    }
}

AspectJ 代码:

package com.test;

public aspect AspectjTest {
    pointcut callAdd(): within(com.test.*) && call(* java.util.List.add(..));

    boolean around() : callAdd() {
        //code to get the property name and property value(i.e. the value going to be added to the list)
        return true;
    }
}

【问题讨论】:

    标签: java aop aspectj


    【解决方案1】:

    您应该通过args() 将方法参数绑定到一个变量,如下所示:

    package com.test;
    
    import java.util.List;
    
    public aspect AspectjTest {
        pointcut callAdd(Object element) :
            within(com.test.*) &&
            call(boolean List.add(*)) &&
            args(element);
    
        boolean around(Object element) : callAdd(element) {
            System.out.println(thisJoinPoint + " -> " + element);
            return proceed(element);
        }
    }
    

    控制台日志:

    call(boolean java.util.List.add(Object)) -> ashish
    call(boolean java.util.List.add(Object)) -> kumar
    

    如果您不明白这一点,请随时提出后续问题。


    更新:我所说的重构是指当您使用菜单选项“Source”、“Generate delegate methods”时 Eclipse 为您(或任何其他体面的 IDE)所做的事情.结果是这样的:

    package com.test;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    
    public class NameDatabase {
        private final List<String> firstNames = new ArrayList<String>();
        private final List<String> lastNames = new ArrayList<String>();
    
        public boolean addFirstName(String e) {
            return firstNames.add(e);
        }
    
        public boolean removeFirstName(Object o) {
            return firstNames.remove(o);
        }
    
        public Stream<String> streamFirstNames() {
            return firstNames.stream();
        }
    
        public boolean addLastName(String e) {
            return lastNames.add(e);
        }
    
        public boolean removeLastName(Object o) {
            return lastNames.remove(o);
        }
    
        public Stream<String> streamLastNames() {
            return lastNames.stream();
        }
    
        public static void main(String[] args) {
            NameDatabase database = new NameDatabase();
            database.addFirstName("Galileo");
            database.addLastName("Galilei");
            database.addFirstName("Isaac");
            database.addLastName("Newton");
            database.addFirstName("Albert");
            database.addLastName("Einstein");
            database.addFirstName("Werner");
            database.addLastName("Heisenberg");
            database.addFirstName("Stephen");
            database.addLastName("Hawking");
    
            database.removeFirstName("Werner");
            database.removeLastName("Heisenberg");
    
            System.out.println(database.streamFirstNames().collect(Collectors.joining(", ")));
            System.out.println(database.streamLastNames().collect(Collectors.joining(", ")));
        }
    }
    

    对应方面:

    package com.test;
    
    public aspect NameDBContentAuditor {
        before(String name) :
            execution(public * NameDatabase.*stName(*)) &&
            args(name)
        {
            System.out.println(thisJoinPoint + " -> " + name);
        }
    }
    

    控制台日志:

    execution(boolean com.test.NameDatabase.addFirstName(String)) -> Galileo
    execution(boolean com.test.NameDatabase.addLastName(String)) -> Galilei
    execution(boolean com.test.NameDatabase.addFirstName(String)) -> Isaac
    execution(boolean com.test.NameDatabase.addLastName(String)) -> Newton
    execution(boolean com.test.NameDatabase.addFirstName(String)) -> Albert
    execution(boolean com.test.NameDatabase.addLastName(String)) -> Einstein
    execution(boolean com.test.NameDatabase.addFirstName(String)) -> Werner
    execution(boolean com.test.NameDatabase.addLastName(String)) -> Heisenberg
    execution(boolean com.test.NameDatabase.addFirstName(String)) -> Stephen
    execution(boolean com.test.NameDatabase.addLastName(String)) -> Hawking
    execution(boolean com.test.NameDatabase.removeFirstName(Object)) -> Werner
    execution(boolean com.test.NameDatabase.removeLastName(Object)) -> Heisenberg
    Galileo, Isaac, Albert, Stephen
    Galilei, Newton, Einstein, Hawking
    

    【讨论】:

    • 感谢您的回复@kriegaex。但我也需要获取类成员名称,即这里只有列表名称(例如“list”和“removeList”)。您给出的示例将能够获取值,但是在内部建议中,不可能知道将哪个值添加到哪个列表中。所以我需要列表名称以及要添加的值。
    • 不,你没有。您需要在 getter/setter 方法中封装对这些成员的访问,并通过其他方式通过 AspectJ 拦截这些成员。很难追踪代码中发生的事情不是调整工具的理由,而是重构的理由。
    • 我更新了答案,以表明重构的意思。
    • 顺便说一句,可以记录分配给set() 方面的两个成员的列表对象,包括从该连接点提取的成员名称,然后从方面进行内部对象簿记。然后,每当对内部列表中的任何成员调用 add() 方法时,您都可以将方法调用与成员名称相关联。但这只是可怕的开销。我知道该怎么做,但与建议的重构相比,我认为付出的努力不值得。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多