java 反射和動態代理

caoyanzhi發表於2020-12-16

1:理解Class類及瞭解其常用的方法

 

  方法名功能說明
static Class forName(String name)返回指定類名 name 的 Class 物件
Object newInstance()呼叫預設建構函式,返回該Class物件的一個例項
getName()返回此Class物件所表示的實體(類、介面、陣列類、基本型別 或void)名稱
Class getSuperClass()返回當前Class物件的父類的Class物件
Class [] getInterfaces()獲取當前Class物件的介面
ClassLoader getClassLoader()返回該類的類載入器
Class getSuperclass()返回表示此Class所表示的實體的超類的Class
Constructor[] getConstructors()返回一個包含某些Constructor物件的陣列
Field[] getDeclaredFields()返回Field物件的一個陣列
Method getMethod(String name,Class … paramTypes)返回一個Method物件,此物件的形參型別為paramType

2獲取Class的幾種常用方法:

              假如有一個類  在 com.test.entity 這個包下面有一個Student物件

                《1》:Class<Student>  stu = Student.class;

                《2》:Student stu=new Student();

                             Class<Student>  stu =stu.getClass();

                《3》:Class  stu = Class.forName(“com.test.entity.Student”);
                               

3類的載入器讀取配置檔案

   Properties用來讀取配置檔案

              Properties pros =  new Properties();

《--------------------------------------------------兩種讀取方式---------------------------------------------------------------》

          用流方式讀取

           FileInputStream fis = new FileInputStream("jdbc.properties");

    用類載入器讀取

         ClassLoader classLoader = 當前物件名.class.getClassLoader();
         InputStream is = classLoader.getResourceAsStream("jdbc.properties");

《-------------------------------------------兩種讀取方式結束----------------------------------------------------------------------》

           pros.load(fis);

          根據配檔案的key獲取值      

        pros.getProperty("user");

動態代理是反射的一種應用

  動態代理實現思路和核心程式碼

1:代理物件和被代理物件必須實現同一套介面  我們需要定義介面

2:建立被代理物件實現定義好的介面

3:呼叫reflect API  獲取代理物件

4:實現當通過代理類的物件呼叫方法a時,動態的去呼叫被代理類中的同名方法a;

程式碼舉例: 

interface Human{

    String getBelief();

    void eat(String food);

}
//被代理類
class SuperMan implements Human{


    @Override
    public String getBelief() {
        return "I believe I can fly!";
    }

    @Override
    public void eat(String food) {
        System.out.println("我喜歡吃" + food);
    }
}



/*
要想實現動態代理,需要解決的問題?
問題一:如何根據載入到記憶體中的被代理類,動態的建立一個代理類及其物件。
問題二:當通過代理類的物件呼叫方法a時,如何動態的去呼叫被代理類中的同名方法a。


 */

class ProxyFactory{
    //呼叫此方法,返回一個代理類的物件。解決問題一
    public static Object getProxyInstance(Object obj){//obj:被代理類的物件
        MyInvocationHandler handler = new MyInvocationHandler();

        handler.bind(obj);

        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
    }

}

class MyInvocationHandler implements InvocationHandler{

    private Object obj;//需要使用被代理類的物件進行賦值

    public void bind(Object obj){
        this.obj = obj;
    }

    //當我們通過代理類的物件,呼叫方法a時,就會自動的呼叫如下的方法:invoke()
    //將被代理類要執行的方法a的功能就宣告在invoke()中
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

       
        //method:即為代理類物件呼叫的方法,此方法也就作為了被代理類物件要呼叫的方法
        //obj:被代理類的物件
        Object returnValue = method.invoke(obj,args);

        //上述方法的返回值就作為當前類中的invoke()的返回值。
        return returnValue;

    }
}

呼叫舉例

 SuperMan superMan = new SuperMan();
        //proxyInstance:代理類的物件
        Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
        //當通過代理類物件呼叫方法時,會自動的呼叫被代理類中同名的方法
        String belief = proxyInstance.getBelief();
        System.out.println(belief);
        proxyInstance.eat("餃子");

        System.out.println("*****************************");

    

           

相關文章