1. 程式人生 > >【八】Java設計模式GOF23之動態代理(原生JDK和CGLIB)

【八】Java設計模式GOF23之動態代理(原生JDK和CGLIB)

一、使用JDK原生動態代理

基於Java反射機制。

Java動態代理是基於介面的,如果物件沒有實現介面則選擇用CGLIB方式實現動態代理。

實現步驟:

1.首先實現一個InvocationHandler,方法呼叫會被轉發到該類的invoke()方法。

2.然後在需要使用Star的時候,通過JDK動態代理獲取Star的代理物件。

目錄

Star.java

public interface Star {
	void confer();//談協議
	void signContract();//籤合同
	void bookTicket();//訂票
	void sing();//唱歌
	void collectMoney();//收尾款
}

RealStar.java

public class RealStar implements Star {

	@Override
	public void confer() {
		System.out.println("RealStar.confer()");

	}

	@Override
	public void signContract() {
		System.out.println("RealStar.signContract()");

	}

	@Override
	public void bookTicket() {
		System.out.println("RealStar.bookTicket()");
	}

	@Override
	public void sing() {
		System.out.println("RealStar().sing()");
	}

	@Override
	public void collectMoney() {
		System.out.println("RealStar.collectMoney()");
	}

}

StarHandler.java


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

//1.首先實現一個InvocationHandler,方法呼叫會被轉發到該類的invoke()方法。
public class StarHandler implements InvocationHandler{

	Star realStar;
	
	public StarHandler(Star realStar) {
		super();
		this.realStar = realStar;
	}

	//所有的流程控制都在這裡面處理
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object obj = null;
		System.out.println("前置方法");
		if(method.getName().equals("sing")){
			obj = method.invoke(realStar, args);
		}
		System.out.println("後續方法");
		return obj;
	}

}

Client.java

import java.lang.reflect.Proxy;


public class Client {
	public static void main(String[] args) {
        //2.然後在需要使用Star的時候,通過JDK動態代理獲取Star的代理物件。
        //newProxyInstance()會返回一個實現了指定介面的代理物件,對該物件的所有方法呼叫都會轉發給InvocationHandler.invoke()方法
		Star proxy = (Star) Proxy.newProxyInstance(
            ClassLoader.getSystemClassLoader(),//1. 類載入器
            new Class[]{Star.class},//2. 代理需要實現的介面,可以有多個
            new StarHandler(new RealStar())  // 3. 方法呼叫的實際處理者,代理物件的方法呼叫都會轉發到這裡
        );
		proxy.sing();
		proxy.bookTicket();
	}
}

二、使用CGLIB動態代理

基於ASM的位元組碼生成庫,它允許在執行時對位元組碼進行修改和動態生成。

CGLIB通過繼承方式實現代理。

CGLIB能代理所有非final的類、方法。

實現步驟

1.首先實現一個MethodInterceptor,方法呼叫會被轉發到該類的intercept()方法。

2.然後在需要使用Star的時候,通過CGLIB動態代理獲取代理物件。

package com.sid.util.proxy.cglib;

/**
 * @program: springboot
 * @description:
 * @author: Sid
 * @date: 2018-11-19 18:22
 * @since: 1.0
 **/
public class Star {

    public void confer() {
        System.out.println("Star.confer()");

    }

    public void signContract() {
        System.out.println("Star.signContract()");

    }

    public void bookTicket() {
        System.out.println("Star.bookTicket()");
    }

    public void sing() {
        System.out.println("Star().sing()");
    }

    public void collectMoney() {
        System.out.println("Star.collectMoney()");
    }
}
package com.sid.util.proxy.cglib;

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @program: springboot
 * @description:
 * @author: Sid
 * @date: 2018-11-19 18:24
 * @since: 1.0
 **/
// 1. 首先實現一個MethodInterceptor,方法呼叫會被轉發到該類的intercept()方法。
public class StarMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("StarMethodInterceptor do"+Arrays.toString(args) );
        //通過呼叫MethodProxy.invokeSuper()方法,將呼叫轉發給原始物件
        return methodProxy.invokeSuper(o, args);
    }
}

package com.sid.util.proxy.cglib;

import org.springframework.cglib.proxy.Enhancer;

/**
 * @program: springboot
 * @description:
 * @author: Sid
 * @date: 2018-11-19 18:27
 * @since: 1.0
 **/
public class Client {
    public static void main(String[] args) {
        // 2. 然後在需要使用Star的時候,通過CGLIB動態代理獲取代理物件。
        //通過CGLIB的Enhancer來指定要代理的目標物件
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Star.class);
        //指定實際處理代理邏輯的物件
        enhancer.setCallback(new StarMethodInterceptor());

        //通過呼叫create()方法得到代理物件
        //對這個物件所有非final方法的呼叫都會轉發給MethodInterceptor.intercept()方法
        Star star = (Star)enhancer.create();
        star.sing();
        star.confer();
    }
}

相關推薦

Java設計模式GOF23動態代理原生JDKCGLIB

一、使用JDK原生動態代理 基於Java反射機制。 Java動態代理是基於介面的,如果物件沒有實現介面則選擇用CGLIB方式實現動態代理。 實現步驟: 1.首先實現一個InvocationHandler,方法呼叫會被轉發到該類的invoke()方法。 2.然後在需要

Java設計模式GOF23介面卡模式類方式實現、物件方式實現

目錄 Target.java package com.bjsxt.adapter; /** * @author liyijie * @date 2016年8月12日下午4:13:21 *

Java設計模式Proxy動態代理

Java動態代理主要涉及到兩個類: InvocationHandler:該介面中僅定義了一個Object : invoke(Object proxy, Method method, Object[] args);引數proxy指代理類,method表示被代理的方法,args

Java設計模式代理模式

代理模式是Java常見的設計模式之一。所謂代理模式是指客戶端並不直接呼叫實際的物件,而是通過呼叫代理,來間接的呼叫實際的物件。 代理模式的定義: 為其他物件提供一種代理,以控制對這個物件的訪問; 為其他物件提供一種代理以控制對這個物件的訪問。代理物件起到中介作用,可去掉功能

設計模式學習動態代理模式

import java.lang.reflect.Method; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; class InvocationHandlerImpl implements I

自用java多執行緒程式設計學習筆記程式碼片段來源於網路

執行緒的基本概念 執行緒是在邏輯上等同於作業系統中說的程序,是程序的細分。比如我們使用同一個軟體同時對電腦進行體檢和防毒的時候,我們就是開啟了那個軟體的程序的兩個執行緒,在邏輯上這兩個執行緒是同時被cpu執行的。 執行緒的生命週期 執行緒的生命週期分為建立,就緒,執行,

javascriptjavascript設計模式單例模式

函數 設置 tin 私有 資源 公有 key fun 初始化 單例模式: 定義:單例模式之所以這麽叫,是因為它限制一個類只能有一個實例化對象。 實現方法:判斷實例是否存在,如果存在則直接返回,如果不存在就創建了再返回。(確保一個類只有一個實例對象) 特點: 命名空間提供者,

javascriptjavasrcipt設計模式策略模式

影響 配置 可能 pan style 類庫 ava 自由 AC 策略模式支持在運行時由使用者選擇合適的算法,對於使用者而言不用關心背後的具體事項,而使用者自動根據當前程序執行的上下文和配置,從已有的算法列表中選擇出合適的算法來處理當前任務。 1.要解決的問題 2.如何實現

本人禿頂程式設計師Java設計模式-介面卡模式

←←←←←←←←←←←← 快,點關注! 介面卡模式(Adapter Pattern):將一個介面轉換成呼叫者希望的另一個介面,使介面不相容的那些類可以一起工作,其別名為包裝類(Wrapper),該模式可以作為類結構型模式,也可以作為物件結構型模式 介面卡模式應該是 Android 開

Java設計模式工廠方法

定義: 抽象工廠模式提供一個建立一系列相關或者相互依賴物件的介面 無需指定它們具體的類 型別:建立型 抽象工

Java設計模式裝飾模式

情況 -s 抽象接口 output 就會 ati ack hba ensure 裝飾模式(Decorator) 1. 裝飾模式(Decorator)的定義:又名包裝(Wrapper)模式。裝飾模式以對client透明的方式擴展對象的功能,是繼承關系的一個替代方案。

java設計模式系列設計模式概要1

而不是 行為型模式 一句話 創建 rom 多次 ati 代理模式 之間 一、什麽是設計模式   設計模式(Design pattern)是一套被反復使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。

Java設計模式2七大設計模式

一.開閉原則 一個軟體實體如類,模組和函式應該對拓展開放,對修改關閉。 用抽象構建框架,用實現拓展細節。 優點:提高軟體系統的可複用性和可維護性。 為了滿足開閉原則,需要對系統進行抽象化設計,抽象化是開閉原則的關鍵。在Java、C#等程式語言中,可以為系統定義一

Java設計模式1UML

UML定義 統一建模語言 UML展現了一系列最佳工程實踐 這些最佳實踐在對大規模,複雜系統進行建模方面,特別是在軟體架構層次已經被證實有效。 UML分類 結構式圖形 行為式圖形 互動式圖形 結構式圖形 靜態圖(類圖,物件圖,包圖)

JAVA設計模式總結23種設計模式

ret 都對 松耦合 mem ava htm 初學者 並不是 不用 一、什麽是設計模式

JavaScript常用設計模式及程式設計技巧ES6描述

前言 平時的開發中可能不太需要用到設計模式,但是 JS 用上設計模式對於效能優化和專案工程化也是很有幫助的,下面就對常用的設計模式進行簡單的介紹與總結。 1. 單例模式 定義:保證一個類僅有一個例項,並提供一個訪問它的全域性訪問點。 class Singleton { constructor(

Java併發程式設計筆記CopyOnWriteArrayList原始碼分析

併發包中併發List只有CopyOnWriteArrayList這一個,CopyOnWriteArrayList是一個執行緒安全的ArrayList,對其進行修改操作和元素迭代操作都是在底層建立一個拷貝陣列(快照)上進行的,也就是寫時拷貝策略。 我們首先看一下CopyOnW

java 設計模式01簡單工廠抽象工廠模式

總結一下: 簡單工廠:工廠根據條件去建立對應的具體實現物件,如果需要增加新的物件,就必須修改建立物件的介面,增加判斷條件,另外可能建立的物件下面的方法也可能有其他物件去實現相同的功能,造成混亂,比如,amd可以造cpu,也可以造網絡卡,不能建立了一個amd造cpu的

java設計模式大話工廠方法模式

    由於簡單工廠模式中工廠類集中了所有例項的建立邏輯,違反了高內聚責任分配原則,將全部建立邏輯集中到了一個工廠類中;它所能建立的類只能是事先考慮到的,如果需要新增新的類,則就需要改變工廠類了。 當

JAVA設計模式初探裝飾者模式

這個模式花費了挺長時間,開始有點難理解,其實就是 定義:動態給一個物件新增一些額外的職責,就象在牆上刷油漆.使用Decorator模式相比用生成子類方式達到功能的擴充顯得更為靈活。設計初衷:通常可以使用繼承來實現功能的拓展,如果這些需要拓展的功能的種類很繁多,那麼勢必生成很