EL可以调用公共接口的非公共实现者吗?

时间:2012-11-15 09:53:01

标签: jsf el

爪哇:

public class MyBean {
  ...
  public Handler getHandler(){  
    return new Handler(){  
      public void handle(ActionEvent e){...}  
    }
  }
  ...
}

public interface Handler{
  void handle(ActionEvent e);
}

XHTML:

<h:commandButton ... actionListener="#{myBean.handler.handle}"/>

我在tomcat 6.0环境中。这是java中的常见模式,但似乎不适用于EL方法绑定。我得到一个例外:

javax.faces.event.MethodExpressionActionListener processAction SEVERE): Received 'java.lang.IllegalAccessException' when invoking action listener '#{myBean.handler.handle}' for component 'j_id115'
javax.faces.event.MethodExpressionActionListener processAction SEVERE): java.lang.IllegalAccessException: Class org.apache.el.parser.AstValue can not access a member of class MyBean$1 with modifiers "public"
...

3 个答案:

答案 0 :(得分:1)

是的,但是你做错了。

首先,#handle() - 方法必须声明为public,因为它是接口的公共方法的实现。

public class MyBean {
  ...
  public Handler getHandler(){  
    return new Handler(){  
      public void handle(){...}  
    };
  }

}

第二点是,你将Handler称为actionListener,但你想要的是调用#handle() - 方法:

<h:commandButton actionListener="#{myBean.handler.handle}"/>

您还应该从界面(和实现)中的方法签名中省略ActionEvent

public interface Handler {
  public void handle();
}

答案 1 :(得分:1)

这比我想的更微妙......

从java中调用内部类中的public方法没有问题:

MyBean myBean = getMyBean();
Handler handler = myBean.getHandler();
handler.handle(event); // OK

使用反射,取决于它是如何完成的。该方法可以声明为(1):

Method getHandlerMethod = MyBean.class.getMethod("getHandler");
Method handleMethod = getHandlerMethod.getReturnType().getMethod("handle", ActionEvent.class);
handleMethod.invoke(handler, event); // OK, invoking declared method works

或者可以按照内部类(2)中的定义调​​用它:

Method handleMethod = handler.getClass().getMethod("handle", ActionEvent.class);
handleMethod.invoke(handler, event) // throws IllegalAccessException

显然,还有第三种选择,它有效(3):

Method handleMethod = handler.getClass().getDeclaredMethod("handle", ActionEvent.class);
handleMethod.invoke(handler, event) // OK

不幸的是,我的JSF环境(带有JSF mojarra 1.2和icefaces 1.8.2的Tomcat 6.0)实现了方法(2)而不是(3),因此我的例子不起作用。

答案 2 :(得分:0)

如果将handle()方法指定为ActionListener,例如

,它应该可以工作
<h:commandButton ... actionListener="#{myBean.handler.handle}"/>

要指定ActionListener接口的实现类,可以使用“f:actionListener”标记,例如

<h:commandButton>
    <f:actionListener type="com.bla.SomeActionListenerImplementation" />
</h:commandButton>

但是这在你的情况下不起作用,因为你的MyBean类没有实现ActionListener接口......