7

次のデフォルトメソッドを持つインターフェースがあります:

default Integer getCurrentYear() {return DateUtil.getYear();}

このインターフェイスを実装するコントローラーもありますが、メソッドは上書きされません。

public class NotifyController implements INotifyController

次のように、xhtml からこのメソッドにアクセスしようとしています。

#{notifyController.currentYear}

ただし、画面を開くと、次のエラーが発生します。

The class 'br.com.viasoft.controller.notify.notifyController' does not have the property 'anoAtual'

コントローラーのインスタンスからこのメソッドにアクセスすると、正しい値が返されますが、xhtml から「プロパティ」としてアクセスしようとすると、このエラーが発生します。

メソッドを実装せずに、コントローラーからの参照からこのインターフェイス プロパティにアクセスする方法はありますか?

4

3 に答える 3

2

これはバグと見なされるか、デフォルト メソッドをプロパティとしてサポートしないという決定であると主張する人がいるかもしれません。
JDK8java.beans.Introspector.getPublicDeclaredMethods(Class<?>)
または JDK13com.sun.beans.introspect.MethodInfo.get(Class<?>)
の行を参照してください。if (!method.getDeclaringClass().equals(clz))
また、スーパー クラスのみが追加されます (再帰的に までObject、インターフェイスは追加されませんjava.beans.Introspector.Introspector(Class<?>, Class<?>, int))。設定時に参照してくださいsuperBeanInfo

ソリューション:

  • ELメソッド呼び出し構文を使用します(つまり、プロパティアクセスではありません):#{notifyController.getCurrentYear()}あなたの場合。
    欠点: JSF コードを変更する必要があり、それがデフォルトの方法である可能性がある場合は、使用するたびに考慮する必要があります。また、リファクタリングは、実行時にのみ、コンパイラによって認識されない変更を強制します。

  • デフォルトのメソッドを一般的にサポートする EL-Resolver を作成します。ただし、これは標準のような適切な内部キャッシュを使用java.beans.Introspectorして、EL 解析を遅くしないようにする必要があります。 基本的な例 (キャッシングなし) については、JSP EL でインターフェイスのデフォルト メソッドを使用する場合の「型でプロパティが見つかりません」
    を参照してください。

  • 少数のクラス/インターフェースのみが影響を受ける場合は、単純に小さなBeanInfoクラスを作成してください。
    以下のコード例はこれを示しています(あなたの例に基づいています)。
    欠点: このようなインターフェースを実装する (JSF/EL で使用される) クラスごとに個別のクラスを作成する必要があります。
    参照: Java 8 および Bean Info Introspector のインターフェースのデフォルト メソッド


getBeanInfo()=>デフォルトのメソッドを持つインターフェース内の 静的 =>インターフェースを拡張する各クラスの
シンプル + ショートクラスBeanInfo

interface INotifyController {
    default Integer getCurrentYear() { ... }
    default boolean isAHappyYear() { ... }
    default void setSomething(String param) { ... }

    /** Support for JSF-EL/Beans to get default methods. */
    static java.beans.BeanInfo[] getBeanInfo() {
        try {
            java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(INotifyController.class);
            if (info != null)  return new java.beans.BeanInfo[] { info };
        } catch (java.beans.IntrospectionException e) {
            //nothing to do
        }
        return null;
    }

}

public class NotifyController implements INotifyController {
    // your class implementation
    ...
}


// must be a public class and thus in its own file
public class NotifyControllerBeanInfo extends java.beans.SimpleBeanInfo {
    @Override
    public java.beans.BeanInfo[] getAdditionalBeanInfo() {
        return INotifyController.getBeanInfo();
    }
}
于 2020-11-12T10:43:40.323 に答える