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

Java Spring/Hibernate如何访问私有成员?,java,hibernate,spring,Java,Hibernate,Spring,如您所知,Spring可以向私有实例变量注入值,Hibernate可以访问持久类的私有变量。然而,我甚至不能通过反射调用类的受保护方法!Spring和Hibernate怎么能像那样公然破坏安全性呢?更重要的是,我该怎么做DHibernate可以通过“字段”级访问配置机制访问私有成员。从文档,第节 “access属性允许您控制Hibernate在运行时如何访问属性。默认情况下,Hibernate将调用属性get/set对。如果指定access=“field”,Hibernate将绕过get/set

如您所知,Spring可以向私有实例变量注入值,Hibernate可以访问持久类的私有变量。然而,我甚至不能通过反射调用类的受保护方法!Spring和Hibernate怎么能像那样公然破坏安全性呢?更重要的是,我该怎么做D

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


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

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


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

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

public class MyBean {
    private String message;
}
通常情况下,消息字段不能从MyBean外部访问,但是,SnoopyClass可以设置并获取其值。我编写了两个静态方法:
setValue
,它可以将值设置到对象bean的名为fieldName的私有字段中;以及
getValue
方法,它可以从对象bean获取名为fieldName的私有变量的值

main方法只是通过创建MyBean类的对象、设置消息变量并检索它来演示它的用法。实际上,我已经将这段代码作为一个独立的应用程序进行了测试,它可以正常工作

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
,以允许读写。最后一步是简单地使用
java.lang.reflect.Field
类提供的
get
set
方法

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

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

实际上是