成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

深入探究動態代理:JDK 與 CGLIB 的實現奧秘與差異剖析

開發 前端
當目標對象有接口且注重開發便捷性、遵循接口編程規范時,JDK 動態代理是首選。例如在標準的企業級 Java 應用開發中,服務層接口常使用 JDK 代理實現日志記錄、權限驗證等 AOP 功能,與 Spring 等框架無縫集成。

在 Java 編程領域,動態代理是一種強大的設計模式,它允許開發者在運行時創建代理對象,對目標對象的行為進行增強、監控或修改,而無需在編譯期就確定代理的具體邏輯。這一特性在諸多框架中廣泛應用,如 Spring AOP(面向切面編程),為實現橫切面關注點的模塊化提供了關鍵支撐。

一、JDK 動態代理實現原理

JDK 動態代理依托于 Java 反射機制構建,核心涉及  java.lang.reflect  包下的幾個重要類。

首先,需要定義一個接口,該接口代表目標對象與代理對象共同遵循的行為規范。假設我們有一個簡單的圖形繪制接口  Shape :

public interface Shape {
    void draw();
}
接著是目標類實現此接口,例如  Circle  類:
public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }
}

創建代理對象的關鍵在于實現  java.lang.reflect.InvocationHandler  接口,它定義了一個  invoke  方法,用于處理代理對象上所有方法的調用邏輯:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ShapeInvocationHandler implements InvocationHandler {
    private final Object target;
    public ShapeInvocationHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在目標方法調用前添加額外邏輯,如日志記錄
        System.out.println("Before method invocation");
        Object result = method.invoke(target, args);
        // 在目標方法調用后添加額外邏輯,如性能統計
        System.out.println("After method invocation");
        return result;
    }
}

最后,通過  java.lang.reflect.Proxy  類生成代理對象:

import java.lang.reflect.Proxy;
public class Main {
    public static void main(String[] args) {
        Shape circle = new Circle();
        ShapeInvocationHandler handler = new ShapeInvocationHandler(circle);
        Shape proxyShape = (Shape) Proxy.newProxyInstance(
                Shape.class.getClassLoader(),
                new Class[]{Shape.class},
                handler);
        proxyShape.draw();
    }
}

在上述代碼中,當調用代理對象  proxyShape  的  draw  方法時,實際上控制權轉移到  ShapeInvocationHandler  的  invoke  方法,在此可以靈活插入前置、后置邏輯,實現對目標對象方法的動態增強。

二、CGLIB 動態代理實現原理

CGLIB(Code Generation Library)動態代理采取了截然不同的字節碼生成策略。它不依賴接口,而是直接對目標類進行字節碼擴展。

引入 CGLIB 相關依賴后,以同樣的  Circle  類為例(此時無需實現接口):

public class Circle {
    public void draw() {
        System.out.println("Drawing a circle");
    }
}

創建一個實現  net.sf.cglib.proxy.MethodInterceptor  接口的攔截器類,它類似于 JDK 代理中的  InvocationHandler :

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibShapeInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("CGLIB: Before method call");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("CGLIB: After method call");
        return result;
    }
}

利用  net.sf.cglib.proxy.Enhancer  類生成代理對象:

import net.sf.cglib.proxy.Enhancer;
public class Main {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Circle.class);
        enhancer.setCallback(new CglibShapeInterceptor());
        Circle proxyCircle = (Circle) enhancer.create();
        proxyCircle.draw();
    }
}

這里, Enhancer  通過修改目標類的字節碼,在原始方法執行前后織入自定義邏輯,生成的代理對象繼承自目標類,能直接調用目標類非  private  的方法,無需像 JDK 代理那樣依賴接口。

三、JDK 動態代理與 CGLIB 動態代理的區別

(一)實現基礎

- JDK 動態代理:基于接口實現,要求目標對象必須實現至少一個接口。它利用 Java 反射在運行時動態生成代理類,該代理類同樣實現目標對象的接口,通過接口回調機制將方法調用轉發至  InvocationHandler  處理。

- CGLIB 動態代理:基于繼承機制,直接操作目標類的字節碼,生成目標類的子類作為代理對象。它通過重寫子類方法,在其中插入攔截邏輯,調用父類(即目標類)原始方法實現功能,無需目標對象有接口實現。

(二)性能表現

- 在創建代理對象階段,JDK 動態代理相對較快,因為它只需基于接口信息利用反射生成簡單代理類結構;而 CGLIB 需要通過復雜的字節碼生成技術創建子類,耗時較長。

- 但在方法調用時,JDK 動態代理由于每次都要經過反射查找方法等操作,性能開銷較大;CGLIB 代理對象調用方法類似普通對象調用,因為方法已在字節碼層面重寫優化,若頻繁調用代理方法,CGLIB 在性能上更具優勢。

(三)適用場景

- 當目標對象有接口且注重開發便捷性、遵循接口編程規范時,JDK 動態代理是首選。例如在標準的企業級 Java 應用開發中,服務層接口常使用 JDK 代理實現日志記錄、權限驗證等 AOP 功能,與 Spring 等框架無縫集成。

- 若目標對象沒有接口,或者需要對 final 修飾的類進行代理(JDK 代理無法做到,因 final 類不可繼承),CGLIB 動態代理便能大顯身手。像一些遺留代碼改造、底層工具類增強場景,CGLIB 可突破接口限制,靈活實現代理需求。

JDK 動態代理與 CGLIB 動態代理各具特色,它們從不同角度為 Java 開發者提供了動態代理的實現路徑,深入理解二者原理與區別,有助于在面對復雜多變的編程需求時,精準選擇合適的代理方式,打造高效、健壯的 Java 應用。

責任編輯:武曉燕 來源: 程序員conan
相關推薦

2024-01-04 07:42:44

JavaCGLIBJDK

2023-12-06 08:23:44

代理模式設計模式

2021-04-22 09:58:15

JDK代理動態

2022-09-01 10:40:29

SpringAOPJDK

2024-03-07 08:22:51

Java機制元數據

2021-07-14 11:07:56

AOPJDKCglib

2023-09-28 09:03:56

開源搜索分析引擎

2024-01-26 08:33:14

JDK17JDK11版本

2024-09-05 09:35:58

CGLIBSpring動態代理

2010-09-01 09:29:51

CSS層疊CSS繼承

2010-08-16 10:25:23

DIVSPAN

2012-09-28 10:20:14

IBMdw

2012-09-27 09:47:43

SpringJava面向對象

2020-10-25 17:11:29

JDK代理監控

2013-05-07 11:43:47

2023-06-07 07:43:57

數據庫JOIN類型

2024-01-31 23:47:17

i++++i編碼

2022-11-15 09:57:51

Java接口

2010-09-30 09:16:04

cookieJ2ME

2011-11-24 21:03:10

ibmdw
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国精产品一品二品国精在线观看 | 国产精品久久久久久久久污网站 | 色爽女| 久久精品视频播放 | 日韩成人免费视频 | 欧美九九九 | 久久国产一区 | 一级一级毛片免费看 | 亚洲成人免费观看 | 天天操妹子 | 国产精品久久久 | 天天色综 | 国产精品一区二区三区久久 | 国产福利资源在线 | 亚州午夜精品 | 国产高清视频在线 | 国产999精品久久久久久绿帽 | 欧美成人精品一区二区男人看 | 久久久美女 | 国产中文 | av免费看片 | 精品九九久久 | 国产成人a亚洲精品 | 国产日韩欧美 | 成人精品一区 | 国产人成精品一区二区三 | 国产精品视频久久久 | 久久香焦| 成人日批视频 | 亚洲国产成人精品久久久国产成人一区 | 国产精品一二三区 | 欧美涩 | 成人在线视频一区二区三区 | 久草网址| 欧洲一区二区三区 | www..99re| 国产剧情久久 | 国产精品视频在 | 精品国产一区二区三区久久久蜜月 | 国产视频1区 | 夜夜操天天操 |