2013-07-17 3 views
0

В JSF 2 Я открыл функцию inspect которая принимает один аргумент типа java.lang.reflect.Method и на основе этого аргумента он выполняет некоторую проверку аннотаций и возвращает true или false. Уловка: я хочу называть эту функцию inspect от JSF EL, чтобы иметь возможность изменять пользовательский интерфейс согласно возвращаемому значению, но я не могу получить ссылку целевого метода, чтобы передать его как аргумент функции, поэтому я хотел бы спросите, как это сделать?Приобретать метод ссылка в JSF EL

Пример

package some.pkg; 

@ManagedBean(name = "someClass") 
public class SomeClass { 

    @MyAnnotation 
    public void someMethod(String arg1, Integer arg2) { /* ... */ } 
} 

функция JSF декларации

<function> 
    <function-name>inspect</function-name> 
    <function-class>some.pkg.Inspector</function-class> 
    <function-signature>boolean inspect(java.lang.reflect.Method)</function-signature> 
</function> 

Желаемая вызов от JSF, но не работает

<h:outputText 
    value="someMethod is annotated by @MyAnnotation" 
    rendered="#{inspect(someClass.someMethod)}" 
/> 

Приемлемый бы также это, но это я s менее удобный вариант

<h:outputText 
    value="someMethod is annotated by @MyAnnotation" 
    rendered="#{inspect(some.pkg.SomeClass.someMethod)}" 
/> 

ответ

0

Почему бы вам не попробовать его просто на стороне сервера? Вы знаете, перед отображением страницы, если the method помечается в текущем компоненте или нет, так:

@ManagedBean(name = "someClass") 
public class SomeClass { 

    boolean annotated = false; 

    public boolean isAnnotated(){ 
     return annotated; 
    } 

    @PostConstruct 
    public void postConstruct(){ 
     if (inspect(this.getClass().getMethod("someMethod")){ 
      annotated=true; 
     } 
    } 

} 

А на странице Xhtml:

<h:outputText 
    value="someMethod is annotated by @MyAnnotation" 
    rendered="#{someClass.annotated}" 
/> 

Вы даже можете адаптировать его использовать параметр и вычислить его на лету:

//Notice in this case we're using a METHOD, not a GETTER 
public boolean annotated(String methodName){ 
    return inspect(this.getClass().getMethod(methodName); 
} 

Назвать это так:

<h:outputText 
     value="someMethod is annotated by @MyAnnotation" 
     rendered="#{someClass.annotated('methodName')}" 
    /> 

Или вы можете использовать @ApplicationScoped управляемый компонент, чтобы иметь доступ к нему с каждой точки зрения:

@ManagedBean 
@ApplicationScoped 
public class InspectorBean{ 

    public boolean inspectMethod(String className, String methodName){ 
     return inspect(Class.forName(className).getMethod(methodName)); 
    } 

} 

Тогда вы можете получить доступ, как, что с все ваши взгляды:

<h:outputText 
     value="someMethod is annotated by @MyAnnotation" 
     rendered="#{inspectorBean.inspectMethod('completeClassName','methodName')}" 
    /> 
+0

Спасибо за попытку, но я не могу этого сделать. Я очень упростил мою актуальную проблему. Мне нужно сделать эту оценку для нескольких компонентов и методов, и она различает каждый запрос, поэтому я не могу с нетерпением оценить его для всех методов и beans, потому что может быть сотни таких методов, и мне нужно оценить только пару. Предположим, что этот подход с ленивой оценкой будет возможен, но это в значительной степени увеличит мои накладные расходы. – Gaim

+0

Если вам нужно использовать отражение сотни раз, пока приложение запускается, вы, вероятно, зайдете в несколько проблем с дизайном. Фактическое представление должно заботиться только о его компоненте, а не о других. –

+0

Ну, вы не вдаетесь в круг вопросов, но я могу сделать короткое разъяснение для вас. Отражение не для вызова, а только для проверки. Оценка не сто раз за запрос, а только пару раз (например, 1-5). И, наконец, это исследовательский проект адаптивных систем, поэтому в настоящее время нет оптимизации. Позже инспекция будет кэшироваться, а оценка - нет. – Gaim

0

Если вы используете EL> 2.2, вам не нужна ваша пользовательская EL-функция. Вы можете вызвать метод из вашего ManagedBean непосредственно с параметрами:

#{someClass.someMethod('foo', 42)} 

В противном случае вы должны объявить пространство имен и использовать его перед вашей функцией:

#{namespace:inspect(someClass.someMethod)} 

Вы можете найти good explanation here.

Но я не уверен, что это будет работать в вашем случае. Даже если можно передать java.lang.reflect.Method в качестве параметра (никогда не пробовали), как должен Метод получить свои параметры? Никто их не пропускает.

+0

Благодарим вас за ответ, но вы полностью не поняли мою проблему.1) Я не хочу называть 'someMethod', я хочу проверить его с помощью отражения, чтобы проверить его аннотации. 2) Я могу вызвать функцию JSF вообще, но я не могу передать ссылку на метод как аргумент - это то, что вы и не знаете. – Gaim

+0

Извините! Просто попробовал, и он не работает. Подумайте, проблема в том, что EL evalutation либо ожидает свойство, либо метод с круглыми скобками. И если вы передадите метод с paranthesis, он будет вызван так, что вы просто передадите результат этого метода 'inspect()'. Возможно, вы могли бы попытаться передать методName как String для 'проверки' и называть его там через отражение. – lefloh

+0

Да, методName as String - единственный вариант, который у меня есть в качестве альтернативы, но это не так круто, как использование EL-опций ... если есть. – Gaim

Смежные вопросы