有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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


共 (2) 个答案

  1. # 1 楼答案

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

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

  2. # 2 楼答案

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

    public class MyBean {
        private String message;
    }
    

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

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

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

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

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