Field.get(obj)返回注入的CDI托管bean上的所有空值,而手动调用getter则返回正确的值 [英] Field.get(obj) returns all nulls on injected CDI managed beans, while manually invoking getters return correct values

查看:357
本文介绍了Field.get(obj)返回注入的CDI托管bean上的所有空值,而手动调用getter则返回正确的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过反射从JSF页面的支持bean访问某些字段的值。问题是,当我使用getter时,我得到了正确的值但是当我使用必要字段的get(obj)方法时,我总是得到一个返回的null值。

I am trying to access the values of some fields from the backing bean of a JSF page via reflection. The problem is that when I use the getter I get the correct value but when I use the get(obj) method of the necessary fields I always get a null value returned.

获取beanObject:

Getting the beanObject:

ELContext elcontext = FacesContext.getCurrentInstance().getELContext();
Object beanObject = FacesContext.getCurrentInstance().getApplication().getELResolver().getValue(elcontext, null, beanName);

要在不使用getter的情况下获取字段值,请执行以下操作:

To get the fields values without using the getter I do the following:

List<Field> fields = new ArrayList<Field>();
ParamsBuilder.getAllFields(fields, beanClass);

for(Field field: fields) {

    field.setAccessible(true);
    System.out.println(field.getName() + ": " + field.get(beanObject)); //just to see if it works

}

getAllFields方法有此实现:

The getAllFields method has this implementation:

public static List<Field> getAllFields(List<Field> fields, Class<?> type) {
    for (Field field: type.getDeclaredFields()) {
        fields.add(field);
    }

    if (type.getSuperclass() != null) {
        fields = getAllFields(fields, type.getSuperclass());
    }

    return fields;
}

要使用getter获取值,请执行以下操作:

To get the values by using the getter I do the following:

private ClassX getValue(Object beanObject, Class<?> beanClass) throws Exception {

    Method getter = beanClass.getDeclaredMethod("myMethod",(Class<?>[]) null);

    return (ClassX)getter.invoke(beanObject, (Object[])null);
}

我可以进一步提及的是我要访问的字段是注入的使用@Inject注释,但我不相信这是问题,因为其他实例字段,没有注入,遭受同样的感情。

What I can further mention is that the fields I am trying to access are injected with the @Inject annotation, but I don't believe this is the problem as other instance fields, not injected, suffer of the same affection.

通常我会使用getter但我在这里尝试做的事情对我正在开发的应用程序有全局影响,这意味着返回并修改所有受影响的类以提供getter是最后一个度量方案。此应用程序也将不断修改和扩展,我不想冒其他开发人员不提供getter的机会,这将导致严重的问题。

Normally I would use the getter but what I am trying to do here has a global impact on the application I am developing, which means that going back and modifying all affected classes to provide getters is a last measure solution. Also this application will be constantly modified and extended and I don't want to take the chance of the other developers not providing the getters, which will result in serious problems.

谢谢!

推荐答案

这确实是预期的行为。 CDI托管bean实例本质上是一个自动生成类的可序列化代理实例,它扩展了原始的支持bean类,并通过公共方法(如EJB的工作方式)将所有公共方法中的代理进一步委托给实际实例。自动生成的类看起来大致如下:

That's indeed expected behavior. The CDI managed bean instance is in essence a serializable proxy instance of an autogenerated class which extends the original backing bean class and delegates in all public methods further to the actual instance via public methods (like as how EJBs work). The autogenerated class looks roughly like this:

public CDIManagedBeanProxy extends ActualManagedBean implements Serializable {

    public String getSomeProperty() {
        ActualManagedBean instance = CDI.resolveItSomehow();
        return instance.getSomeProperty();
    }

    public void setSomeProperty(String someProperty) {
        ActualManagedBean instance = CDI.resolveItSomehow();
        instance.setSomeProperty(someProperty);
    }

}

如你所见,没有具体领域。你也应该在检查类本身时注意到自动生成的类签名。

As you see, there are no concrete fields. You should also have noticed the autogenerated class signature while inspecting the class itself too.

毕竟,你的方法是错误的。你应该使用 java.beans .Introspector API 来内省bean并调用bean实例上的getter / setter。

After all, you're going about this the wrong way. You should be using java.beans.Introspector API to introspect the bean and invoke getters/setters on bean instances.

这是一个启动示例:

Object beanInstance = getItSomehow();
BeanInfo beanInfo = Introspector.getBeanInfo(beanInstance.getClass());

for (PropertyDescriptor property : beanInfo.getPropertyDescriptors()) {
    String name = property.getName();
    Method getter = property.getReadMethod();
    Object value = getter.invoke(beanInstance);
    System.out.println(name + "=" + value);
}

这个API像JSF和CDI一样尊重 JavaBeans规范,因此您无需摆弄原始反射API并计算/猜测正确的方法名称。

This API respects like JSF and CDI the JavaBeans spec, so you don't need to fiddle around with raw reflection API and figuring/guessing the correct method names.

无关具体问题,具体取决于具体功能你可能错误地认为这一切都是正确的解决方案的要求,你在问题中没有说明任何东西,可能有更好的方法来实现它,而不是内省bean实例。

Unrelated to the concrete problem, depending on the concrete functional requirement for which you possibly incorrectly thought that this all would be the right solution, which you didn't tell anything about in the question, there may be even more better ways to achieve it than introspecting the bean instances.

这篇关于Field.get(obj)返回注入的CDI托管bean上的所有空值,而手动调用getter则返回正确的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆