非最终类中的代理最终方法

时间:2015-01-17 00:02:11

标签: java android javassist bytecode-manipulation

我需要在Android UI Framework中的各种视图类上代理方法,例如TextView。特别是TextView#setText(int resId)。此方法不是界面的一部分。因此,Java Proxy将无法工作,因为它仅适用于接口。我需要使用字节码操作。

我发现了一个名为dexmaker的图书馆似乎很有希望。我假设我需要进行运行时字节代码操作,因为Android View类实际上只能在设备上使用。 Dexmaker可以在具体类上代理公共方法。然后我注意到TextView#setText(int resId)莫名其妙地finalTextView类本身不是最终的。

我想我可以派遣dexmaker来支持非final类的最终方法。这可能吗?如果不是,我不想启动这个项目。这对我的库来说是一个巨大的胜利,因为开发人员不需要为他们的视图提供子类,接口或手动静态方法调用。我的图书馆需要知道何时在特定视图上设置文本。代理是完美的设计模式。

2 个答案:

答案 0 :(得分:2)

" final"的意图是该方法不能被覆盖。这有效地阻止了扩展代理。但是,你仍然可以通过包装代理,就像Spring处理它一样。

这就是将界面与实现分开的最佳实践的原因之一。

更具体地说......

// This snip is not supposed to be functional, only to demonstrate a concept
interface TextViewInterface {
    void setText (int resId);
}

class TextView implements TextViewInterface {
    public final void setText (int resId) {
    ... snip ...
    }
}

class Proxy$TextView implements TextViewInterface 
extends View { // Added this for Android hierarchy
    private TextView textView;

    public void setText (int  resId) {
        textView.setText(resId);
    }
}

这有帮助吗?

答案 1 :(得分:2)

据我所知,这在Android上无法实现。

Dexmaker创建包含新类的dex文件。然后使用dex类加载器将这些类添加到应用程序中。但是,这些dex文件不能用于替换类,只能添加用作代理的新子类。

从这个意义上讲,dexmaker就像cglib而不是javassist。

请注意,Android既不提供与常规Jvm类似的仪器功能,您可以通过代理重新定义类来检测最终类和方法。 Android不提供此功能:http://developer.android.com/reference/android/app/Instrumentation.html