反射3--Method,簡單的實現和部分源碼分析

public class Person {

    private int age;
    public String name;

    public Person(){};

    public Person(String name) {
        this.name = name;
        System.out.println(this.name);
    }

    public Person(int age, String name) {
        this(name);
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void getInfo() {
        System.out.println("name:" + name + "; age:" + age);
    }

    public void setNum(double x) {
        x = 3 * x;
    }

    public void firstMethod(){
        System.out.println("This is first method");
    }

    private void secondMethod(){
        System.out.println("This is second method");
    }

    private String ThirdMethod(String arg){
        return "This is third method"+arg;
    }
}
public class reflectTest {
    public static void main(String[] args) throws Exception {
        //1. 實例化Person
        Person person = (Person)Class.forName("POJO.Person").newInstance();

        //2. getDeclaredMethod()獲取方法
        Method method = person.getClass().getDeclaredMethod("firstMethod");

        //3. method.getModifiers()獲取方法做用域,method.getName()獲取方法名
        System.out.println("fitst method:"+Modifier.toString(method.getModifiers())+" "+method.getName()+" ");

        //4. invoke注入方法對象
        method.invoke(person);
    }
}

執行後輸出:java

fitst method:public firstMethod 
This is first method

依然是看一下源碼安全

public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
        throws NoSuchMethodException, SecurityException {

        //1.依然是先進行java的安全驗證和權限驗證,具體參考上一章,
        //private的方法會拋異常(java.lang.IllegalAccessException)
        checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);

        //2.searchMethods將在,privateGetDeclaredMethods返回的方法(Method[])中,
        //查找一個name(名稱),和parameterTypes(參數類型)匹配的方法
        Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);

        if (method == null) {
            throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
        }
        return method;
    }
@CallerSensitive
    public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException
    {
        if (!override) {
            //1. quickCheckMemberAccess進行權限檢查,若是是public,跳出if判斷
            //若是不是public,則獲取這個類(參考上一章),以後對這個類進行判斷
            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                Class<?> caller = Reflection.getCallerClass();
                checkAccess(caller, clazz, obj, modifiers);
            }
        }

        //再由MethodAccessor對象來調用invoke方法,具體往下看
        MethodAccessor ma = methodAccessor;             // read volatile
        if (ma == null) {
            ma = acquireMethodAccessor();
        }
        return ma.invoke(obj, args);
    }

MethodAccessor 是個啥玩意?
我也不知道,源碼中也並無寫更多註釋,但網絡上的一篇文章解釋了這個對象網絡

https://www.sczyh30.com/posts/Java/java-reflection-2/
其中做者解釋了使用這個對象的緣由ide

每一個Java方法有且只有一個Method對象做爲root,它至關於根對象,對用戶不可見。當咱們建立Method對象時,咱們代碼中得到的Method對象都至關於它的副本(或引用)。root對象持有一個MethodAccessor對象,因此全部獲取到的Method對象都共享這一個MethodAccessor對象,所以必須保證它在內存中的可見性。
時序圖post

invoke底層會經過jni去調用.dll動態連接庫的方法invoke0來實現方法的調用,native實際上是在JVM的棧中找到這個方法,而後經過方法實例根據參數進行方法運行ui

相關文章
相關標籤/搜索