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

淺談Java反射與代理

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

Java反射機(jī)制與動(dòng)態(tài)代理,使得Java更加強(qiáng)大,Spring核心概念I(lǐng)oC、AOP就是通過反射機(jī)制與動(dòng)態(tài)代理實(shí)現(xiàn)的。

1 Java反射

示例:

User user = new User();
user.setTime5Flag("test");
 
Class<?> cls = Class.forName("com.test.User");
//接口必須public,無論是否在本類內(nèi)部使用!或者使用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);

通過一個(gè)對(duì)象獲得完整的包名和類名:

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

獲取class:

Class.forName("com.test.User");
com.test.User.class;
user.getClass();
通過class實(shí)例化一個(gè)對(duì)象
User user = (User) cls.newInstance();//必須有無參構(gòu)造函數(shù)
取得全部構(gòu)造函數(shù)
Constructor<?> cons[]=cls.getConstructors(); //按聲明順序返回
cons[0].newInstance();//無顯示聲明,則有默認(rèn)構(gòu)造函數(shù)
取得一個(gè)類所實(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();

設(shè)置指定屬性可訪問

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

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

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

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

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


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

2  Java代理

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

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

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

•動(dòng)態(tài)代理:在程序運(yùn)行時(shí),由Java反射機(jī)制動(dòng)態(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("事務(wù)處理之前");      
    countImpl.queryCount(); // 調(diào)用委托類的方法;
    System.out.println("事務(wù)處理之后"); 
  }
} 
//測(cè)試類
public class TestCount { 
  public static void main(String[] args) { 
    CountImpl countImpl = new CountImpl(); 
    CountProxy countProxy = new CountProxy(countImpl); 
    countProxy.queryCount();  
  } 
}

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

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

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

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

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

InvocationHandler接口:

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

參數(shù)說明:

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

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

Proxy類:

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

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

參數(shù)說明:

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

如果想要完成動(dòng)態(tài)代理,首先需要定義一個(gè)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動(dòng)態(tài)代理類
class MyInvocationHandler implements InvocationHandler {
  private Object target = null;
  //綁定委托對(duì)象并返回一個(gè)代理類
  public Object bind(Object target) {
    this. target = target;
    return Proxy.newProxyInstance(target.getClass().getClassLoader(),
          target.getClass().getInterfaces(), this); //要綁定接口(cglib彌補(bǔ)了這一點(diǎn))
  }
  @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的動(dòng)態(tài)代理依靠接口實(shí)現(xiàn),如果有些類并沒有實(shí)現(xiàn)接口,則不能使用JDK代理,這就要使用cglib動(dòng)態(tài)代理了。 

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

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

cglib是針對(duì)類來實(shí)現(xiàn)代理的,它的原理是對(duì)指定的目標(biāo)類生成一個(gè)子類,并覆蓋其中方法實(shí)現(xiàn)增強(qiáng),但因?yàn)椴捎玫氖抢^承,所以不能對(duì)final修飾的類進(jìn)行代理。

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動(dòng)態(tài)代理類
public class BookFacadeCglib implements MethodInterceptor { 
  private Object target;  
  //綁定委托對(duì)象并返回一個(gè)代理類
  public Object getInstance(Object target) { 
    this.target = target; 
    Enhancer enhancer = new Enhancer(); 
    enhancer.setSuperclass(this.target.getClass()); 
    // 回調(diào)方法 
    enhancer.setCallback(this); 
    // 創(chuàng)建代理對(duì)象 
    return enhancer.create(); 
  }  
  @Override 
  // 回調(diào)方法 
  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("事物結(jié)束"); 
    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反射與代理就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • idea更改默認(rèn)緩存位置的步驟詳解

    idea更改默認(rèn)緩存位置的步驟詳解

    在idea使用中,會(huì)產(chǎn)生大量的緩存,一般默認(rèn)存放在C盤里面,會(huì)加大C盤的儲(chǔ)存負(fù)擔(dān),如果C盤足夠大,可以不考慮更改idea的緩存位置,所以本文小編給如何更改idea默認(rèn)緩存位置,文中通過圖文結(jié)合介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • 詳解獲取Spring MVC中所有RequestMapping以及對(duì)應(yīng)方法和參數(shù)

    詳解獲取Spring MVC中所有RequestMapping以及對(duì)應(yīng)方法和參數(shù)

    本篇文章主要介紹了詳解獲取Spring MVC中所有RequestMapping以及對(duì)應(yīng)方法和參數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-03-03
  • java中構(gòu)造方法和普通方法的區(qū)別說明

    java中構(gòu)造方法和普通方法的區(qū)別說明

    這篇文章主要介紹了java中構(gòu)造方法和普通方法的區(qū)別說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • MybatisPlus實(shí)現(xiàn)數(shù)據(jù)攔截的使用示例

    MybatisPlus實(shí)現(xiàn)數(shù)據(jù)攔截的使用示例

    在MyBatis-Plus中,可以通過自定義攔截器來實(shí)現(xiàn)對(duì)SQL語句的攔截和修改,本文就來介紹一下如何使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-10-10
  • idea搭建mybatis環(huán)境配置全過程

    idea搭建mybatis環(huán)境配置全過程

    本文介紹了如何以IDEA搭建MyBatis環(huán)境配置的方法,包括步驟和注意事項(xiàng),通過本文的介紹,可以輕松地以IDEA搭建MyBatis環(huán)境配置,提高開發(fā)效率
    2023-10-10
  • SpringBoot快速構(gòu)建應(yīng)用程序方法介紹

    SpringBoot快速構(gòu)建應(yīng)用程序方法介紹

    這篇文章主要介紹了SpringBoot快速構(gòu)建應(yīng)用程序方法介紹,涉及SpringBoot默認(rèn)的錯(cuò)誤頁(yè)面,嵌入式Web容器層面的約定和定制等相關(guān)內(nèi)容,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-11-11
  • 使用AOP+反射實(shí)現(xiàn)自定義Mybatis多表關(guān)聯(lián)查詢

    使用AOP+反射實(shí)現(xiàn)自定義Mybatis多表關(guān)聯(lián)查詢

    這篇文章主要介紹了使用AOP+反射實(shí)現(xiàn)自定義Mybatis多表關(guān)聯(lián),目前的需求是增強(qiáng)現(xiàn)有的查詢,使用簡(jiǎn)單的注解即可實(shí)現(xiàn)多表關(guān)聯(lián),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-05-05
  • 詳解springboot整合ehcache實(shí)現(xiàn)緩存機(jī)制

    詳解springboot整合ehcache實(shí)現(xiàn)緩存機(jī)制

    這篇文章主要介紹了詳解springboot整合ehcache實(shí)現(xiàn)緩存機(jī)制,ehcache提供了多種緩存策略,主要分為內(nèi)存和磁盤兩級(jí),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • spring/springboot整合dubbo詳細(xì)教程

    spring/springboot整合dubbo詳細(xì)教程

    今天教大家如何使用spring/springboot整合dubbo,文中有非常詳細(xì)的圖文介紹及代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴有很好地幫助,需要的朋友可以參考下
    2021-05-05
  • java中實(shí)現(xiàn)分頁(yè)的幾種常見方式總結(jié)

    java中實(shí)現(xiàn)分頁(yè)的幾種常見方式總結(jié)

    在項(xiàng)目中經(jīng)常會(huì)查詢大量數(shù)據(jù),這就要用到分頁(yè)展示,下面這篇文章主要給大家介紹了關(guān)于java中實(shí)現(xiàn)分頁(yè)的幾種常見方式,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12

最新評(píng)論