欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java的動(dòng)態(tài)代理和靜態(tài)代理及反射常用API詳解

 更新時(shí)間:2024年01月15日 08:35:43   作者:小湯湯湯湯  
這篇文章主要介紹了Java的動(dòng)態(tài)代理和靜態(tài)代理及反射常用API詳解,動(dòng)態(tài)代理是一種在運(yùn)行時(shí)動(dòng)態(tài)生成代理對(duì)象的技術(shù),它是一種設(shè)計(jì)模式,用于在不修改原始對(duì)象的情況下,通過(guò)代理對(duì)象來(lái)間接訪問(wèn)原始對(duì)象,并在訪問(wèn)前后執(zhí)行額外的操作,需要的朋友可以參考下

JDK動(dòng)態(tài)代理

我們看下JDK動(dòng)態(tài)代理的實(shí)現(xiàn)步驟:

第一步:創(chuàng)建接口,JDK動(dòng)態(tài)代理基于接口實(shí)現(xiàn),所以接口必不可少(準(zhǔn)備工作)

第二步:實(shí)現(xiàn)InvocationHandler接口,重寫invoke方法(準(zhǔn)備工作)

第三步:調(diào)用Proxy的靜態(tài)方法newProxyInstance方法生成代理實(shí)例(生成實(shí)例時(shí)需要提供類加載器,我們可以使用接口類的加載器即可)

第四步:使用新生成的代理實(shí)例調(diào)用某個(gè)方法實(shí)現(xiàn)功能。

我們的動(dòng)態(tài)代理實(shí)現(xiàn)過(guò)程中根本沒(méi)有涉及到真實(shí)類實(shí)例。

靜態(tài)代理

 package ceshi1;
 public interface Iuser {
     void eat(String s);
 }
package ceshi1;
public class UserImpl implements Iuser {
  @Override
  public void eat(String s) {
    System.out.println("我要吃"+s);
  }
}
package ceshi1;
public class UserProxy implements Iuser {
  private Iuser user = new UserImpl();
  @Override
  public void eat(String s) {
    System.out.println("靜態(tài)代理前置內(nèi)容");
    user.eat(s);
    System.out.println("靜態(tài)代理后置內(nèi)容");
  }
}
package ceshi1;
public class ProxyTest {
  public static void main(String[] args) {
    UserProxy proxy = new UserProxy();
    proxy.eat("蘋果");
  }
}

動(dòng)態(tài)代理

package ceshi1;
 public interface Iuser {
   void eat(String s);
 }
package ceshi1;
public class UserImpl implements Iuser {
  @Override
  public void eat(String s) {
    System.out.println("我要吃"+s);
  }
}
package ceshi1;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicProxy implements InvocationHandler {
  private Object object;//用于接收具體實(shí)現(xiàn)類的實(shí)例對(duì)象
  //使用帶參數(shù)的構(gòu)造器來(lái)傳遞具體實(shí)現(xiàn)類的對(duì)象
  public DynamicProxy(Object obj){
    this.object = obj;
  }
  @Override
  public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
    System.out.println("前置內(nèi)容");
    method.invoke(object, args);
    System.out.println("后置內(nèi)容");
    return null;
  }
}
package ceshi1;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class ProxyTest {
  public static void main(String[] args) {
    Iuser user = new UserImpl();
    InvocationHandler h = new DynamicProxy(user);
    Iuser proxy = (Iuser) Proxy.newProxyInstance(Iuser.class.getClassLoader(), new Class[]{Iuser.class}, h);
    proxy.eat("蘋果");
  }
}

反射

JDK 提供的反射 API 進(jìn)行反射調(diào)用:

Class clz = Class.forName("com.chenshuyi.reflect.Apple");
Method method = clz.getMethod("setPrice", int.class);
Constructor constructor = clz.getConstructor();
Object object = constructor.newInstance();
method.invoke(object, 4);

一般情況下我們使用反射獲取一個(gè)對(duì)象的步驟:

獲取類的 Class 對(duì)象實(shí)例

Class clz = Class.forName("com.zhenai.api.Apple");

根據(jù) Class 對(duì)象實(shí)例獲取 Constructor 對(duì)象

Constructor appleConstructor = clz.getConstructor();

使用 Constructor 對(duì)象的 newInstance 方法獲取反射類對(duì)象

Object appleObj = appleConstructor.newInstance();

而如果要調(diào)用某一個(gè)方法,則需要經(jīng)過(guò)下面的步驟:

獲取方法的 Method 對(duì)象

Method setPriceMethod = clz.getMethod("setPrice", int.class);

利用 invoke 方法調(diào)用方法

setPriceMethod.invoke(appleObj, 14);

反射常用API

在 Java API 中,獲取 Class 類對(duì)象有三種方法:

第一種,使用 Class.forName 靜態(tài)方法。當(dāng)你知道該類的全路徑名時(shí),你可以使用該方法獲取 Class 類對(duì)象。

Class clz = Class.forName("java.lang.String");

第二種,使用 .class 方法。

這種方法只適合在編譯前就知道操作的 Class。

Class clz = String.class;

第三種,使用類對(duì)象的 getClass() 方法。

String str = new String("Hello");

Class clz = str.getClass();

通過(guò)反射創(chuàng)建類對(duì)象

通過(guò)反射創(chuàng)建類對(duì)象主要有兩種方式:通過(guò) Class 對(duì)象的 newInstance() 方法、通過(guò) Constructor 對(duì)象的 newInstance() 方法。

第一種:通過(guò) Class 對(duì)象的 newInstance() 方法。

Class clz = Apple.class;
Apple apple = (Apple)clz.newInstance();

第二種:通過(guò) Constructor 對(duì)象的 newInstance() 方法

Class clz = Apple.class;
Constructor constructor = clz.getConstructor();
Apple apple = (Apple)constructor.newInstance();

通過(guò) Constructor 對(duì)象創(chuàng)建類對(duì)象可以選擇特定構(gòu)造方法,而通過(guò) Class 對(duì)象則只能使用默認(rèn)的無(wú)參數(shù)構(gòu)造方法。下面的代碼就調(diào)用了一個(gè)有參數(shù)的構(gòu)造方法進(jìn)行了類對(duì)象的初始化。

Class clz = Apple.class;
Constructor constructor = clz.getConstructor(String.class, int.class);
Apple apple = (Apple)constructor.newInstance("紅富士", 15);

我們通過(guò) Class 對(duì)象的 getFields() 方法可以獲取 Class 類的屬性,但無(wú)法獲取私有屬性。

Class clz = Apple.class;
Field[] fields = clz.getFields();
for (Field field : fields) {
    System.out.println(field.getName());
}

而如果使用 Class 對(duì)象的 getDeclaredFields() 方法則可以獲取包括私有屬性在內(nèi)的所有屬性:

Class clz = Apple.class;
Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
    System.out.println(field.getName());
}

到此這篇關(guān)于Java的動(dòng)態(tài)代理和靜態(tài)代理及反射常用API詳解的文章就介紹到這了,更多相關(guān)Java動(dòng)態(tài)代理和反射內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論