国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java動(dòng)態(tài)代理、反射

這篇具有很好參考價(jià)值的文章主要介紹了Java動(dòng)態(tài)代理、反射。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

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

調(diào)用者—>代理—>對象

動(dòng)態(tài)代理就是無侵入式的給代碼增加新的功能,通過接口保證后面的對象和代理需要實(shí)現(xiàn)同一個(gè)接口,接口中就是被代理的所有方法,代理里面就是對象要被代理的方法。

為什么需要代理

因?yàn)橐粋€(gè)對象覺得自己身上的功能太多,就會(huì)將一部分功能代理出去,對象中什么方法想要被代理,在代理中必須有對應(yīng)的方法,一般會(huì)定義一個(gè)接口,接口中的方法是想要被代理的方法

代理的詳細(xì)實(shí)現(xiàn)過程

首先是有一個(gè)需要被代理的對象,然后這個(gè)對象中有哪個(gè)方法想要被代理,創(chuàng)建一個(gè)接口,接口中的方法就是這個(gè)對象想要被代理的方法,在這個(gè)對象中需要實(shí)現(xiàn)這個(gè)接口,然后重寫這幾個(gè)方法。這時(shí)候就需要一個(gè)代理類,這個(gè)代理類,這個(gè)代理類主要是用到里面的代理方法,這個(gè)方法的作用是給一個(gè)對象創(chuàng)建一個(gè)代理,將需要被代理的對象傳入其中,然后返回的是代理的對象。在這個(gè)方法里面,需要調(diào)用一個(gè)方法,就是java.util.reflect.Proxy類里面的一個(gè)方法,由于這個(gè)方法是靜態(tài)方法,所以可以直接使用類名進(jìn)行調(diào)用,public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)在這個(gè)方法中,第一個(gè)參數(shù)是指定哪一個(gè)類加載器去加載生成的代理類,第二個(gè)參數(shù)是指定的接口,第三個(gè)參數(shù)是用于指定生成的代理對象要干什么,一般創(chuàng)建代理對象不會(huì)調(diào)用到第三個(gè)參數(shù),后面只有通過代理對象進(jìn)行方法回調(diào)的時(shí)候才會(huì)調(diào)用第三個(gè)參數(shù),在執(zhí)行這個(gè)第三個(gè)參數(shù)時(shí),會(huì)重寫invoke方法進(jìn)行代理方法的實(shí)現(xiàn),傳入invoke方法有三個(gè)參數(shù),第一個(gè)參數(shù)是傳入代理的對象,第二個(gè)參數(shù)是傳入需要運(yùn)行的就是原本對象的方法,第三個(gè)參數(shù)就是傳入這個(gè)方法的參數(shù)。在返回的時(shí)候,返回的是傳入這個(gè)方法的invoke方法傳回的值。

代碼詳情

  • 首先是定義一個(gè)方法,里面是所有的功能,這里定義了一個(gè)明星類
public class BigStar implements Star {
    private String name;

    public BigStar() {

    }

    public BigStar(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String sing(String name) {
        System.out.println(this.name + "正在唱" + name);
        return "謝謝";
    }

    @Override
    public void dance() {
        System.out.println(this.name + "跳舞");
    }
}


  • 其次是一個(gè)需要代理的方法
/**
 * 我們可以將所有想要被代理的方法定義在接口當(dāng)中
 */
public interface Star {

    // 唱歌
    String sing(String name);

    // 跳舞
    void dance();
}


  • 然后是一個(gè)代理類
public class ProxyUtil {
    /**
     * 這個(gè)方法的作用:給明星的一個(gè)對象創(chuàng)建一個(gè)代理
     * @param bigStar 被代理的明星對象
     * @return 給明星創(chuàng)建的代理
     */
    public static Star createProxy(BigStar bigStar){

        /**
         * java.util.reflect.Proxy類:提供了為對象產(chǎn)生代理對象的方法
         * public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
         * 參數(shù)一:用于指定用哪個(gè)類加載器去加載生成的代理類
         * 參數(shù)二:指定接口,就是這個(gè)接口用于指定生成的代理有哪些方法
         * 參數(shù)三:用于指定生成的代理對象要干什么
         */
        Star star = (Star) Proxy.newProxyInstance(
                ProxyUtil.class.getClassLoader(),
                new Class[]{Star.class},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        /**
                         * 參數(shù)一:代理的對象
                         * 參數(shù)二:要運(yùn)行的方法
                         * 參數(shù)三:調(diào)用方法時(shí)傳遞的實(shí)參
                         */
                        if("sing".equals(method.getName())){
                            System.out.println("給話筒");
                        } else if ("dance".equals(method.getName())) {
                            System.out.println("準(zhǔn)備場地");
                        }
                        return method.invoke(bigStar, args);
                    }
                }
        );

        return star;
    }
}


  • 測試代理
public class Test {
    public static void main(String[] args) {

        BigStar bigStar = new BigStar("坤哥");
        Star prosy = ProxyUtil.createProxy(bigStar);
        String res = prosy.sing("雞你太美");
        System.out.println(res);
//        ProxyUtil.createProxy(bigStar).dance();
    }
}

反射

反射概念

反射就是可以在運(yùn)行時(shí)分析類和執(zhí)行類的能力,通過反射可以獲得任意一個(gè)類的屬性和方法,還可以調(diào)用這些類的屬性和方法。比如下面這張圖片。

Java動(dòng)態(tài)代理、反射,Java基礎(chǔ),java,開發(fā)語言

反射中常用的方法

在反射中,我們可以使用三種方式調(diào)用類的字節(jié)碼文件,分別是Class.forName(全類名),類名.class,對象.getClass();在這三種調(diào)用類的字節(jié)碼的過程中,第一種一般市用在類加載過程中的,第二種經(jīng)常作為參數(shù)進(jìn)行調(diào)用,第三種一般是創(chuàng)建對象之后,然后使用對象名進(jìn)行調(diào)用。當(dāng)我們獲取到類的字節(jié)碼文件之后,就可以通過類的字節(jié)碼文件去調(diào)用類中的構(gòu)造方法,成員變量和成員方法以及他們相應(yīng)的信息。構(gòu)造方法(Constructor),使用getConstructors可以獲取到所有的公共的構(gòu)造方法,使用getDeclaredConstructors可以獲取所有的構(gòu)造方法,使用不加s的可以用來獲取單個(gè)的構(gòu)造方法,但是需要傳入構(gòu)造方法中傳入的參數(shù)類型,比如Stirng就需要傳入String.class,int就需要傳入int.class,Declared是用來控制是否查找公共方法,當(dāng)我們獲取到某個(gè)對象之后,可以使用getModifiers獲取修飾這個(gè)對象的權(quán)限修飾符(但是一般獲取到的都是數(shù)字比如下圖),使用getParameters獲取這個(gè)對象中所有傳入?yún)?shù)的類型,然后使用newInstance去構(gòu)造這個(gè)對象,但是一般private修飾的方法會(huì)報(bào)錯(cuò),需要使用setAccessible(true)消除掉當(dāng)前方法的修飾權(quán)限。

Java動(dòng)態(tài)代理、反射,Java基礎(chǔ),java,開發(fā)語言

Java動(dòng)態(tài)代理、反射,Java基礎(chǔ),java,開發(fā)語言

反射雖然給與了我們在運(yùn)行時(shí)分析類和操作類的能力,但是也增加了安全性問題,可以通過setAccessible(true)方法設(shè)置對象可被強(qiáng)制訪問,可以破壞單例的封裝性文章來源地址http://www.zghlxwxcb.cn/news/detail-666028.html

所有代碼

  • 獲取類字節(jié)碼文件
/**
 * Java反射
 * 反射允許對類的成員變量,成員方法,構(gòu)造方法的信息進(jìn)行編程訪問
 * 可以獲取到這三者的權(quán)限修飾符,名字,返回值類型??梢詫Λ@取到的屬性賦值,或者獲取已經(jīng)有的值。
 * 可以獲取到成員方法返回的值,還可以獲取到方法拋出的異常,方法上的注解
 * 可以運(yùn)行獲取出來的方法
 *
 * 首先要獲取.class字節(jié)碼文件
 * 獲取class對象的三種方式:
 * 1. Class.forName("全類名");  <源代碼階段使用>
 * 2. 類名.class   <類加載階段使用>
 * 3. 對象.getClass();    <運(yùn)行階段使用>
 */
public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        Student student = new Student();

        // 最常見的一種
        System.out.println(Class.forName("oop.reflectdemo.reflect.Student"));

        // 一般當(dāng)作參數(shù)進(jìn)行傳遞
        System.out.println(Student.class);

        // 當(dāng)只有這個(gè)類的對象才可以使用
        System.out.println(student.getClass());
    }
}

  • 獲取類中的構(gòu)造方法,屬性,以及成員方法信息
/**
 * Java反射
 * 常見的獲取構(gòu)造方法,成員變量,成員方法的方法
 * Java中Constructor描述構(gòu)造方法,F(xiàn)ield描述成員變量,Method描述成員方法
 */
public class ReflectDemo2 {
    public static void main(String[] args) throws Exception {

        // 獲取字節(jié)碼文件對象
        Class clazz = Class.forName("oop.reflectdemo.reflect.Student");

        // 獲取所有公共的的構(gòu)造方法
        Constructor[] constructor = clazz.getConstructors();
        for (Constructor constructor1 : constructor) {
            System.out.println(constructor1);
        }

        // 獲取所有的構(gòu)造方法
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

        /**
         * 獲取單個(gè)構(gòu)造方法
         * 后面括號(hào)里面需輸入這個(gè)構(gòu)造方法的傳入值類型
         * 一般getConstructor只能獲取到public修飾的方法,而要獲取到所有權(quán)限修飾的方法必須用getDeclaredConstructor;
         *
         */
        clazz.getConstructor(); // 獲取無參構(gòu)造

        clazz.getConstructor(String.class); // 獲取傳入?yún)?shù)為String類型的構(gòu)造方法

        Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class, int.class);// 獲取傳入?yún)?shù)為int的構(gòu)造方法

        // 獲取修飾這個(gè)對象的權(quán)限修飾符
        int modifiers = declaredConstructor.getModifiers();
        System.out.println(modifiers);

        // 獲取這個(gè)對象中所有傳入?yún)?shù)的類型
        declaredConstructor.getParameters();

        declaredConstructor.setAccessible(true);
        Student tom = (Student) declaredConstructor.newInstance("Tom", 21);
        System.out.println(tom);


        /**
         * 操作成員變量
         */
        // 獲取public修飾的所有的成員變量
        Field[] fields = clazz.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        // 獲取所有成員變量
        Field[] declaredField = clazz.getDeclaredFields();
        for (Field field : declaredField) {
            System.out.println(field);
        }


        // 返回單個(gè)的成員變量對象
        Field name = clazz.getDeclaredField("name");
        System.out.println(name);
        // 獲取權(quán)限修飾符
        int modifiers1 = name.getModifiers();
        System.out.println(modifiers1);

        // 獲取名字
        String name1 = name.getName();
        System.out.println(name1);

        // 獲取類型
        Class<?> type = name.getType();
        System.out.println(type);

        // 獲取成員變量記錄的值
        Student s = new Student("Tom", 32);
        name.setAccessible(true);
        Object value = name.get(s);
        System.out.println(value);

        // 修改對象里面的值
        name.set(s,"Jerry");
        System.out.println(s.getName());


        /**
         * 操作成員方法
         */
        // 獲取所有的公共方法
        Method[] methods = clazz.getMethods();

        // 獲取所有的方法
        Method[] declaredMethods = clazz.getDeclaredMethods();

        /**
         * 獲取方法進(jìn)行調(diào)用
         */
        // 獲取單個(gè)方法, 傳入方法名,后面跟著方法傳入的參數(shù)類型
        Method eat = clazz.getMethod("eat", String.class);

        // 獲取方法的權(quán)限修飾符
        int modifiers2 = eat.getModifiers();

        // 獲取方法的形參
        Parameter[] parameters = eat.getParameters();

        // 獲取方法拋出的異常
        Class<?>[] exceptionTypes = eat.getExceptionTypes();

        // 方法運(yùn)行
        Student student = new Student();
        eat.setAccessible(true);
        eat.invoke(student,"漢堡");


    }
}

到了這里,關(guān)于Java動(dòng)態(tài)代理、反射的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Java反射機(jī)制,動(dòng)態(tài)代理,hook以及在Retrofit源碼中的應(yīng)用

    Java反射機(jī)制,動(dòng)態(tài)代理,hook以及在Retrofit源碼中的應(yīng)用

    1.反射的基礎(chǔ)知識(shí): Java的反射機(jī)制是指在程序的運(yùn)行狀態(tài)中,可以構(gòu)造任意一個(gè)類的對象,可以了解任意一個(gè)對象所屬的類,可以了解任意一個(gè)類的成員變量和方法,可以調(diào)用任意一個(gè)對象的屬性和方法。這種動(dòng)態(tài)獲取程序信息以及動(dòng)態(tài)調(diào)用對象的功能稱為Java語言的反射機(jī)

    2024年02月13日
    瀏覽(17)
  • java語法(二)線程并發(fā)、Juit單元測試、反射機(jī)制、注解、動(dòng)態(tài)代理、XML解析、JVM

    java語法(二)線程并發(fā)、Juit單元測試、反射機(jī)制、注解、動(dòng)態(tài)代理、XML解析、JVM

    正則表達(dá)式驗(yàn)證網(wǎng)站 1、 ? :表示前邊這個(gè)字符可以出現(xiàn)0次或者1次。例如下邊 /used? 既可以匹配 use 也可以匹配 used 。 2、 * :匹配0個(gè)或者多個(gè)字符, * 號(hào)代表前邊這個(gè)字符可以出現(xiàn)0次或者多次。例如 /ab*c 可以匹配 ac、abc、abbbbc 3、 + :與 * 號(hào)不同的是, + 需要前面這個(gè)字符

    2024年02月06日
    瀏覽(25)
  • java基礎(chǔ)之Java的動(dòng)態(tài)代理如何實(shí)現(xiàn)

    目錄 Java實(shí)現(xiàn)動(dòng)態(tài)代理的兩種方式 兩種動(dòng)態(tài)代理的區(qū)別 JDK 的動(dòng)態(tài)代理是基于接口的代理。 CGLIB 是基于繼承的代理。 總結(jié) 補(bǔ)充 靜態(tài)代理和動(dòng)態(tài)代理的區(qū)別 動(dòng)態(tài)代理的用途 Spring AOP的實(shí)現(xiàn)方式 JDK 動(dòng)態(tài)代理代碼示例 Cglib動(dòng)態(tài)代理代碼示例 JDK動(dòng)態(tài)代理 :Java.lang.reflect 包中的Pr

    2024年02月03日
    瀏覽(35)
  • Java反射、代理機(jī)制

    官方解釋:反射允許對封裝類的字段、方法和構(gòu)造方法的信息進(jìn)行編程訪問。 虛擬機(jī)加載類文件后,會(huì)在方法區(qū)生成一個(gè)類對象,包含了類的結(jié)構(gòu)信息,如字段、方法、構(gòu)造方法等。反射是一種能夠在程序運(yùn)行時(shí)動(dòng)態(tài)訪問、修改類對象中任意屬性的機(jī)制(包括private屬性)。

    2024年02月10日
    瀏覽(17)
  • 反射機(jī)制-體會(huì)反射的動(dòng)態(tài)性案例(尚硅谷Java學(xué)習(xí)筆記)

    反射機(jī)制-體會(huì)反射的動(dòng)態(tài)性案例(尚硅谷Java學(xué)習(xí)筆記)

    // 舉例01 public class Reflect{ } 案例:榨汁機(jī)榨水果汁,水果分別有果(com.reflect.Apple)、香蕉(Banana)、桔子(Orange)等。 效果如圖。 提示: 1、聲明(Fruit)水果接口,包含榨汁抽象方法: void squeeze(); /skwi:z/ 2、聲明榨汁機(jī)(Juicer),包含運(yùn)行方法: public void run(Fruit f),方法體中,調(diào)用f的榨汁方

    2024年02月11日
    瀏覽(30)
  • java使用@interface和反射來動(dòng)態(tài)生成excel

    1、對象類上搞注解 public class ReportExecuteDetailDto { ? ? // 項(xiàng)目信息 ? ? private String regionCode; ?? ??? ?// 大區(qū)編號(hào) ? ? @ExcelColumn(order = 0, title = \\\"大區(qū)\\\") ? ? private String regionName; ?? ??? ?// 大區(qū)名稱 ?? ? ?? ?@ExcelColumn(order = 14, title = \\\"行申請金額\\\", dataType = ExcelColumn.FieldType.

    2024年02月11日
    瀏覽(25)
  • 【Java 基礎(chǔ)篇】Java 反射詳解

    Java反射是指在運(yùn)行時(shí)動(dòng)態(tài)地獲取類的信息,并可以通過該信息來操作類或?qū)ο蟆Mㄟ^反射,我們可以在運(yùn)行時(shí)獲取類的字段、方法、構(gòu)造函數(shù)等信息,并能夠動(dòng)態(tài)地創(chuàng)建對象、調(diào)用方法、訪問和修改字段的值。本文將詳細(xì)介紹Java反射的概念、原理和使用方法,并提供一些示

    2024年02月09日
    瀏覽(19)
  • Java基礎(chǔ)篇——反射&枚舉

    B友:https://www.bilibili.com/video/BV1QG4y1J76q/ VIP服務(wù)課程 :https://edu.51cto.com/course/32767.html 當(dāng)程序要使用某個(gè)類時(shí),如果該類還未被加載到內(nèi)存中,則系統(tǒng)會(huì)通過類的【加載】,【連接】,【初始化】 這三個(gè)步驟來對類進(jìn)行初始化。 如果不出現(xiàn)意外情況,JVM將會(huì)連續(xù)完成這三個(gè)步

    2024年02月12日
    瀏覽(18)
  • 【Java 基礎(chǔ)篇】Java反射:深入了解Class對象

    【Java 基礎(chǔ)篇】Java反射:深入了解Class對象

    Java是一門強(qiáng)類型語言,它要求在編譯時(shí)知道所有的類和對象類型。然而,有時(shí)候我們需要在運(yùn)行時(shí)動(dòng)態(tài)地獲取和操作類的信息,這就是Java反射的用武之地。本文將深入探討Java反射,特別是與Class對象相關(guān)的內(nèi)容。 反射是一種機(jī)制,允許我們在運(yùn)行時(shí)檢查、獲取和操作類的信

    2024年02月06日
    瀏覽(24)
  • Java語言----反射、枚舉以及l(fā)ambda表達(dá)式

    Java語言----反射、枚舉以及l(fā)ambda表達(dá)式

    目錄 一.反射 1.1反射的基本情況 1.2反射中最重要的類 1.2.1 Class類 1.2.2Field類 1.2.3Constructor類 1.2.4Method類 1.3反射優(yōu)缺點(diǎn)? 二.枚舉 2.1概念 2.2枚舉(enum)類方法 2.3枚舉的構(gòu)造 三.Lambda表達(dá)式 3.1Lambda介紹 3.2 函數(shù)式接口 3.3使用lambda表達(dá)式 3.2.1不使用Lambda表達(dá)式調(diào)用 3.2.2使用Lambda表

    2024年02月08日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包