今天工作的时候,我看到如下的代码:
@Autowired
private DeviceManager deviceManager;
习以为常的代码,使用Spring IOC注入成员属性。可一想,反射可以轻松做到注入私有属性,这不是破坏封装了吗?带着疑问接下去看。
二、如何用反射做到
大家都知道,Spring是通过反射做到的,所以我们也可以。在StackOverFlow,有人给出了例子,我在此基础上加上了自动测试。
1)假如类 MyBean 有私有成员msg
package com.linuxidc.reflect;
public class MyBean{
@SuppressWarnings("unused")
private String msg;
}
2)反射工具类 InjectMemberUtil:
package com.linuxidc.reflect;
import Java.lang.reflect.Field;
public class InjectMemberUtil {
public static void setValue(Object obj, String fieldName, Object value)
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public static Object getValue(Object obj, String fieldName)
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(obj);
}
}
3)测试类 InjectMemberTest:
package com.linuxidc.reflect.test;
import java.lang.reflect.ReflectPermission;
import java.util.Objects;
import junit.framework.TestCase;
import com.linuxidc.reflect.InjectMemberUtil;
import com.linuxidc.reflect.MyBean;
public class InjectMemberTest extends TestCase{
public void testInjectPrivateMember() {
String injectMsg = "InjectMsg";
MyBean myBean = new MyBean();
try {
InjectMemberUtil.setValue(myBean, "msg", injectMsg);
assertEquals(injectMsg, (String)InjectMemberUtil.getValue(myBean, "msg"));
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
4)运行Junit测试,显示成功