If you try to visit the value of an object's private field using reflection, such as Field#get or Field#set, you should call Field#setAccessible ahead.
look at the sample program below. It works when I run it.
Field[] fields = reflectAllFields(parameter);
for (Field field : fields) {
if ("createTime".equals(field.getName())) {
field.setAccessible(true);
Object localCreateDate = field.get(parameter);
if (localCreateDate == null || "".equals(localCreateDate)) {
if (field.getType() == Date.class) {
field.set(parameter, DateUtils.getPlusDaysDate( new Date(),10));
} else if (field.getType() == LocalDateTime.class) {
field.set(parameter, LocalDateTime.now());
}
}
}
}
By the way, the utility method reflectAllFields
// import java.lang.reflect.Field;
private static Field[] reflectAllFields(Object object) {
Class<?> clazz = object.getClass();
List<Field> fieldList = new ArrayList<>();
while (clazz != null) {
fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
clazz = clazz.getSuperclass();
}
Field[] fields = new Field[fieldList.size()];
fieldList.toArray(fields);
return fields;
}
View Code
Then, I make a little adjustment, see below. Run it again, and the program throws an exception → can not access a member of class com.emaxcard.account.entity.Account with modifiers "private"
Field[] fields = reflectAllFields(parameter);
for (Field field : fields) {
if ("createTime".equals(field.getName())) {
Object localCreateDate = field.get(parameter);
if (localCreateDate == null || "".equals(localCreateDate)) {
field.setAccessible(true);
if (field.getType() == Date.class) {
field.set(parameter, DateUtils.getPlusDaysDate( new Date(),10));
} else if (field.getType() == LocalDateTime.class) {
field.set(parameter, LocalDateTime.now());
}
}
}
}
Here are the stacktraces :
java.lang.IllegalAccessException: Class com.emaxcard.account.config.MybatisInterceptor can not access a member of class com.emaxcard.account.entity.Account with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
at java.lang.reflect.Field.get(Field.java:390)
at com.emaxcard.account.config.MybatisInterceptor.intercept(MybatisInterceptor.java:89)
at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
at com.sun.proxy.$Proxy157.update(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:63)
... 50 more
I note that The mentioned field com.emaxcard.account.entity.Account#createTime is private. When I change it to public, the above IllegalAccessException disappears. Of course, we should define fields as private, that's the POJO specification.
In a word, If you try to visit the value of an object's private field using reflection, such as Field#get or Field#set, you should call Field#setAccessible ahead.
当看到一些不好的代码时,会发现我还算优秀;当看到优秀的代码时,也才意识到持续学习的重要!--buguge