Spring / Hibernate如何访问私有成员?

时间:2010-11-08 19:41:35

标签: java hibernate spring

如您所知,Spring可以为私有实例变量注入值,Hibernate可以访问持久化类的私有变量。但是,我甚至无法通过反射调用类的受保护方法! Spring和Hibernate如何公然违反安全性?更重要的是,我该怎么做? :d

3 个答案:

答案 0 :(得分:8)

在没有禁止的安全管理器的情况下运行时,您可以通过反射获取相应方法或字段的实例,并在其上调用setAccessible()

使用Java安全管理器,您当然可以通过编写自定义策略来禁用它。

答案 1 :(得分:3)

您可以通过反射设置私有另一个对象的变量。这是一个如何做到这一点的例子。考虑具有私有变量的以下对象:

public class MyBean {
    private String message;
}

通常,消息字段无法从 MyBean 外部访问,但 SnoopyClass 可以设置并获取其值。我编写了两个静态方法:setValue,它可以将设置为一个名为 fieldName 的私有字段,对象 bean 和一个{ {1}}方法,可以从Object bean 获取名为 fieldName 的私有变量的值。

main 方法只是通过创建一个MyBean类的对象,设置消息变量并检索它来演示它的用法。我实际上已将此代码作为独立应用程序进行测试,但它确实有效。

getValue

该实现在Object的类上使用import java.lang.reflect.Field; public class SnoopyClass { private static void setValue(Object bean, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException { Field privateVar = bean.getClass().getDeclaredField(fieldName); privateVar.setAccessible(true); privateVar.set(bean, value); } private static Object getValue(Object bean, String fieldName) throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException { Field privateVar = bean.getClass().getDeclaredField(fieldName); privateVar.setAccessible(true); return privateVar.get(bean); } public static void main(String[] argv) throws IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchFieldException { MyBean instance = new MyBean(); setValue(instance, "message", "Shht! Don't tell anyone!"); System.out.println("The message is '" + getValue(instance, "message")); } } 方法,因为此方法可以查找所有字段,甚至是私有字段。相反,getDeclaredField只能访问公共成员。下一步是在字段上调用getField以允许读取和写入它。最后一步,只需使用setAccessible类提供的getset方法。

只有在安全管理员允许的情况下才允许这种操作。默认情况下,Java不会安装任何安全管理器,因此在通过IDE或命令行启动的独立程序中,使用此技术不会有任何问题。我也尝试过,在Tomcat下的Spring应用程序中,它仍在工作。

主要的应用程序,至少对我而言,能够在我的单元测试中设置私有变量,特别是对于Spring Beans,而不会用不需要的setter污染接口。

答案 2 :(得分:1)

Hibernate可以通过“字段”级访问配置机制访问私有成员。从文档中,5.1.11

部分

“访问属性允许您控制Hibernate在运行时访问属性的方式。默认情况下,Hibernate将调用属性get / set对。如果指定access =”field“,Hibernate将绕过get / set对,使用反射直接访问该字段。“