繁体   English   中英

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

[英]How Can Spring/Hibernate Access Private Members?

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

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

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

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

public class MyBean {
    private String message;
}

通常,无法从MyBean外部访问消息字段,但是, SnoopyClass可以设置并获取其值。 我写了两个静态方法: setValue可以将设置到名为字段名对象和的私人领域getValue方法,可以从一个对象称为字段名私有变量的值。

main方法只是通过创建一个MyBean类的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"));
    }

}

该实现在Object的类上使用getDeclaredField方法,因为此方法可以查找所有字段,甚至是私有字段。 相比之下, getField只能访问公共成员。 下一步是在字段上调用setAccessible以允许读取和写入它。 最后一步,只需使用java.lang.reflect.Field类提供的getset方法。

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM