最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java JDK動(dòng)態(tài)代理在攔截器和聲明式接口中的應(yīng)用小結(jié)

 更新時(shí)間:2025年01月21日 11:31:58   作者:碼到三十五  
Java動(dòng)態(tài)代理技術(shù)通過(guò)反射機(jī)制在運(yùn)行時(shí)動(dòng)態(tài)生成代理類,實(shí)現(xiàn)對(duì)目標(biāo)對(duì)象方法的攔截和增強(qiáng),本文給大家介紹Java JDK動(dòng)態(tài)代理在攔截器和聲明式接口中的應(yīng)用小結(jié),感興趣的朋友跟隨小編一起看看吧

一、動(dòng)態(tài)代理概念回顧

Java動(dòng)態(tài)代理技術(shù)是基于反射機(jī)制的基礎(chǔ)。核心在于利用反射機(jī)制和接口編程在運(yùn)行時(shí)動(dòng)態(tài)生成代理類,并通過(guò)InvocationHandler接口實(shí)現(xiàn)代理邏輯的靈活擴(kuò)展。通過(guò)動(dòng)態(tài)代理,Java程序可以在運(yùn)行時(shí)動(dòng)態(tài)地生成代理類,并控制對(duì)目標(biāo)對(duì)象的訪問(wèn),從而實(shí)現(xiàn)對(duì)目標(biāo)對(duì)象方法的攔截和增強(qiáng)。
其優(yōu)勢(shì)在于靈活性、可擴(kuò)展性、解耦、AOP支持和遠(yuǎn)程方法調(diào)用等方面.

Java動(dòng)態(tài)代理原理主要基于Java的反射機(jī)制,通過(guò)動(dòng)態(tài)地生成代理類來(lái)實(shí)現(xiàn)對(duì)接口的動(dòng)態(tài)代理。

二、 核心組件

  • java.lang.reflect.Proxy 類:這是Java動(dòng)態(tài)代理的核心類,提供了創(chuàng)建動(dòng)態(tài)代理實(shí)例的靜態(tài)方法。
  • java.lang.reflect.InvocationHandler:該接口定義了一個(gè)方法 invoke(Object proxy, Method method, Object[] args),代理實(shí)例在調(diào)用接口方法時(shí),會(huì)調(diào)用此方法。

三、工作流程

  • 定義業(yè)務(wù)接口:首先,需要定義一個(gè)或多個(gè)業(yè)務(wù)接口,這些接口將被動(dòng)態(tài)代理。
  • 實(shí)現(xiàn)InvocationHandler接口:創(chuàng)建一個(gè)實(shí)現(xiàn)了InvocationHandler接口的類,在該類的invoke方法中編寫代理邏輯。invoke方法會(huì)在代理對(duì)象調(diào)用接口方法時(shí)被自動(dòng)調(diào)用。
  • 生成代理實(shí)例:通過(guò)Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法生成代理實(shí)例。這個(gè)方法接收三個(gè)參數(shù):
    • ClassLoader loader:類加載器,用于加載代理類。
    • Class<?>[] interfaces:一個(gè)接口數(shù)組,代理類將實(shí)現(xiàn)這些接口。
    • InvocationHandler h:當(dāng)代理對(duì)象的方法被調(diào)用時(shí),會(huì)調(diào)用此處理器的invoke方法。
  • 調(diào)用代理實(shí)例的方法:當(dāng)調(diào)用代理實(shí)例的方法時(shí),實(shí)際上會(huì)調(diào)用InvocationHandlerinvoke方法,然后可以在invoke方法中執(zhí)行自定義邏輯,并調(diào)用實(shí)際接口實(shí)現(xiàn)的方法。
  • 動(dòng)態(tài)生成字節(jié)碼Proxy.newProxyInstance 方法內(nèi)部會(huì)動(dòng)態(tài)生成一個(gè)實(shí)現(xiàn)了指定接口的代理類字節(jié)碼。這個(gè)代理類會(huì)重寫接口中的所有方法,并在方法內(nèi)部調(diào)用InvocationHandlerinvoke方法。JDK生成的代理類名稱通常為com.sun.proxy.$ProxyN,其中N是一個(gè)遞增的數(shù)字,表示這是第幾個(gè)動(dòng)態(tài)生成的代理類。

四、動(dòng)態(tài)代理的應(yīng)用場(chǎng)景

動(dòng)態(tài)代理的兩個(gè)最常用見(jiàn)應(yīng)用場(chǎng)景為 攔截器聲明性接口

4.1 搭載器(AOP)

搭載器就是將目標(biāo)組件劫持,在執(zhí)行目標(biāo)組件代碼的前后,塞入一些其它代碼。比如在正式執(zhí)行業(yè)務(wù)方法前,先進(jìn)行權(quán)限校驗(yàn),如果校驗(yàn)不通過(guò),則拒絕繼續(xù)執(zhí)行。對(duì)于此類操作,業(yè)界已經(jīng)抽象出一組通用的編程模型:面向切面編程AOP。

接口定義和實(shí)現(xiàn)

public interface Performer {
    void play(String subject);
    String introduction();
}
public interface Director {
    List<String> getCreations();
}
public class DefaultActor implements Performer {
    @Override
    public void play(String subject) {
        System.out.println("[DefaultActor]: 默認(rèn)男演員正在即興表演《" + subject + "》");
    }
    @Override
    public String introduction() {
        return "李白·上李邕: 大鵬一日同風(fēng)起,扶搖直上九萬(wàn)里。假令風(fēng)歇時(shí)下來(lái),猶能顛卻滄溟水。世人見(jiàn)我恒殊調(diào),聞?dòng)啻笱越岳湫ΑP干心芪泛笊?,丈夫未可輕年少。";
    }
}
public class DefaultDirector implements Director {
    @Override
    public List<String> getCreations() {
        List<String> creations = new ArrayList<>();
        creations.add("《霸王別姬》");
        creations.add("《活著》");
        return creations;
    }
}

攔截器核心類

攔截器核心類實(shí)現(xiàn)了InvocationHandler接口,并在invoke方法中插入攔截邏輯。

package guzb.diy.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyForInterceptor implements InvocationHandler {
    private Object target;
    public ProxyForInterceptor(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前置攔截邏輯:開始執(zhí)行 " + method.getName() + " 方法");
        Object result = method.invoke(target, args);
        System.out.println("后置攔截邏輯:完成執(zhí)行 " + method.getName() + " 方法");
        return result;
    }
}

測(cè)試

public class IntercepterTestMain {
    public static void main(String[] args) {
        // 創(chuàng)建原始對(duì)象
        Performer actor = new DefaultActor();
        Director director = new DefaultDirector();
        // 創(chuàng)建代理對(duì)象
        Performer actorProxy = (Performer) Proxy.newProxyInstance(
                Performer.class.getClassLoader(),
                new Class[]{Performer.class},
                new ProxyForInterceptor(actor)
        );
        Director directorProxy = (Director) Proxy.newProxyInstance(
                Director.class.getClassLoader(),
                new Class[]{Director.class},
                new ProxyForInterceptor(director)
        );
        // 通過(guò)代理對(duì)象調(diào)用方法
        actorProxy.play("京劇");
        System.out.println(actorProxy.introduction());
        System.out.println("導(dǎo)演的作品集:");
        directorProxy.getCreations().forEach(System.out::println);
    }
}

4.2 聲明是接口

MyBatis中,聲明式接口(通過(guò)注解@Select、@Insert等)允許直接在接口方法上通過(guò)注解來(lái)定義SQL語(yǔ)句,而不需要編寫具體的SQL實(shí)現(xiàn)類。這種方式使得代碼更加簡(jiǎn)潔,易于維護(hù)。

使用JDK動(dòng)態(tài)代理來(lái)模擬MyBatis中的聲明式接口。

定義業(yè)務(wù)接口

先定義一個(gè)業(yè)務(wù)接口,里面包含使用注解定義的SQL操作。

public interface UserMapper {
    @Select("SELECT * FROM user WHERE name = #{name}")
    User findUserByName(String name);
}
// User的POJO類
class User {
    private Integer id;
    private String name;
    // getters and setters
}

這里的@Select注解是自定義的,很簡(jiǎn)單就不展示了。

編寫InvocationHandler
寫一個(gè)InvocationHandler,它會(huì)在運(yùn)行時(shí)解析@Select這些注解,并執(zhí)行相應(yīng)的SQL操作。簡(jiǎn)化版只模擬解析和調(diào)用的過(guò)程。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyBatisInvocationHandler implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 這里假設(shè)能夠獲取到注解并解析它
        // 實(shí)際上,你需要一個(gè)SQL執(zhí)行器來(lái)執(zhí)行這里定義的SQL
        System.out.println("Executing method: " + method.getName());
        System.out.println("Parameters: " + Arrays.toString(args));
        // 模擬的SQL執(zhí)行結(jié)果
        User user = new User();
        user.setId(1);
        user.setName((String) args[0]);
        return user;
    }
}

生成代理對(duì)象并調(diào)用

最后,我們生成UserMapper接口的代理對(duì)象,并調(diào)用它的方法。

import java.lang.reflect.Proxy;
public class MyBatisProxyDemo {
    public static void main(String[] args) {
        MyBatisInvocationHandler handler = new MyBatisInvocationHandler();
        UserMapper mapper = (UserMapper) Proxy.newProxyInstance(
            UserMapper.class.getClassLoader(),
            new Class[]{UserMapper.class},
            handler
        );
        User user = mapper.findUserByName("Alice");
        System.out.println("Found user: " + user.getName());
    }
}

輸出結(jié)果

Executing method: findUserByName
Parameters: [Alice]
Found user: Alice

到此這篇關(guān)于Java JDK動(dòng)態(tài)代理在攔截器和聲明式接口中的應(yīng)用小結(jié)的文章就介紹到這了,更多相關(guān)JDK動(dòng)態(tài)代理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java HTTP協(xié)議收發(fā)MQ 消息代碼實(shí)例詳解

    Java HTTP協(xié)議收發(fā)MQ 消息代碼實(shí)例詳解

    這篇文章主要通過(guò)實(shí)例代碼為大家詳細(xì)介紹了如何在Java 環(huán)境下使用 HTTP 協(xié)議收發(fā) MQ 消息,需要的朋友可以參考下
    2017-04-04
  • Spring Boot 表單驗(yàn)證篇

    Spring Boot 表單驗(yàn)證篇

    在表單提交的時(shí)候,我們需要進(jìn)行驗(yàn)證。下面通過(guò)本篇文章給大家介紹Spring Boot 表單驗(yàn)證篇,需要的朋友可以參考下
    2017-08-08
  • Json在Struts中的轉(zhuǎn)換與傳遞方法

    Json在Struts中的轉(zhuǎn)換與傳遞方法

    下面小編就為大家?guī)?lái)一篇Json在Struts中的轉(zhuǎn)換與傳遞方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-11-11
  • Java使用ScriptEngine動(dòng)態(tài)執(zhí)行代碼(附Java幾種動(dòng)態(tài)執(zhí)行代碼比較)

    Java使用ScriptEngine動(dòng)態(tài)執(zhí)行代碼(附Java幾種動(dòng)態(tài)執(zhí)行代碼比較)

    這篇文章主要介紹了Java使用ScriptEngine動(dòng)態(tài)執(zhí)行代碼,并且分享Java幾種動(dòng)態(tài)執(zhí)行代碼比較,需要的朋友可以參考下
    2021-04-04
  • springboot自動(dòng)重啟的簡(jiǎn)單方法

    springboot自動(dòng)重啟的簡(jiǎn)單方法

    Springboot提供了熱部署的方式,當(dāng)發(fā)現(xiàn)任何類發(fā)生了改變,馬上通過(guò)JVM類加載的方式,加載最新的類到虛擬機(jī)中。這篇文章主要介紹了springboot自動(dòng)重啟的實(shí)現(xiàn)方法,需要的朋友可以參考下
    2018-04-04
  • SpringBoot加載profile全面解析

    SpringBoot加載profile全面解析

    SpringBoot的Profile機(jī)制通過(guò)多配置文件和注解實(shí)現(xiàn)環(huán)境隔離,支持開發(fā)、測(cè)試、生產(chǎn)等不同環(huán)境的靈活配置切換,無(wú)需修改代碼,關(guān)鍵點(diǎn)包括配置文件命名規(guī)范、激活方式、優(yōu)先級(jí)及企業(yè)級(jí)安全部署實(shí)踐,本文介紹SpringBoot加載profile的過(guò)程,感興趣的朋友一起看看吧
    2025-08-08
  • SpringBoot框架集成ElasticSearch實(shí)現(xiàn)過(guò)程示例詳解

    SpringBoot框架集成ElasticSearch實(shí)現(xiàn)過(guò)程示例詳解

    這篇文章主要為大家介紹了SpringBoot如何集成ElasticSearch的實(shí)現(xiàn)過(guò)程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-11-11
  • java二分查找插入法

    java二分查找插入法

    當(dāng)你需要構(gòu)建一個(gè)大的有序隊(duì)列,用插入發(fā)太慢了,可以先用二分查找法,找到在隊(duì)列要插入的位置,把數(shù)后移一下,然后放進(jìn)去。比較效率,下面是java使用示例,需要的朋友可以參考下
    2014-03-03
  • Java Web基于Session的登錄實(shí)現(xiàn)方法

    Java Web基于Session的登錄實(shí)現(xiàn)方法

    這篇文章主要介紹了Java Web基于Session的登錄實(shí)現(xiàn)方法,涉及Java針對(duì)session的操作及表單提交與驗(yàn)證技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-10-10
  • Spring中@ConditionalOnProperty注解的作用詳解

    Spring中@ConditionalOnProperty注解的作用詳解

    這篇文章主要介紹了Spring中@ConditionalOnProperty注解的作用詳解,@ConditionalOnProperty注解主要是用來(lái)判斷配置文件中的內(nèi)容來(lái)決定配置類是否生效用的,如果條件不匹配,則配置類不生效,需要的朋友可以參考下
    2024-01-01

最新評(píng)論

五指山市| 灵璧县| 延长县| 深州市| 廉江市| 宿迁市| 城市| 商都县| 海南省| 五原县| 贺州市| 陆丰市| 黄陵县| 阿勒泰市| 广丰县| 新干县| 阆中市| 怀柔区| 建德市| 广丰县| 大连市| 祁门县| 扶绥县| 饶平县| 嘉兴市| 绥滨县| 新安县| 金山区| 甘南县| 馆陶县| 图木舒克市| 封开县| 福清市| 铁岭市| 新闻| 汶川县| 邵武市| 建水县| 确山县| 永昌县| 沙坪坝区|