【问题标题】:Pointcut to match call to any method except those frm jdk切入点以匹配对除 frm jdk 之外的任何方法的调用
【发布时间】:2015-12-16 17:25:36
【问题描述】:

我希望我的切入点来标记对除 java sdk 中的方法之外的任何方法的调用

Pointcut trace(): call(* *(..)) && !within(methodprofilt) && !call(* java*(..)

这不起作用

【问题讨论】:

  • 我会说这是不可能的,因为如果我愿意的话,我可以在一个名为 java.util 的包中创建一个类(除非你有一个 JDK 类的列表)
  • 那么我怎样才能避免 java jdk 的类,让我说我没有在 java.util 中创建类仍然为什么它不工作

标签: java aspect pointcut


【解决方案1】:

我认为这并不容易,如果您查看 JDK,您会看到除 java..* 之外的更多包名称。查看我的示例代码,它使用了其他包中的 JDK 类(还有更多,这只是一个小展示),一些用于正常访问,另一些用于受限访问:

助手类:

package de.scrum_master.app;

public class Foo {
    public static void doSomething() {
        System.out.println("Doing something");
    }
}

驱动程序应用:

package de.scrum_master.app;

import javax.swing.event.EventListenerList;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.Oid;
import org.omg.CORBA.IntHolder;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.xml.sax.InputSource;

// Internal Sun/Oracle-specific JDK classes,
// not recommended for JDK- and version-agnostic use
import sun.util.calendar.CalendarUtils;
import com.sun.beans.finder.BeanInfoFinder;

public class Application {
    public static void main(String[] args)
        throws GSSException, ClassNotFoundException, InstantiationException,
        IllegalAccessException, ClassCastException
    {
        sayHelloTo("world");
        Foo.doSomething();
        new Oid("1.2.840.113554.1.2.2").getDER();
        System.out.println("Process ID (PID) = " + getPID());
        new IntHolder(11)._type();
        DOMImplementationRegistry.newInstance().getDOMImplementation("XML 3.0");
        new InputSource().setEncoding("UTF-8");
        new EventListenerList().getListenerCount();

        // Internal Sun/Oracle-specific JDK classes,
        // not recommended for JDK- and version-agnostic use
        new BeanInfoFinder().getPackages();
        new CalendarUtils().isGregorianLeapYear(2015);
    }

    public static void sayHelloTo(String visitor) {
        System.out.println("Hello " + visitor);
    }

    public static long getPID() {
        String processName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
        return Long.parseLong(processName.split("@")[0]);
    }
}

改进的拦截器方面:

package de.scrum_master.aspect;

public aspect NonJDKInterceptor {
    pointcut allCalls() : call(* *(..));
    pointcut jdkCalls() :
        call(* java..*(..)) || call(* javax..*(..)) ||
        call(* org.ietf..*(..)) || call(* org.omg..*(..)) ||
        call(* org.w3c..*(..)) || call(* org.xml..*(..)) ||
        call(* sun..*(..)) || call(* com.sun..*(..));

    before() : allCalls() && !jdkCalls() && !within(NonJDKInterceptor) {
        System.out.println(thisJoinPoint);
    }
}

控制台输出:

call(void de.scrum_master.app.Application.sayHelloTo(String))
Hello world
call(void de.scrum_master.app.Foo.doSomething())
Doing something
call(long de.scrum_master.app.Application.getPID())
Process ID (PID) = 13948

您的简单切入点会错过大多数 JDK 调用。只有这个切入点

pointcut jdkCalls() : call(* java..*(..));

输出如下所示:

call(void de.scrum_master.app.Application.sayHelloTo(String))
Hello world
call(void de.scrum_master.app.Foo.doSomething())
Doing something
call(byte[] org.ietf.jgss.Oid.getDER())
call(long de.scrum_master.app.Application.getPID())
Process ID (PID) = 13748
call(TypeCode org.omg.CORBA.IntHolder._type())
call(DOMImplementationRegistry org.w3c.dom.bootstrap.DOMImplementationRegistry.newInstance())
call(DOMImplementation org.w3c.dom.bootstrap.DOMImplementationRegistry.getDOMImplementation(String))
call(void org.xml.sax.InputSource.setEncoding(String))
call(int javax.swing.event.EventListenerList.getListenerCount())
call(String[] com.sun.beans.finder.BeanInfoFinder.getPackages())
call(boolean sun.util.calendar.CalendarUtils.isGregorianLeapYear(int))

更新:我忘了提到使用execution() 切入点而不是call() 的替代方法,因为它们

  • 效率更高,因为它们在执行方法的地方创建字节码,而不是在调用它的一百个地方,
  • 默认情况下仅编织到您自己的代码中,即无论如何您都不会编织到 JDK 二进制文件中,因此默认情况下会忽略 JDK 方法执行。简化的方面变为:
package de.scrum_master.aspect;

public aspect NonJDKInterceptor {
    before() : execution(* *(..)) {
        System.out.println(thisJoinPoint);
    }
}

日志输出与第一个类似,但现在还列出了main(..)方法的执行情况:

execution(void de.scrum_master.app.Application.main(String[]))
execution(void de.scrum_master.app.Application.sayHelloTo(String))
Hello world
execution(void de.scrum_master.app.Foo.doSomething())
Doing something
execution(long de.scrum_master.app.Application.getPID())
Process ID (PID) = 13916

我认为这是您想要的简单有效的解决方案。可以回答call() 切入点正是您所要求的。

【讨论】:

    【解决方案2】:

    我正在寻找的切入点是

    call(java..*..*(..))
    

    【讨论】:

    • 其实这里的语法是错误的。你的意思是call(* java..*(..))。但这无论如何都不是正确的解决方案,请参阅我自己的答案。
    猜你喜欢
    • 1970-01-01
    • 2021-01-25
    • 2018-05-08
    • 1970-01-01
    • 1970-01-01
    • 2011-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多