繁体   English   中英

如何使用标准java功能拦截方法调用(没有AspectJ等)?

[英]How do I intercept a method invocation with standard java features (no AspectJ etc)?

我想拦截所有方法调用到某个类MyClass,以便能够对某些setter-invocations做出反应。

我试图使用动态代理,但据我所知,这仅适用于实现某些接口的类。 但MyClass没有这样的界面。

除了实现一个包装类之外,还有其他方法将所有调用委托给一个成员,该成员是MyClass的一个实例,或者是使用AOP的旁边?

如您所知,您不能使用JDK动态代理(无接口),但使用Spring和CGLIB(Spring中包含JAR),您可以执行以下操作:

public class Foo
{
    public void setBar()
    {
        throw new UnsupportedOperationException("should not go here");
    }

    public void redirected()
    {
        System.out.println("Yiha");
    }
}

Foo foo = new Foo();
ProxyFactory pf = new ProxyFactory(foo);

pf.addAdvice(new MethodInterceptor()
{
    public Object invoke(MethodInvocation mi) throws Throwable
    {
        if (mi.getMethod().getName().startsWith("set"))
        {
            Method redirect = mi.getThis().getClass().getMethod("redirected");
            redirect.invoke(mi.getThis());
        }
        return null;
    }
});

Foo proxy = (Foo) pf.getProxy();
proxy.setBar(); // prints "Yiha"

如果你准备做一些非常丑陋的事情,请看看:

http://docs.oracle.com/javase/7/docs/technotes/guides/jpda/

基本上调试器接口应该允许您像调试器一样附加,从而拦截调用。 请记住,我认为这是一个非常糟糕的主意,但你问是否有可能。

我刚刚为此开发了一个小框架。 您可以访问: http//code.google.com/p/java-interceptor/ (使用svn签出)。

Java没有用于方法拦截的任何实际语言功能(不确定任何静态语言)

我有点像尼克使用调试器界面的想法,这只是意思。

我认为你需要的简短答案是:没有一种方法可以拦截Java中的方法调用,而无需使用代理或包装器实际替换类。

注意:AOP库只是自动执行此操作。

一些Java专家可能对此不以为然,但我已经取得了一些成功,完全避免了原始类型和setter。 我的班级看起来像这样:

class Employee extends SmartPojo {
    public SmartString name;
    public SmartInt age;
}

你会注意到两件事:1。一切都是公开的。 2.没有构造函数。

魔术发生在SmartPojo中,它搜索实现“智能”接口并初始化它的任何字段。 由于这不是原始的(并且没有最终类),我可以在一个地方为模型中的任何位置添加set()和get()方法。 因此,不再有setter / getter浪费,添加通知(也在一个地方)等非常简单。

没错,这不再是POJO了,而且在大多数情况下都不是Bean,但我发现这些旧想法限制了我,而不是他们的帮助。 因人而异。

AspectJ中没有太多魔力。 您可以编写自己的代理。 http://java.sun.com/javase/6/docs/api/java/lang/instrument/package-summary.html似乎是一个很好的起点。

  1. 为什么你的类不能实现接口? 您可以从中提取一些包含您要拦截的所有方法的接口,并轻松使用动态代理机制。 使用接口而不是类进行编码也是一种很好的编程习惯。

  2. 您可以将Spring框架与Spring AOP功能(使用内部的动态代理)一起使用。 您只需要在配置文件中将您的类定义为Spring bean,并且您的类的客户端必须从Spring应用程序上下文中获取其实例或自动作为依赖项(例如,通过定义setMyClass(MyClass mc)方法) )。 从那里,您可以轻松地定义一个截取对此类的所有方法调用的方面。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM