最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談Java反射與代理

 更新時間:2016年07月24日 11:31:56   投稿:jingxian  
下面小編就為大家?guī)硪黄獪\談Java反射與代理。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

Java反射機制與動態(tài)代理,使得Java更加強大,Spring核心概念IoC、AOP就是通過反射機制與動態(tài)代理實現(xiàn)的。

1 Java反射

示例:

User user = new User();
user.setTime5Flag("test");
 
Class<?> cls = Class.forName("com.test.User");
//接口必須public,無論是否在本類內部使用!或者使用cls.getDeclaredMethod(),或者遍歷修改可訪問性
Method method = cls.getMethod("getTime5Flag");
String res1 = (String) method.invoke(user);
System.out.println(res1);
//涉及到基本類型如int,則使用int.class!Integer.class!=int.class!
method = cls.getMethod("setTime5Flag", String.class); 
method.invoke(user, "Rollen");
method = cls.getMethod("getTime5Flag");
String res2 = (String) method.invoke(user);
System.out.println(res2);

通過一個對象獲得完整的包名和類名:

user.getClass().getName();//全路徑類名
user.getClass().getSimpleName();//無包名的類名

獲取class:

Class.forName("com.test.User");
com.test.User.class;
user.getClass();
通過class實例化一個對象
User user = (User) cls.newInstance();//必須有無參構造函數(shù)
取得全部構造函數(shù)
Constructor<?> cons[]=cls.getConstructors(); //按聲明順序返回
cons[0].newInstance();//無顯示聲明,則有默認構造函數(shù)
取得一個類所實現(xiàn)的所有interface 
Class<?> intes[] = cls.getInterfaces();
取得父類
cls.getSuperClass();
取得修飾符
int mo = cls.getModifiers();
int mo = cons[0].getModifiers();
int mo = method.getModifiers();
Modifier.toString(mo);
獲取方法參數(shù)
method.getParametors();
cons[0].getParametors();
獲取方法參數(shù)類型
method.getParametorTypes();
cons[0].getParametorTypes();
獲取方法聲明拋出的所有異常類型
method.getExceptionTypes();
獲取本類聲明的全部屬性
Field[] field = cls.getDeclaredFields(); //包括private
field[0].getModifiers();
field[0].getType();

獲取本類的全部公開屬性,包括父類聲明、接口聲明、本類聲明的所有public屬性

cls.getFields();

設置指定屬性可訪問

field.setAccessible(true);
field.set(obj,'ces');
field.get(obj);

* getFields()與getDeclaredFields()區(qū)別:getFields()只能訪問類中聲明為公有的字段,私有的字段它無法訪問,能訪問從其它類繼承來的公有字段;getDeclaredFields()能訪問類中所有的字段,與public,private,protect無關,但不能訪問從其它類繼承來的字段

* getMethods()與getDeclaredMethods()區(qū)別:getMethods()只能訪問類中聲明為公有的方法,私有的方法它無法訪問,能訪問從其它類繼承來的公有方法;getDeclaredMethods()能訪問類中所有的字段,與public,private,protect無關,不能訪問從其它類繼承來的方法

* getConstructors()與getDeclaredConstructors()區(qū)別:getConstructors()只能訪問類中聲明為public的構造函數(shù);getDeclaredConstructors()能訪問類中所有的構造函數(shù),與public,private,protect無關

通過反射獲取并修改數(shù)組的信息


int[] temp={1,2,3,4,5};
Class<?> demo = temp.getClass().getComponentType();
System.out.println("數(shù)組類型: "+demo.getName());//int
System.out.println("數(shù)組長度: "+Array.getLength(temp));//5
System.out.println("數(shù)組的第一個元素: "+Array.get(temp, 0));//1
Array.set(temp, 0, 100);
System.out.println("修改之后數(shù)組第一個元素為: "+Array.get(temp, 0));//100
獲取數(shù)組類型
cls.getComponentType();
判斷是否是數(shù)組類型
cls.isArray();

2  Java代理

代理模式是常用的Java設計模式,它的特征是代理類與委托類有同樣的接口,代理類主要負責為委托類預處理消息、過濾消息、把消息轉發(fā)給委托類,以及事后處理消息等。代理類與委托類之間通常會存在關聯(lián)關系,一個代理類的對象與一個委托類的對象關聯(lián),代理類的對象本身并不真正實現(xiàn)服務,而是通過調用委托類的對象的相關方法,來提供特定的服務。

按照代理的創(chuàng)建時期,代理類可以分為2種。

•靜態(tài)代理:由程序員創(chuàng)建或特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的.class文件就已經存在了。

•動態(tài)代理:在程序運行時,由Java反射機制動態(tài)生成字節(jié)碼。

2.1 靜態(tài)代理

public interface Count { 
  public void queryCount();
}
public class CountImpl implements Count {
  public void queryCount() { 
    System.out.println("查看賬戶方法...");
  }
}
//代理類
public class CountProxy implements Count { 
  private CountImpl countImpl;  
  public CountProxy(CountImpl countImpl) { 
    this.countImpl = countImpl; 
  }  
  @Override 
  public void queryCount() { 
    System.out.println("事務處理之前");      
    countImpl.queryCount(); // 調用委托類的方法;
    System.out.println("事務處理之后"); 
  }
} 
//測試類
public class TestCount { 
  public static void main(String[] args) { 
    CountImpl countImpl = new CountImpl(); 
    CountProxy countProxy = new CountProxy(countImpl); 
    countProxy.queryCount();  
  } 
}

觀察代碼可以發(fā)現(xiàn)每一個代理類只能為一個接口服務,這樣一來程序開發(fā)中必然會產生過多的代理,而且,所有的代理操作除了調用的方法不一樣之外,其他的操作都一樣,則此時肯定是重復代碼。解決這一問題最好的做法是可以通過一個代理類完成全部的代理功能,那么此時就必須使用動態(tài)代理完成。

2.2   動態(tài)代理

動態(tài)代理類的字節(jié)碼在程序運行時由Java反射機制動態(tài)生成,無需程序員手工編寫它的源代碼。動態(tài)代理類不僅簡化了編程工作,而且提高了軟件系統(tǒng)的可擴展性,因為Java 反射機制可以生成任意類型的動態(tài)代理類。

2.2.1  JDK動態(tài)代理

java.lang.reflect 包中的Proxy類和InvocationHandler 接口提供了生成動態(tài)代理類的能力。

InvocationHandler接口:

public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}

參數(shù)說明:

Object proxy:指被代理的對象。
Method method:要調用的方法
Object[] args:方法調用時所需要的參數(shù)

可以將InvocationHandler接口的子類想象成一個代理的最終操作類,替換掉ProxySubject。

Proxy類:

Proxy類是專門完成代理的操作類,可以通過此類為一個或多個接口動態(tài)地生成實現(xiàn)類,此類提供了如下的操作方法:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException

參數(shù)說明:

ClassLoader loader:類加載器
Class<?>[] interfaces:得到全部的接口
InvocationHandler h:得到InvocationHandler接口的子類實例

如果想要完成動態(tài)代理,首先需要定義一個InvocationHandler接口的子類,以完成代理的具體操作。

interface Subject {
  public String say(String name, int age);
}
class RealSubject implements Subject {
  @Override
  public String say(String name, int age) {
    return name + " " + age;
  }
}
//JDK動態(tài)代理類
class MyInvocationHandler implements InvocationHandler {
  private Object target = null;
  //綁定委托對象并返回一個代理類
  public Object bind(Object target) {
    this. target = target;
    return Proxy.newProxyInstance(target.getClass().getClassLoader(),
          target.getClass().getInterfaces(), this); //要綁定接口(cglib彌補了這一點)
  }
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println(“before method!”);
    Object temp = method.invoke(target, args);
    System.out.println(“after method!”);
    return temp;
  }
}
class hello {
  public static void main(String[] args) {
    MyInvocationHandler demo = new MyInvocationHandler();
    Subject sub = (Subject) demo.bind(new RealSubject());
    String info = sub.say("Rollen", 20);
    System.out.println(info);
  }
}

但是,JDK的動態(tài)代理依靠接口實現(xiàn),如果有些類并沒有實現(xiàn)接口,則不能使用JDK代理,這就要使用cglib動態(tài)代理了。 

2.2.2  CGLIB動態(tài)代理

JDK的動態(tài)代理機制只能代理實現(xiàn)了接口的類,而未實現(xiàn)接口的類就不能實現(xiàn)JDK的動態(tài)代理。

cglib是針對類來實現(xiàn)代理的,它的原理是對指定的目標類生成一個子類,并覆蓋其中方法實現(xiàn)增強,但因為采用的是繼承,所以不能對final修飾的類進行代理。

public interface BookFacade { 
  public void addBook(); 
} 
public class BookFacadeImpl1 { 
  public void addBook() { 
    System.out.println("增加圖書的普通方法..."); 
  } 
} 
 
import java.lang.reflect.Method;  
import net.sf.cglib.proxy.Enhancer; 
import net.sf.cglib.proxy.MethodInterceptor; 
import net.sf.cglib.proxy.MethodProxy; 
//cglib動態(tài)代理類
public class BookFacadeCglib implements MethodInterceptor { 
  private Object target;  
  //綁定委托對象并返回一個代理類
  public Object getInstance(Object target) { 
    this.target = target; 
    Enhancer enhancer = new Enhancer(); 
    enhancer.setSuperclass(this.target.getClass()); 
    // 回調方法 
    enhancer.setCallback(this); 
    // 創(chuàng)建代理對象 
    return enhancer.create(); 
  }  
  @Override 
  // 回調方法 
  public Object intercept(Object obj, Method method, Object[] args, 
      MethodProxy proxy) throws Throwable { 
    System.out.println("事物開始"); 
    Object temp = proxy.invokeSuper(obj, args); 
    System.out.println("事物結束"); 
    return temp;  
  } 
} 
public class TestCglib {
  public static void main(String[] args) { 
    BookFacadeCglib cglib = new BookFacadeCglib(); 
    BookFacadeImpl1 bookCglib = (BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1()); 
    bookCglib.addBook(); 
  } 
}

以上這篇淺談Java反射與代理就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • 解決@Async(“taskExecutor“)異步線程報錯問題

    解決@Async(“taskExecutor“)異步線程報錯問題

    這篇文章主要介紹了解決@Async(“taskExecutor“)異步線程報錯問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • java兩個數(shù)組合并為一個數(shù)組的幾種方法

    java兩個數(shù)組合并為一個數(shù)組的幾種方法

    這篇文章主要給大家介紹了關于java兩個數(shù)組合并為一個數(shù)組的幾種方法,最近在寫代碼時遇到了需要合并兩個數(shù)組的需求,文中將每種方法都介紹的非常詳細,需要的朋友可以參考下
    2023-07-07
  • 有關Java常見的誤解小結(來看一看)

    有關Java常見的誤解小結(來看一看)

    下面小編就為大家?guī)硪黄嘘PJava常見的誤解小結(來看一看)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • spring-cloud-gateway啟動踩坑及解決

    spring-cloud-gateway啟動踩坑及解決

    這篇文章主要介紹了spring-cloud-gateway啟動踩坑及解決方案,具有很好的參考價值,希望對大家有所幫助。
    2021-08-08
  • IDEA中java斷言assert語法及使用

    IDEA中java斷言assert語法及使用

    這篇文章主要介紹了IDEA中java斷言assert語法詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • nohup運行Java tail查看日志方式

    nohup運行Java tail查看日志方式

    nohup命令允許程序在用戶退出賬戶或關閉終端后繼續(xù)運行,常與"&"結合使用以實現(xiàn)程序的后臺執(zhí)行,配合重定向操作,nohup可以將程序輸出保存到日志文件中,如nohup java -jar XXX.jar &> myout.log &,此外,tail命令可用于實時監(jiān)控日志文件的變化
    2024-09-09
  • Spring-AOP @AspectJ切點函數(shù)之@annotation()用法

    Spring-AOP @AspectJ切點函數(shù)之@annotation()用法

    這篇文章主要介紹了Spring-AOP @AspectJ切點函數(shù)之@annotation()用法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 利用Socket.io 實現(xiàn)消息實時推送功能

    利用Socket.io 實現(xiàn)消息實時推送功能

    這篇文章主要介紹了利用Socket.io 實現(xiàn)消息實時推送功能,需要的朋友可以參考下
    2017-12-12
  • 詳解Spring中InitializingBean接口的功能

    詳解Spring中InitializingBean接口的功能

    這篇文章主要介紹了Spring中InitializingBean接口的功能,講述了spring中InitializingBean接口的功能簡介說明,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • springboot 多模塊將dao(mybatis)項目拆分出去

    springboot 多模塊將dao(mybatis)項目拆分出去

    這篇文章主要介紹了springboot 多模塊將dao(mybatis)項目拆分出去,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05

最新評論

平远县| 丹阳市| 苏尼特左旗| 门源| 大化| 洛川县| 潞西市| 商洛市| 酒泉市| 玉屏| 长阳| 封开县| 上饶市| 黎城县| 长海县| 宁南县| 交口县| 南漳县| 宜良县| 林西县| 孟津县| 泸定县| 晋州市| 鹤山市| 红河县| 嵊泗县| 开封市| 体育| 成武县| 海南省| 米脂县| 宝山区| 汝南县| 聂荣县| 腾冲县| 勐海县| 鹤庆县| 香格里拉县| 龙南县| 江门市| 肥东县|