深入理解java反射机制中Method类中的invoke()方法
1.先说明Method类中的几个重要的属性
1)Method类型的root属性:
可以理解为每一个 java方法都有唯一的一个Method对象,这个对象就是root,我们可以利用反射创建java方法的众多的Method类的对象,这些对象指向root,可以理解为root的镜像。
2)MethodAccessor类型的 methodAccessor属性:
每一个Method对象有一个root属性,每一个root对象里有一个methodAccessor对象。我们获取的Method相当于root的镜像,可以共用methodAccessor对象。这个对象由ReflectionFactory来创建
2.源码分析
首先是判断override是true还是false,override属性是Method类的父类Executable的父类AccessibleObject的一个属性,用来判断是否要进行访问权限判断。默认为false,我们可以通过setAccessible()方法来设置override的值。它里面有一个setAccessible0()方法:
如果override设置为true,则可以忽略访问权限的限制,直接调用。如果为false,则通过执行Reflection.quickCheckMemberAccess(clazz, modifiers)这个方法来判断我们需要调用的方法是不是public类型的(还是访问权限的问题,public,protected,private的范围)。如果不是public类型的,则我们通过 Class<?> caller = Reflection.getCallerClass();来获取该方法的Class对象。然后调用checkAccess(caller, clazz, obj, modifiers);进行访问权限的校验。
在这个访问权限的校验方法中我们用到了缓存,即第一次校验后就存放到缓存中,下次进行缓存校验时如果还是同一个类来校验,则不校验,直接返回。但是如果下一次不是同一个类,我们会覆盖缓存中的类。
访问权限的判断校验后就是重点:
首先我们会获取methodAccessor对象,因为每个java方法的methodAccessor唯一。此处我们通过acquireMethodAccessor()来生成methodAccessor对象:
如果root中的methodAccessor不为空,即上次调用invoke()已经为root中的methodAccessor赋值了。否则通过reflectionFactory.newMethodAccessor(this);来创建methodAccessor对象,然后调用setMethodAccessor(tmp);为root中的methodAccessor赋值。然后通过methodAccessor对象的invoke()来完成对方法的调用。实际上Method.invoke()不是自己来完成反射调用逻辑的,而是委托给MethodAccessor的invoke()来实现的。每个java方法只有一个Method对象作为root,同样,对应的methodAccessor对象也只能是一个。我们每次创建返回的Method对象都是包装了root的对象。