-
當前位置:首頁 > 創(chuàng)意學院 > 技術 > 專題列表 > 正文
java獲取接口的所有實現(xiàn)類(java 獲取接口實現(xiàn)類)
大家好!今天讓創(chuàng)意嶺的小編來大家介紹下關于java獲取接口的所有實現(xiàn)類的問題,以下是小編對此問題的歸納整理,讓我們一起來看看吧。
開始之前先推薦一個非常厲害的Ai人工智能工具,一鍵生成原創(chuàng)文章、方案、文案、工作計劃、工作報告、論文、代碼、作文、做題和對話答疑等等
只需要輸入關鍵詞,就能返回你想要的內(nèi)容,越精準,寫出的就越詳細,有微信小程序端、在線網(wǎng)頁版、PC客戶端
官網(wǎng):https://ai.de1919.com
本文目錄:
一、關于java this.getClass();
Java的每個類都帶有一個運行時類對象,該Class對象中保存了創(chuàng)建對象所需的所有信息。
可以用.class返回此 Object 的運行時類Class對象,也可以用getClass()獲得。
獲得此對象后可以利用此Class對象的一些反射特性進行操作,
例如:
this.getClass().newInstance(); //用缺省構造函數(shù)創(chuàng)建一個該類的對象
this.getClass().getInterfaces(); //獲得此類實現(xiàn)的接口信息
this.getClass().getMethods();//獲得此類實現(xiàn)的所有公有方法
Class.forName(" ... JDBC driver class name...."); // Class類的靜態(tài)方法forName, 向DiverManager注冊這個JDBC driver類
二、Mybatis Mapper接口是如何找到實現(xiàn)類的-源碼分析
KeyWords: Mybatis 原理,源碼,Mybatis Mapper 接口實現(xiàn)類,代理模式,動態(tài)代理,Java動態(tài)代理,Proxy.newProxyInstance,Mapper 映射,Mapper 實現(xiàn)
MyBatis 是一款優(yōu)秀的持久層框架,它支持定制化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數(shù)以及獲取結果集。我們在使用 Mybaits 進行 ,通常只需要定義幾個 Mapper 接口,然后在編寫一個 xml 文件,我們在配置文件中寫好 sql , Mybatis 幫我們完成 Mapper 接口道具體實現(xiàn)的調(diào)用。以及將結果映射到 model bean 中。
我們在項目中所編寫的眾多的 Mapper 類只是一個接口(interface ),根據(jù) Java 的多態(tài)性我們知道,可以使用接口接口作為形參,進而在運行時確定具體實現(xiàn)的對象是什么。但是,對于 Mapper 接口,我們并沒有編寫其實現(xiàn)類!Mybatis是如何找到其實現(xiàn)類,進而完成具體的 CRUD 方法調(diào)用的呢?原理何在?
為了弄清楚 Mapper 接口是如何找到實現(xiàn)類的,我們先回憶一下 Mybatis 是怎么使用的,根據(jù)實際的例子,進而一點點的去分析。這里的使用指的是Mybatis 單獨使用,而不是整合 spring , 因為整合 spring 的話,還需要涉及 Mapper dao 裝載到 spring 容器的問題,spring 幫忙創(chuàng)建數(shù)據(jù)源配置等問題。
通常我們使用 Mybatis 的主要步驟是:
從一段代碼看起
上面我們概括了使用 Mybatis 的4個步驟。這4個步驟看起來很簡單,但是用代碼寫出來就很多。我們不妨先記著這4個步驟,再去看代碼,會容易點。
在這塊代碼中,第 1 部分我們使用了 Java 編碼的形式來實現(xiàn) SqlSessionFactory ,也可以使用 xml 。如果使用xml的話,上面的第一部分代碼就是這樣的:
我們本次的目標是弄清楚 “ Mapper 是如何找到實現(xiàn)類的 ”,我們注意上面代碼 3 , 4 的位置:
這里 mapper 可以調(diào)用selectBlog(1) 這個方法,說明 mapper 是個對象,因為對象才具有方法行為實現(xiàn)啊。BlogMapper接口是不能實例化的,更沒有具體方法實現(xiàn)。我們并沒有定義一個類,讓它實現(xiàn)BlogMapper接口,而在這里它只是通過調(diào)用session.getMapper() 所得到的。由此,我們可以推斷:肯定是session.getMapper() 方法內(nèi)部產(chǎn)生了BlogMapper的實現(xiàn)類。有什么技術可以根據(jù)BlogMapper 接口生成了一個實現(xiàn)類呢?想到這里,對于有動態(tài)代理 使用經(jīng)驗的程序員來說,很容易想到,這背后肯定是基于動態(tài)代理技術,具體怎么實現(xiàn)的呢?下面我們來根據(jù)源碼一探究竟。
Mapper 接口的注冊
從上面的代碼中,我們知道 BlogMapper 接口的實現(xiàn)類是從session.getMapper中得來的,大概是基于動態(tài)代理技術實現(xiàn)。我們既然能夠從SqlSession中得到BlogMapper接口的,那么我們肯定需要先在哪里把它放進去了,然后 SqlSession 才能生成我們想要的代理類啊。上面代碼中有這么一行:
跟著這個 addMapper 方法的代碼實現(xiàn)是這樣的:
我們看到這里 mapper 實際上被添加到 mapperRegissry 中。繼續(xù)跟進代碼:
看到這里我們知道上面所執(zhí)行的configuration.addMapper(BlogMapper.class); 其實最終被放到了HashMap中,其名為knownMappers ,knowMappers是MapperRegistry 類的一個私有屬性,它是一個HashMap 。其Key 為當前Class對象,value 為一個MapperProxyFactory 實例。
這里我們總結一下: 諸如BlogMapper 之類的Mapper接口被添加到了MapperRegistry 中的一個HashMap中。并以 Mapper 接口的 Class 對象作為 Key , 以一個攜帶Mapper接口作為屬性的MapperProxyFactory 實例作為value 。MapperProxyFacory從名字來看,好像是一個工廠,用來創(chuàng)建Mapper Proxy的工廠。我們繼續(xù)往下看。
Mapper接口的動態(tài)代理類的生成
上面我們已經(jīng)知道,Mapper 接口被到注冊到了MapperRegistry中——放在其名為knowMappers 的HashMap屬性中,我們在調(diào)用Mapper接口的方法的時候,是這樣的:
這里,我們跟蹤一下session.getMapper() 方法的代碼實現(xiàn),這里 SqlSession 是一個接口,他有兩個實現(xiàn)類,一個是DefaultSqlSession,另外一個是SqlSessionManager,這里我們用的是DefaultSqlSession. 為什么是DefaultSqlSession呢?因為我們在初始化SqlSessionFactory的時候所調(diào)用的SqlSessionFactoryBuilder的build()方法里邊配置的就是DefaultSqlSession, 所以,我們進入到DefaultSession類中,看看它對session.getMapper(BlogMapper.class)是怎么實現(xiàn)的:
如代碼所示,這里的 getMapper 調(diào)用了 configuration.getMapper , 這一步操作其實最終是調(diào)用了MapperRegistry,而此前我們已經(jīng)知道,MapperRegistry是存放了一個HashMap的,我們繼續(xù)跟蹤進去看看,那么這里的get,肯定是從這個hashMap中取數(shù)據(jù)。我們來看看代碼:
我們調(diào)用的session.getMapper(BlogMapper.class);最終會到達上面這個方法,這個方法,根據(jù)BlogMapper的class對象,以它為key在knowMappers 中找到了對應的value —— MapperProxyFactory(BlogMapper) 對象,然后調(diào)用這個對象的newInstance()方法。根據(jù)這個名字,我們就能猜到這個方法是創(chuàng)建了一個對象,代碼是這樣的:
看到這里,就清楚了,最終是通過Proxy.newProxyInstance產(chǎn)生了一個BlogMapper的代理對象。Mybatis 為了完成 Mapper 接口的實現(xiàn),運用了代理模式。具體是使用了JDK動態(tài)代理,這個Proxy.newProxyInstance方法生成代理類的三個要素是:
代理模式中,代理類(MapperProxy)中才真正的完成了方法調(diào)用的邏輯。我們貼出MapperProxy的代碼,如下:
我們調(diào)用的 Blog blog = mapper.selectBlog(1); 實際上最后是會調(diào)用這個MapperProxy的invoke方法。這段代碼中,if 語句先判斷,我們想要調(diào)用的方法是否來自Object類,這里的意思就是,如果我們調(diào)用toString()方法,那么是不需要做代理增強的,直接還調(diào)用原來的method.invoke()就行了。只有調(diào)用selectBlog()之類的方法的時候,才執(zhí)行增強的調(diào)用——即mapperMethod.execute(sqlSession, args);這一句代碼邏輯。
而mapperMethod.execute(sqlSession, args);這句最終就會執(zhí)行增刪改查了,代碼如下:
再往下一層,就是執(zhí)行JDBC那一套了,獲取鏈接,執(zhí)行,得到ResultSet,解析ResultSet映射成JavaBean。
至此,我們已經(jīng)摸清楚了Blog blog = mapper.selectBlog(1); 中,BlogMapper接口調(diào)用到得到數(shù)據(jù)庫數(shù)據(jù)過程中,Mybaitis 是如何為接口生成實現(xiàn)類的,以及在哪里出發(fā)了最終的CRUD調(diào)用。實際上,如果我們在調(diào)用Blog blog = mapper.selectBlog(1);之前,把從slqSession中得到的 mapper 對象打印出來就會看到,輸出大概是這樣的:
動態(tài)代理沒錯吧,Java動態(tài)代理實在是太美妙了。
上面我們用層層深入的方式摸清楚了 Mapper接口是如何找到實現(xiàn)類的。我們分析了 Mapper接口是如何注冊的,Mapper接口是如何產(chǎn)生動態(tài)代理對象的,Maper接口方法最終是如何執(zhí)行的??偨Y起來主要就是這幾個點:
三、JAVA 將接口的引用指向?qū)崿F(xiàn)類的對象
有一個很簡單的例子,java.util中的類ArrayList實現(xiàn)了接口List則生成ArrayList對象時可用以下語句.
List list=new ArrayList();
也就是說所有實現(xiàn)了接口List的類,都可以用List接口來聲明對象類型,然后用實體類進行實例化.這表明了接口可以用來作為類型的表述.當然,生成的對象list只能調(diào)用接口List中提供的方法.
同樣的操作也可以用在父類與子類身上,例如設A類是B類的父類
則創(chuàng)建B類對象的時候可以用以下語句
A b=new B();
這樣的用法可以大大提高編程的靈活性.~
四、java Connection 是個接口
你最開始注冊驅(qū)動時不是傳了一個字符串進去嗎,Class.forName("className");這其實就是一個實現(xiàn)了Driver接口的類,當你調(diào)用DriverManager.getConnection(url)時,DriverManager將這個url傳給已經(jīng)注冊過所有的Driver對象,看是否有哪一個驅(qū)動即Driver 實現(xiàn)類能夠解吸這個url,假如有能夠解吸的話,那么調(diào)用這個Driver實現(xiàn)類的getConnection方法,而不同的Driver的getconnection方法實現(xiàn)肯定是不同的,但是他們都返回的是實現(xiàn)的cnnection接口的實現(xiàn)類,所以當你調(diào)用getconnection方法時,你實際在調(diào)用你的Class.forName傳如的類的getconnection方法
也就是說,你是獲取了注冊了的Connection對象,是一個已經(jīng)實現(xiàn)的類。
這個就好比log4j,是一個接口,你使用任何記錄日志的jar,都是通過這個log4j統(tǒng)一接口去解析,返回給你一個已經(jīng)實現(xiàn)的類。
以上就是關于java獲取接口的所有實現(xiàn)類相關問題的回答。希望能幫到你,如有更多相關問題,您也可以聯(lián)系我們的客服進行咨詢,客服也會為您講解更多精彩的知識和內(nèi)容。
推薦閱讀:
怎樣注冊chatGPT賬號(cheatninja要如何注冊)