今天,我了解到我们可以使用spring的@AutoWired注释来完成自动注入, @AutoWired可以在许多条件下使用,例如
@AutoWired
public void setInstrument(Instrument instrument){
this.instrument = instrument;
}
但我们也可以将@AutoWired
放在私有字段上,例如
@AutoWired
private Instrument instrument;
我想知道,spring如何将一个对象注入私有字段,我知道我们可以使用java的反射来获取一些元数据,当我使用反射在私有字段上设置一个对象时,这就出现了问题,以下是stacktrace
java.lang.IllegalAccessException: Class com.wire.with.annotation.Main can not access a member of class com.wire.with.annotation.Performer with modifiers "private"
有些人可以解释一下吗?为什么spring可以将一个对象注入一个没有setter方法的私有字段。非常感谢
答案 0 :(得分:7)
使用Filed.setAccessible(true)
访问private
字段所需的反射即可完成此操作。
privateField.setAccessible(true);//works ,if java security manager is disable
<强>更新: - 强>
例如 -
public class MainClass {
private String string="Abcd";
public static void main(String... arr) throws SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchFieldException{
MainClass mainClass=new MainClass();
Field stringField=MainClass.class.getDeclaredField("string");
stringField.setAccessible(true);//making field accessible
/*if SecurityManager enable then,
java.security.AccessControlException: access denied will be thrown here*/
stringField.set(mainClass, "Defgh");//seting value to field as it's now accessible
System.out.println("value of string ="+stringField.get(mainClass));//getting value from field then printing it on console
}
}
Java安全管理器(如果启用)也会阻止Spring访问私有字段
答案 1 :(得分:3)
我猜您忘记在您尝试访问的字段上设置setAccessible(true)
:
public class Main {
private String foo;
public static void main(String[] args) throws Exception {
// the Main instance
Main instance = new Main();
// setting the field via reflection
Field field = Main.class.getDeclaredField("foo");
field.setAccessible(true);
field.set(instance, "bar");
// printing the field the "classic" way
System.out.println(instance.foo); // prints "bar"
}
}
请同时阅读this related post。