1. 程式人生 > >Jdk 動態代理(一個實際案例使用)

Jdk 動態代理(一個實際案例使用)

Jdk 動態代理:利用java的反射,允許執行時動態地建立一個代理類,實現一個或多個介面,將方法的呼叫轉發到你所指定的類。

問題場景:

有一個Person類,其中屬性欄位有:姓名name、性別gender、興趣interests、評分值hotOrNotRating,要求:get方法所有欄位,對於所有該類例項擁有者或者非該類例項擁有者都有效,而該類例項擁有者除了不能給自己評分之外,可以修改所有的其他欄位,而非該類例項擁有者只能設定該評分值,而不能修改其他所有的欄位。

利用Java動態代理實現程式碼如下:

PersonBean.java 類如下:

public interface PersonBean {

    String getName(); // 取得人的名字
    String getGender(); // 性別
    String getInterests(); // 興趣
    int getHotOrNotRating(); // HotOrNot評分(1到10)

    void setName(String name);
    void setGender(String name);
    void setInterests(String interests);
    void setHotOrNotRating(int rating);
}

PersonBeanImpl.java 類如下:

public class PersonBeanImpl implements PersonBean {
    String name;
    String gender;
    String interests;
    int rating; //當前的評價分數
    int ratingCount = 0; // 當前的評價數

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getGender() {
        return gender;
    }

    @Override
    public String getInterests() {
        return interests;
    }

    @Override
    public int getHotOrNotRating() {
        if (ratingCount == 0) return 0;
        return (rating/ratingCount);
    }

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

    @Override
    public void setGender(String name) {
        this.gender = gender;
    }

    @Override
    public void setInterests(String interests) {
        this.interests = interests;
    }

    @Override
    public void setHotOrNotRating(int rating) {
        this.rating += rating;
        ratingCount++;
    }
}

擁有者使用類的情況:

OwnerInvocationHandler.java 類如下:

**
 *  擁有者使用類的情況
 */
public class OwnerInvocationHandler implements InvocationHandler {

    PersonBean person;

    public OwnerInvocationHandler(PersonBean person){
        this.person = person;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException {

        try {
            if (method.getName().startsWith("get")){
                return method.invoke(person, args);
            } else if (method.getName().equals("setHotOrNotRating")) {
                throw new IllegalAccessException();
            } else if (method.getName().startsWith("set")) {
                return method.invoke(person, args);
            }
        } catch (InvocationTargetException e) { // 真正主題丟擲異常
            e.printStackTrace();
        }
        return null; // 如果呼叫其他的方法,一律不理,返回null
    }
}

非擁有者使用類如下:

NonOwnerInvocationHandler.java 類如下:

public class NonOwnerInvocationHandler implements InvocationHandler {

    PersonBean person;

    public NonOwnerInvocationHandler(PersonBean person) {
        this.person = person;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException {
        try {
            if (method.getName().startsWith("get")){
                return method.invoke(person, args);
            } else if (method.getName().equals("setHotOrNotRating")) {
                return method.invoke(person, args);
            } else if (method.getName().startsWith("set")) {
                throw  new IllegalAccessException();
            }
        } catch (InvocationTargetException e) { // 真正主題丟擲異常
            e.printStackTrace();
        }
        return null; // 如果呼叫其他的方法,一律不理,返回null
    }
}

測試類如下:

MatchMakikngTestDrive.java 類:

public class MatchMakingTestDrive {

    public static void main(String[] args) {
        MatchMakingTestDrive test = new MatchMakingTestDrive();
        test.drive();
    }

    public void drive() {
        PersonBean joe = new PersonBeanImpl();
        joe.setName("tim"); joe.setGender("girl"); joe.setInterests("watch movies"); joe.setHotOrNotRating(0);
        PersonBean ownerProxy = getOwnerProxy(joe);
        System.out.println("Name is: " + ownerProxy.getName());
        ownerProxy.setInterests("bowling, Go");
        System.out.println("Interests set from owner proxy");
        try {
            ownerProxy.setHotOrNotRating(10);
        } catch (Exception e) {
            System.out.println("Can't set rating from owner proxy");
        }
        System.out.println("Rating is " + ownerProxy.getHotOrNotRating());

        PersonBean nonOwnerProxy = getNonOwnerProxy(joe);
        System.out.println("Name is: " + nonOwnerProxy.getName());
        try {
            nonOwnerProxy.setInterests("bowling, go");
        } catch (Exception e) {
            System.out.println("Can't set interests from non owner proxy");
        }
        nonOwnerProxy.setHotOrNotRating(3);
        System.out.println("Rating set from non owner proxy");
        System.out.println("Rating is " + nonOwnerProxy.getHotOrNotRating());

    }

    PersonBean getOwnerProxy(PersonBean person) {
        return (PersonBean) Proxy.newProxyInstance(person.getClass().getClassLoader(),
                person.getClass().getInterfaces(),
                new OwnerInvocationHandler(person));
    }

    PersonBean getNonOwnerProxy(PersonBean person) {
        return (PersonBean) Proxy.newProxyInstance(person.getClass().getClassLoader(),
                person.getClass().getInterfaces(),
                new NonOwnerInvocationHandler(person));
    }
}

輸出:

Name is: tim

Interests setfrom owner proxy

Can't setrating from owner proxy

Rating is 0

Name is: tim

Can't setinterests from non owner proxy

Rating setfrom non owner proxy

Rating is 1

分析:

需要實現InvocationHandler介面,然後會自動覆蓋如下方法:

public Object invoke(Object proxy,Method method, Object[] args) throws IllegalAccessException

在實現類中需要傳入需要代理的類欄位

在invoke方法中進行呼叫。

返回該類的例項:

return (PersonBean) Proxy.newProxyInstance(person.getClass().getClassLoader(),
               person.getClass().getInterfaces(),
                new OwnerInvocationHandler(person));








相關推薦

Jdk 動態代理一個實際案例使用

Jdk 動態代理:利用java的反射,允許執行時動態地建立一個代理類,實現一個或多個介面,將方法的呼叫轉發到你所指定的類。 問題場景: 有一個Person類,其中屬性欄位有:姓名name、性別gender、興趣interests、評分值hotOrNotRating,要求:

jdk動態代理底層動態生成代理類和編譯過程

     Java動態代理,顧名思義,動態的生成代理物件。其實難點就在這裡—動態。到底怎麼動態生成。代理解決的問題就是增強類。其實,實現代理的方式很多種,比如繼承,子類對一個類增強,我們可以認為子類就是一個代理類,在比如組合,組合簡單理解就是在類中注入要增強類的物件。組合和繼

JDK動態代理3WeakCache快取的實現機制

上一篇我們分析了Proxy類的內部是怎樣產生代理類的,我們看到了Proxy內部用到了快取機制,如果根據提供的類載入器和介面陣列能在快取中找到代理類就直接返回該代理類,否則會呼叫ProxyClassFactory工廠去生成代理類。這裡用到的快取是二級快取,它的一級

JDK動態代理4ProxyGenerator生成代理類的位元組碼檔案解析

通過前面幾篇的分析,我們知道代理類是通過Proxy類的ProxyClassFactory工廠生成的,這個工廠類會去呼叫ProxyGenerator類的generateProxyClass()方法來生成代理類的位元組碼。ProxyGenerator這個類存放在su

JDK動態代理2JDK動態代理的底層實現之Proxy原始碼分析

JDK動態代理(2)JDK動態代理的底層實現之Proxy原始碼分析 在上一篇裡為大家簡單介紹了什麼是代理模式?為什麼要使用代理模式?並用例子演示了一下靜態代理和動態代理的實現,分析了靜態代理和動態代理各自的優缺點。在這一篇中筆者打算深入原始碼為大家剖析JDK動態代理實現的機制,建議讀者閱

用 HPjtune 分析 GC 日誌一個實際案例的診斷過程

上次介紹了IBM的兩款分析gc log的工具(GCMV和PMAT),這次講講HP推出的HPjmeter。HPjmeter集成了以前的HPjtune功能,可以分析在HP機器上產生的垃圾回收日誌檔案。你可以到Hewlett-Packard Java website免費下載最新的4

JDK動態代理深入理解分析並手寫簡易JDK動態代理

上篇分析的是JDK動態代理實現原理,這個下篇是一個自實現的動態代理案例,這一篇我們自定義代理Proxy,代理業務需要實現的Handler介面,以及類載入器ClassLoader;最終我們以自己寫的程式碼去生成代理類的程式碼,再用代理類的程式碼去代理執行我們的業務程式碼,完成一套標準的動態代理; 首先我們分析

JDK動態代理深入理解分析並手寫簡易JDK動態代理

部落格真的是好幾個月沒更了,2019新年第一篇,繼續深入動態代理,前兩篇簡單分析了動態代理的實現原理之後,這次繼續深入瞭解具體的實現方式,並手寫一套簡易的動態代理已加強理解; 先接上一篇程式碼,這裡先上程式碼說話,一個簡單案列,代理找物件和找工作: JDK動態代理只能代理有介面的類,定義Persion介面

JDK動態代理JDK dynamic proxy

import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * JDK動態代理。 * @author Bright Le

Java JDK 動態代理AOP使用及實現原理分析

/** * A factory function that generates, defines and returns the proxy class given * the ClassLoader and array of interfaces. */ privat

Java-JDK動態代理AOP使用及實現原理分析

# Java-JDK動態代理(AOP)使用及實現原理分析 # 第一章:代理的介紹 介紹:我們需要掌握的程度 > 動態代理(理解) 基於反射機制 掌握的程度: 1.什麼是動態代理? 2.動態代理能夠做什麼? 後面我們在用Spirng和Mybatis的時候,要理解怎麼使用的. ## 1.什麼是代理

Dom4j封裝解析xml資料個人實際案例

public static void main(String[] args) throws DocumentException {         //Document document = DocumentHelper.parseTe

基於介面的 InvocationHandler 動態代理換種寫法

InvocationHandler is the interface implemented by the invocation handler of a proxy instance. Each proxy instance has an associated invocation handler. Wh

基於繼承的 MethodInterceptor 動態代理換種寫法

net. sf. cglib. proxy.Enhancer   Generates dynamic subclasses to enable method interception. This class started as a substitute for the standa

JDK動態代理一個最簡單的例項

JDK動態代理大家都知道的有spring aop,它的實現就是基於JDK的動態代理,它只能對實現了介面的類實現代理,在程式執行過程中,根據代理的介面來動態生成代理類,如果要使用類的代理,就得使用cglib,我們另一篇文章進行說明。下面直接看一個最簡單的例項程式碼 1:定義一

Linux共享庫的動態載入附測試案例

共享庫的動態載入是指可以在程式執行的過程中去載入所需的共享庫。常用於某些系統或者應用程式的自動升級。 在C語言的源程式動態載入共享庫,需要呼叫一組特殊的函式,它們被聲明於一個專門的標頭檔案dlfcn.h,並在一個獨立的庫中予以實現。使用這組函式需要包含此標頭檔

netcore 之動態代理微服務專題

動態代理配合rpc技術呼叫遠端服務,不用關注細節的實現,讓程式就像在本地呼叫以用。 因此動態代理在微服務系統中是不可或缺的一個技術。網上看到大部分案例都是通過反射自己實現,且相當複雜。編寫和除錯相當不易,我這裡提供裡一種簡便的方式來實現動態代理。 1、建立我們的空白.netcore專案  通過

模式的秘密-代理模式2-JDK動態代理

handler ins strong alt mov .... implement class 以及 代理模式-動態代理 (1) (2) 代碼實踐動態代理: 第一步:被代理類的接口: package com.JdkProxy; public interface

AOP的基礎知識總結jdk動態代理/cglib動態代理

AOP的基礎知識總結(jdk動態代理/cglib動態代理) 知識總結 aop切面程式設計 切面: 切面包含了通知和切點,通知和切點共同定義了切面是什麼,在何時,何處執行切面邏輯。 切點: 如果說通知定義了在何時執行通知,那麼切點就定義了在何處執行通知。所

【資料運營】在運營中,為什麼文字分析遠比數值型分析重要?一個實際案例,五點分析

https://www.pmcaff.com/article/index/408451832537216?from=profile 本文是《資料分析中,文字分析遠比數值型分析重要!》的下篇,以一個實際案例來聊聊文字分析在實際運營中如何落地。行為脈絡如下:先簡要講述文字分析的分支---情緒分析的基本原