天天看點

Spring-Aop學習的前提——反射+動态代理——2

繼上次的總結,首先說一下如何擷取私有構造函數:

通過反射擷取私有構造函數

Person.java

public class Person {
    private String name;
    private int age;
    public String address;
    public Person() {
        // TODO Auto-generated constructor stub
    }
    private Person(String name,int age) {
        this.name = name;
        this.age = age;
    }
    public Person(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
    public void show() {
        System.out.println("show........");
    }
    public void method(String s) {
        System.out.println("method  "+s);
    }
    public String getString(String s,int i) {
        return s+"==="+i;
    }
    private void function() {
        System.out.println("function");
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", address=" + address + "]";
    }
}
           

測試類:

//不加con.setAccessible(true);報錯:java.lang.IllegalAccessException:非法的通路異常
        Constructor con = c.getDeclaredConstructor(String.class,int.class);
        con.setAccessible(true);//值為true訓示反射的對象在使用時候取消java語言通路檢查
        Object object = con.newInstance("嘿嘿",20);
        System.out.println(object);
           

接下來說一下如何擷取成員變量并進行指派:

Class c = Class.forName("Reflect.Person"); //帶包的全路徑
        Field[] fields = c.getFields();  
        for (Field field : fields) {
            System.out.println(field);
        }
           

以上擷取的成員變量隻是public修飾的。

擷取全部的成員變量:

Field[] fields = c.getDeclaredFields(); //擷取全部的變量
        for (Field field : fields) {
            System.out.println(field);
        }
           

以上兩種方法是擷取全部的變量,接下來說一下如何擷取單個變量并進行使用:

通路公有屬性

//擷取address并對其指派  address是public修飾的
        Field addressFiled = c.getField("address");
        //通過無參構造方法建立對象
        Constructor con = c.getConstructor();
        Object obj = con.newInstance();
        //addressFiled.set(obj, value):給obj這個對象的addressField這個屬性設定值等于value
        addressFiled.set(obj, "濟南");
           

這個地方的指派比較難了解,addressFiled.set(obj, value);這句代碼的意思是給obj這個對象的addressFiled變量指派為value。

通路私有屬性:

//通路私有的name屬性
        Field nameField = c.getDeclaredField("name");
        nameField.setAccessible(true);
        nameField.set(obj, "張三");
           

以上是擷取構造器和屬性,還剩擷取所有方法,原理類似于擷取構造器和變量。

擷取公有的方法:

Method[] methods = c.getMethods();//擷取自己的公共方法,包括父類的公共方法
        for (Method method : methods) {
            System.out.println(method);
        }
           

經過測試發現,裡面的公有方法不僅是Person類裡的公有方法,而且包括Person父類Object裡的公有方法,那如何擷取Person類自身的構造方法呢?

Method[] methods = c.getDeclaredMethods();//擷取自己的所有方法
        for (Method method : methods) {
            System.out.println(method);
        }
           

接下來是擷取單個方法(這裡分成無參無傳回值、有參無傳回值、有多個參數,有傳回值、和私有方法四個方面來講,這四個方面也基本覆寫了我們類定義的方法)

首先我們構造出無參對象:

Constructor con = c.getConstructor();
        Object obj = con.newInstance();
           

首先看一下擷取無參無傳回值的show()方法:

Method m1 = c.getMethod("show");
m1.invoke(obj);
           

擷取有參數無傳回值的方法method:

Method m2 = c.getMethod("method", String.class); 
m2.invoke(obj, "hello");
           

取有多個參數的有傳回值得方法getString():

Method m3 = c.getMethod("getString", String.class,int.class); 
        Object objectString = m3.invoke(obj, "helloworld",);
        System.out.println(objectString);
           

擷取私有方法function():

Method m4 = c.getDeclaredMethod("function");
m4.setAccessible(true);
m4.invoke(obj);
           

以上就是我們擷取各種方法的步驟,下面我們總結一下:

1.c.getMethod(name, parameterTypes) 第一個參數表示方法名字,第二個參數表示形參的class類型。

2.m1.invoke(obj, args) 第一個參數表示對象是誰,第二個參數表示調用該方法實參。

以上就是反射的基本内容,接下來會舉幾個關于如何利用反射的列子。

繼續閱讀