1 反射的概述
程序在運(yùn)行狀態(tài)中,對于任意一個類,都可以知道這個類的所有屬性和方法;對于任意一個對象,都能夠調(diào)用他的任意方法和屬性。這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為java語言的反射機(jī)制。
java文件都會被編譯成一個.class文件,類被加載以后,class文件會被加載到虛擬機(jī)中Java虛擬機(jī),在內(nèi)存中自動產(chǎn)生一個Class對象。Class對象承載了這個類的所有信息,包括父類、接口、構(gòu)造函數(shù)、方法、屬性等。

2 獲取class對象的方法
獲取class對象主要有以下三種方式,下面以Person為例說明。注意,一個類在 JVM 中只會有一個 Class 實(shí)例。
Class.forName("全類名")
Class c = Class.forName("com.reflex.Person");
- 類名.class
Class c = Person.class;
- 對象.getClass()
Person p = new Person();
Class c = p.getClass();
3 反射的作用
利用反射可以程序運(yùn)行時動態(tài)訪問和修改任何類的行為和狀態(tài)。反射最重要的用途就是開發(fā)各種通用框架.
3.1 動態(tài)創(chuàng)建對象
通過反射創(chuàng)建類對象主要有兩種方式:
- 通過 Class 對象的 newInstance() 方法
Class<?> c = String.class;
Object str = c.newInstance();
- 通過 Constructor 對象的 newInstance() 方法
/* 獲取String所對應(yīng)的Class對象 */
Class<?> c = String.class;
/* 獲取String類帶一個String參數(shù)的構(gòu)造器 */
Constructor constructor =c.getConstructor(String.class);
/* 根據(jù)構(gòu)造器創(chuàng)建實(shí)例 */
Object obj=constructor.newInstance("abc");
3.2 動態(tài)操作屬性
- getFileds: 獲取公有的成員變量
- getDeclaredFields: 獲取所有已聲明的成員變量,但是不能得到父類的成員變量
3.3 動態(tài)調(diào)用方法
- getMethods(): 返回某個類所有的public方法
public Method[] getMethods() throws SecurityException {}
- getMethod(): 返回一個特定的方法
// name :方法名稱
// parameterType :方法的參數(shù)對應(yīng)Class的對象
public Method getMethod(String name,Class<?>... parameterType) {}
- getDeclaredMethods(): 返回類或接口聲明的所有方法
//包括公共,保護(hù),默認(rèn)(包)訪問和私有方法
//不包括繼承的方法
public Method[] getDeclaredMethods() throws SecurityException {}
從類中獲取一個方法后,可以使用invoke() 來調(diào)用這個方法
public Object invoke(Object obj, Object ... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {}
4 Method.invoke()的原理
JDK里Method.invoke()實(shí)際上并不是自己實(shí)現(xiàn)的反射調(diào)用邏輯,而是委托給sun.reflect.MethodAccessor來處理。
public final class Method extends Executable {
private volatile MethodAccessor methodAccessor;
public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
if (!this.override) {
Class<?> caller = Reflection.getCallerClass();
this.checkAccess(caller, this.clazz, Modifier.isStatic(this.modifiers) ? null : obj.getClass(), this.modifiers);
}
MethodAccessor ma = this.methodAccessor;
if (ma == null) {
//獲取MethodAccessor
ma = this.acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
4.1 Method#root屬性
Method中有一個很重要的成員屬性root, root對象只有一個,可以理解為root包裝了MethodAccessors。在每次通過 getMethod 獲取 method 對象時,都會把 root 復(fù)制一份返回給用戶。同時,會把復(fù)制出的對象與 root 建立關(guān)聯(lián)。該 root 對象就是為了共享 MethodAccessors 對象。
public final class Method extends Executable {
// root對象只有一個, root 對象是為了共享 MethodAccessors 對象
private volatile MethodAccessor methodAccessor;
private Method root;
public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
if (!this.override) {
Class<?> caller = Reflection.getCallerClass();
this.checkAccess(caller, this.clazz, Modifier.isStatic(this.modifiers) ? null : obj.getClass(), this.modifiers);
}
MethodAccessor ma = this.methodAccessor;
if (ma == null) {
//獲取MethodAccessor
ma = this.acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
private MethodAccessor acquireMethodAccessor() {
// First check to see if one has been created yet, and take it
// if so
MethodAccessor tmp = null;
if (root != null) tmp = root.getMethodAccessor();
if (tmp != null) {
methodAccessor = tmp;
} else {
// Otherwise fabricate one and propagate it up to the root
tmp = reflectionFactory.newMethodAccessor(this);
//把新創(chuàng)建methodAccessor對象通過root包裝起來
setMethodAccessor(tmp);
}
return tmp;
}
void setMethodAccessor(MethodAccessor accessor) {
methodAccessor = accessor;
// Propagate up
if (root != null) {
root.setMethodAccessor(accessor);
}
}
}
4.2 MethodAccessor
MethodAccessor 是一個接口,定義了方法調(diào)用的具體操作
public interface MethodAccessor {
Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException;
}
MethodAccessor實(shí)現(xiàn)類
MethodAccessor 有兩種實(shí)現(xiàn),一種為使用 bytecodes 實(shí)現(xiàn)的 java 版本:
- Native 版本
sun.reflect.NativeMethodAccessorImpl, 一開始啟動快,但是隨著運(yùn)行時間邊長,速度變慢 - bytecodes 實(shí)現(xiàn)的 java 版本,開始加載慢,但是隨著運(yùn)行時間邊長,速度變快
sun.reflect.MethodAccessorImpl
DelegatingMethodAccessorImpl
為了完成切換兩個版本的切換,引入了DelegatingMethodAccessorImpl
第一次加載的時候使用的是 NativeMethodAccessorImpl 的實(shí)現(xiàn),而當(dāng)反射調(diào)用次數(shù)超過 15 次之后,則使用 MethodAccessorGenerator 生成的MethodAccessorImpl 對象去實(shí)現(xiàn)反射。
class DelegatingMethodAccessorImpl extends MethodAccessorImpl {
private MethodAccessorImpl delegate;
DelegatingMethodAccessorImpl(MethodAccessorImpl delegate) {
this.setDelegate(delegate);
}
public Object invoke(Object obj, Object[] args) throws IllegalArgumentException, InvocationTargetException {
return this.delegate.invoke(obj, args);
}
void setDelegate(MethodAccessorImpl delegate) {
this.delegate = delegate;
}
}
MethodAccessor的創(chuàng)建
從 acquireMethodAccessor() 方法我們可以看到,
- 代碼先判斷是否存在對應(yīng)的 MethodAccessor 對象,如果存在那么就復(fù)用之前的 MethodAccessor 對象,否則調(diào)用 ReflectionFactory 對象的 newMethodAccessor 方法生成一個 MethodAccessor 對象。
public MethodAccessor newMethodAccessor(Method method) {
checkInitted();
Method root;
if (Reflection.isCallerSensitive(method)) {
root = findMethodForReflection(method);
if (root != null) {
method = root;
}
}
root = (Method)langReflectAccess.getRoot(method);
if (root != null) {
method = root;
}
if (noInflation && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
return (new MethodAccessorGenerator()).generateMethod(method.getDeclaringClass(), method.getName(), method.getParameterTypes(), method.getReturnType(), method.getExceptionTypes(), method.getModifiers());
} else {
NativeMethodAccessorImpl acc = new NativeMethodAccessorImpl(method);
DelegatingMethodAccessorImpl res = new DelegatingMethodAccessorImpl(acc);
acc.setParent(res);
return res;
}
}
- DelegatingMethodAccessorImpl使用了代理模式,將 NativeMethodAccessorImpl 對象賦給DelegatingMethodAccessorImpl 的delegate。
而在 NativeMethodAccessorImpl 的 invoke 方法里,其會判斷調(diào)用次數(shù)是否超過閥值(numInvocations)。
class NativeMethodAccessorImpl extends MethodAccessorImpl {
private final Method method;
private DelegatingMethodAccessorImpl parent;
private int numInvocations;
NativeMethodAccessorImpl(Method method) {
this.method = method;
}
public Object invoke(Object obj, Object[] args) throws IllegalArgumentException, InvocationTargetException {
if (++this.numInvocations > ReflectionFactory.inflationThreshold() && !ReflectUtil.isVMAnonymousClass(this.method.getDeclaringClass())) {
MethodAccessorImpl acc = (MethodAccessorImpl)(new MethodAccessorGenerator()).generateMethod(this.method.getDeclaringClass(), this.method.getName(), this.method.getParameterTypes(), this.method.getReturnType(), this.method.getExceptionTypes(), this.method.getModifiers());
this.parent.setDelegate(acc);
}
return invoke0(this.method, obj, args);
}
void setParent(DelegatingMethodAccessorImpl parent) {
this.parent = parent;
}
private static native Object invoke0(Method var0, Object var1, Object[] var2);
}
如果超過該閥值,那么通過MethodAccessorGenerator生成java 版本的 MethodAccessor對象,并將原來 DelegatingMethodAccessorImpl 對象中的 delegate 屬性指向最新的java版本的MethodAccessor對象。
