2010-11-08 5 views
8

Wie Sie wissen, kann Spring Werte für private Instanzvariablen einbringen, und Hibernate kann auf private Variablen persistenter Klassen zugreifen. Ich kann jedoch nicht einmal geschützte Methoden einer Klasse durch Reflexion nennen! Wie können Spring und Hibernate die Sicherheit so unverhohlen durchbrechen? Und noch wichtiger, wie mache ich das? : DWie kann der Zugriff auf private Mitglieder im Frühling/Winterschlaf erfolgen?

+0

Effektiv ein Duplikat von http://stackoverflow.com/questions/3391256/how-java-jaxb-works – skaffman

Antwort

8

Wenn Sie ohne prohibitiven Sicherheitsmanager arbeiten, können Sie die entsprechende Methode oder das entsprechende Feld durch Reflektion abrufen und setAccessible() darauf aufrufen.

Mit dem Java-Sicherheitsmanager können Sie das natürlich deaktivieren, indem Sie eine benutzerdefinierte Richtlinie schreiben.

1

Hibernate kann über den Zugriffskonfigurationsmechanismus auf Feldebene auf private Mitglieder zugreifen. Aus der Dokumentation Abschnitt 5.1.11

"Mit dem Zugriffsattribut können Sie steuern, wie Hibernate zur Laufzeit auf die Eigenschaft zugreift. Standardmäßig ruft Hibernate das property get/set-Paar auf. Wenn Sie access =" field "angeben, wird Hibernate Umgehen Sie das Get/Set-Paar und greifen Sie direkt auf das Feld zu, indem Sie die Reflektion verwenden. "

3

Sie können private eine Variable eines anderen Objekts durch Reflexion festlegen. Hier ist ein Beispiel, wie es geht. Betrachten Sie das folgende Objekt mit einer privaten Variable:

public class MyBean { 
    private String message; 
} 

Normalerweise wird die Nachricht Feld von außen nicht zugänglich wären MyBean jedoch SnoopyClass kann seinen Wert gesetzt und erhalten. Ich schrieb zwei statische Methoden: setValue, die einen Wert in ein privates Feld Feldname ein Objekts Bohne und eine getValue Methode, die den Wert einer privaten Variable mit dem Namen festlegen Feldnamen aus einem Objekt Bohne genannt bekommen kann.

Die Haupt Verfahren zeigt nur seine Verwendung durch ein Objekt der Klasse MyBean Erstellen Einstellen der Nachricht variable und Abrufen von ihm. Ich habe diesen Code tatsächlich als eigenständige Anwendung getestet und es funktioniert.

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")); 
    } 

} 

Die Implementierung verwendet getDeclaredField Methode für die Klasse des Objekts, da diese Methode für alle Bereiche sehen kann, auch privat. Im Gegensatz dazu kann getField nur auf öffentliche Mitglieder zugreifen. Der nächste Schritt lautet setAccessible auf dem Feld, um es lesen und schreiben zu können. Der letzte Schritt ist, verwenden Sie einfach die get und set Methoden von der java.lang.reflect.Field Klasse zur Verfügung gestellt.

Diese Art der Manipulation ist nur erlaubt, wenn der Sicherheitsmanager dies erlaubt. Standardmäßig installiert Java keinen Sicherheitsmanager. In einem eigenständigen Programm, das Sie über Ihre IDE oder die Befehlszeile starten, haben Sie daher keine Probleme, diese Technik zu verwenden. Ich habe es auch in einer Spring-Anwendung unter Tomcat versucht, und es funktioniert immer noch. Die primäre Anwendung, zumindest für mich, ist die Möglichkeit, private Variablen in meinen Komponententests, insbesondere für Spring Beans, zu setzen, ohne die Schnittstelle mit unnötigen Setter zu verschmutzen.

Verwandte Themen