日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

学习spring之前必学之反射技术(IOC)(一)

發布時間:2024/9/5 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 学习spring之前必学之反射技术(IOC)(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引述要學習Spring框架的技術內幕,必須事先掌握一些基本的Java知識,正所謂“登高必自卑,涉遠必自邇”。

以下幾項Java知識和Spring框架息息相關,不可不學

??? Java語言允許通過程序化的方式間接對Class進行操作,Class文件由類裝載器裝載后,在JVM中將形成一份

描述Class結構的元信息對象,通過該元信息對象可以獲知Class的結構信息:如構造函數、屬性和方法等。Java

允許用戶借由這個Class相關的元信息對象間接調用Class對象的功能,這就為使用程序化方式操作Class對象開辟

了途徑。

簡單實例

??? 我們將從一個簡單例子開始探訪Java反射機制的征程,下面的Car類擁有兩個構造函數、兩個方法以及三個屬性?

Java代碼 ?
  • package?com.baobaotao.reflect;??
  • public?class?Car?{??
  • ????private?String?brand;??
  • ????private?String?color;??
  • ????private?int?maxSpeed;??
  • ??????
  • ?????//①默認構造函數??
  • ????public?Car(){}??
  • ???????
  • ?????//②帶參構造函數??
  • ????public?Car(String?brand,String?color,int?maxSpeed){???
  • ????????this.brand?=?brand;??
  • ????????this.color?=?color;??
  • ????????this.maxSpeed?=?maxSpeed;??
  • ????}??
  • ??
  • ?????//③未帶參的方法??
  • ????public?void?introduce()?{???
  • ???????System.out.println("brand:"+brand+";color:"+color+";maxSpeed:"?+maxSpeed);??
  • ????}??
  • ?????//省略參數的getter/Setter方法??
  • ?????…??
  • }??

  • 一般情況下,我們會使用如下的代碼創建Car的實例:

    Java代碼 ?
  • Car?car?=?new?Car();??
  • car.setBrand("紅旗CA72");??

  • 或者:

    Java代碼 ?
  • Car?car?=?new?Car("紅旗CA72","黑色");??


  • 以上兩種方法都采用傳統方式的直接調用目標類的方法,下面我們通過Java反射機制以一種更加通用的方式間接地操作目標類:

    Java代碼 ?
  • package?com.baobaotao.?reflect;??
  • import?java.lang.reflect.Constructor;??
  • import?java.lang.reflect.Field;??
  • import?java.lang.reflect.Method;??
  • public?class?ReflectTest?{??
  • ????public?static?Car??initByDefaultConst()?throws?Throwable??
  • ????{??
  • ????????//①通過類裝載器獲取Car類對象??
  • ????????ClassLoader?loader?=?Thread.currentThread().getContextClassLoader();???
  • ????????Class?clazz?=?loader.loadClass("com.baobaotao.reflect.Car");???
  • ??????????
  • ??????????//②獲取類的默認構造器對象并通過它實例化Car??
  • ????????Constructor?cons?=?clazz.getDeclaredConstructor((Class[])null);???
  • ????????Car?car?=?(Car)cons.newInstance();??
  • ??????????
  • ???????????
  • ??????????//③通過反射方法設置屬性??
  • ????????Method?setBrand?=?clazz.getMethod("setBrand",String.class);??????????
  • ????????setBrand.invoke(car,"紅旗CA72");????????
  • ????????Method?setColor?=?clazz.getMethod("setColor",String.class);??
  • ????????setColor.invoke(car,"黑色");????????
  • ????????Method?setMaxSpeed?=?clazz.getMethod("setMaxSpeed",int.class);??
  • ????????setMaxSpeed.invoke(car,200);??????????
  • ????????return?car;??
  • ????}??
  • ??
  • ????public?static?void?main(String[]?args)?throws?Throwable?{??
  • ????????Car?car?=?initByDefaultConst();??
  • ????????car.introduce();??
  • ????}??
  • }??

  • 運行以上程序,在控制臺上將打印出以下信息:

    引用 brand:紅旗CA72;color:黑色;maxSpeed:200



    這說明我們完全可以通過編程方式調用Class的各項功能,這和直接通過構造函數和方法調用類功能的效果是一致的,

    只不過前者是間接調用,后者是直接調用罷了。

    在ReflectTest中,使用了幾個重要的反射類,分別是ClassLoader、Class、Constructor和Method,通過這些

    反射類就可以間接調用目標Class的各項功能了。在①處,我們獲取當前線程的ClassLoader,然后通過指定的全

    限定類“com.baobaotao.beans.Car”裝載Car類對應的反射實例。在②處,我們通過Car的反射類對象獲取Car的

    構造函數對象cons,通過構造函數對象的newInstrance()方法實例化Car對象,其效果等同于new Car()。在③處

    我們又通過Car的反射類對象的getMethod(String methodName,Class paramClass)獲取屬性的Setter方法

    對象,第一個參數是目標Class的方法名;第二個參數是方法入參的對象類型。獲取方法反射對象后,即可通過

    invoke(Object obj,Object param)方法調用目標類的方法,該方法的第一個參數是操作的目標類對象實例;

    第二個參數是目標方法的入參。?


    類裝載器ClassLoader

    類裝載器工作機制

    類裝載器就是尋找類的節碼文件并構造出類在JVM內部表示對象的組件。在Java中,類裝載器把一個類裝入JVM中,要經過以下步驟:
    [1.]裝載:查找和導入Class文件;

    [2.]鏈接:執行校驗、準備和解析步驟,其中解析步驟是可以選擇的:

    ? [2.1]校驗:檢查載入Class文件數據的正確性;?

    ? [2.2]準備:給類的靜態變量分配存儲空間;

    ? [2.3]解析:將符號引用轉成直接引用;

    [3.]初始化:對類的靜態變量、靜態代碼塊執行初始化工作。

    ?

    ? ? ? 類裝載工作由ClassLoader及其子類負責,ClassLoader是一個重要的Java運行時系統組件,它負責在運行時

    查找和裝入Class字節碼文件。JVM在運行時會產生三個ClassLoader:根裝載器、ExtClassLoader(擴展類裝載器)

    和AppClassLoader(系統類裝載器)。其中,根裝載器不是ClassLoader的子類,它使用C++編寫,因此我們在

    Java中看不到它,根裝載器負責裝載JRE的核心類庫,如JRE目標下的rt.jar、charsets.jar等。ExtClassLoader

    和AppClassLoader都是ClassLoader的子類。其中ExtClassLoader負責裝載JRE擴展目錄ext中的JAR類包;

    AppClassLoader負責裝載Classpath路徑下的類包。

    這三個類裝載器之間存在父子層級關系,即根裝載器是ExtClassLoader的父裝載器,ExtClassLoader是AppClassLoader的父裝載器。

    默認情況下,使用AppClassLoader裝載應用程序的類,我們可以做一個實驗:

    Java代碼 ?
  • public?class?ClassLoaderTest?{??
  • ????public?static?void?main(String[]?args)?{??
  • ????????ClassLoader?loader?=?Thread.currentThread().getContextClassLoader();??
  • ????????System.out.println("current?loader:"+loader);??
  • ????????System.out.println("parent?loader:"+loader.getParent());??
  • ????????System.out.println("grandparent?loader:"+loader.getParent().?getParent());??
  • ????}??
  • }??

  • 運行以上代碼,在控制臺上將打出以下信息:

    引用 current loader:sun.misc.Launcher$AppClassLoader@131f71a
    parent loader:sun.misc.Launcher$ExtClassLoader@15601ea
    ???? //①根裝載器在Java中訪問不到,所以返回null
    grandparent loader:null



    通過以上的輸出信息,我們知道當前的ClassLoader是AppClassLoader,父ClassLoader是ExtClassLoader

    ,祖父ClassLoader是根類裝載器,因為在Java中無法獲得它的句柄,所以僅返回null。

    JVM裝載類時使用“全盤負責委托機制”,“全盤負責”是指當一個ClassLoader裝載一個類的時,除非顯式地使用

    另一個ClassLoader,該類所依賴及引用的類也由這個ClassLoader載入;“委托機制”是指先委托父裝載器尋找

    目標類,只有在找不到的情況下才從自己的類路徑中查找并裝載目標類。這一點是從安全角度考慮的,試想如果

    有人編寫了一個惡意的基礎類(如java.lang.String)并裝載到JVM中將會引起多么可怕的后果。但是由于有了

    “全盤負責委托機制”,java.lang.String永遠是由根裝載器來裝載的,這樣就避免了上述事件的發生。

    ClassLoader重要方法

    在Java中,ClassLoader是一個抽象類,位于java.lang包中。下面對該類的一些重要接口方法進行介紹:

    • ? Class loadClass(String name)? ?name參數指定類裝載器需要裝載類的名字,必須使用全限定類名,如com.baobaotao. beans.Car。該方法有一個重載方法loadClass(String name ,boolean resolve),resolve參數告訴類裝載器是否需要解析該類。在初始化類之前,應考慮進行類解析的工作,但并不是所有的類都需要解析,如果JVM只需要知道該類是否存在或找出該類的超類,那么就不需要進行解析。
    • Class defineClass(String name, byte[] b, int off, int len)?將類文件的字節數組轉換成JVM內部的java.lang.Class對象。字節數組可以從本地文件系統、遠程網絡獲取。name為字節數組對應的全限定類名。
    • ? Class findSystemClass(String name)? 從本地文件系統載入Class文件,如果本地文件系統不存在該Class文件,將拋出ClassNotFoundException異常。該方法是JVM默認使用的裝載機制。
    • ? Class findLoadedClass(String name)?調用該方法來查看ClassLoader是否已裝入某個類。如果已裝入,那么返回java.lang.Class對象,否則返回null。如果強行裝載已存在的類,將會拋出鏈接錯誤。
    • ? ClassLoader getParent()?獲取類裝載器的父裝載器,除根裝載器外,所有的類裝載器都有且僅有一個父裝載器,ExtClassLoader的父裝載器是根裝載器,因為根裝載器非Java編寫,所以無法獲得,將返回null。



    除JVM默認的三個ClassLoader以外,可以編寫自己的第三方類裝載器,以實現一些特殊的需求。類文件被裝載并解析后,

    在JVM內將擁有一個對應的java.lang.Class類描述對象,該類的實例都擁有指向這個類描述對象的引用,而類描述對象

    又擁有指向關聯ClassLoader的引用,如圖3-4所示。



    每一個類在JVM中都擁有一個對應的java.lang.Class對象,它提供了類結構信息的描述。數組、

    枚舉、注解以及基本Java類型(如int、double等),甚至void都擁有對應的Class對象。Class

    沒有public的構造方法。Class對象是在裝載類時由JVM通過調用類裝載器中的defineClass()方

    法自動構造的。

    Java反射機制

    Class反射對象描述類語義結構,可以從Class對象中獲取構造函數、成員變量、方法類等類元素的

    反射對象,并以編程的方式通過這些反射對象對目標類對象進行操作。這些反射對象類在java.reflect

    包中定義,下面是最主要的三個反射類:?

      • ?? Constructor:類的構造函數反射類,通過Class#getConstructors()方法可以獲得類的所有構造函數反射對象數組。在JDK5.0中,還可以通過getConstructor(Class... parameterTypes)獲取擁有特定入參的構造函數反射對象。Constructor的一個主要方法是newInstance(Object[] initargs),通過該方法可以創建一個對象類的實例,相當于new關鍵字。在JDK5.0中該方法演化為更為靈活的形式:newInstance (Object... initargs)。
      • ?? Method:類方法的反射類,通過Class#getDeclaredMethods()方法可以獲取類的所有方法反射類對象數組Method[]。在JDK5.0中可以通過getDeclaredMethod(String name, Class... parameterTypes)獲取特定簽名的方法,name為方法名;Class...為方法入參類型列表。Method最主要的方法是invoke(Object obj, Object[] args),obj表示操作的目標對象;args為方法入參,代碼清單3 10③處演示了這個反射類的使用方法。在JDK 5.0中,該方法的形式調整為invoke(Object obj, Object... args)。此外,Method還有很多用于獲取類方法更多信息的方法: ????? 1)Class getReturnType():獲取方法的返回值類型;
      • ????? 2)Class[] getParameterTypes():獲取方法的入參類型數組;
      • ????? 3)Class[] getExceptionTypes():獲取方法的異常類型數組;
    • ????? 4)Annotation[][] getParameterAnnotations():獲取方法的注解信息,JDK 5.0中的新方法;
    • ?? Field:類的成員變量的反射類,通過Class#getDeclaredFields()方法可以獲取類的成員變量反射對象數組,通過Class#getDeclaredField(String name)則可獲取某個特定名稱的成員變量反射對象。Field類最主要的方法是set(Object obj, Object value),obj表示操作的目標對象,通過value為目標對象的成員變量設置值。如果成員變量為基礎類型,用戶可以使用Field類中提供的帶類型名的值設置方法,如setBoolean(Object obj, boolean value)、setInt(Object obj, int value)等。


    此外,Java還為包提供了Package反射類,在JDK 5.0中還為注解提供了AnnotatedElement反射類。總之,

    Java的反射體系保證了可以通過程序化的方式訪問目標類中所有的元素,對于private或protected的成員變量

    和方法,只要JVM的安全機制允許,也可以通過反射進行調用,請看下面的例子:

    Java代碼 ?
  • package?com.baobaotao.reflect;??
  • public?class?PrivateCar?{??
  • ???????//①private成員變量:使用傳統的類實例調用方式,只能在本類中訪問??
  • ???private?String?color;???
  • ????????//②protected方法:使用傳統的類實例調用方式,只能在子類和本包中訪問??
  • ???protected?void?drive(){??
  • ?????????
  • System.out.println("drive?private?car!?the?color?is:"+color);??
  • ???}??
  • }??

  • color變量和drive()方法都是私有的,通過類實例變量無法在外部訪問私有變量、調用私有方法的,但通過

    反射機制卻可以繞過這個限制:

    Java代碼 ?
  • …??
  • public?class?PrivateCarReflect?{??
  • ???public?static?void?main(String[]?args)?throws?Throwable{??
  • ???????ClassLoader?loader?=?Thread.currentThread().getContextClassLoader();??
  • ???????Class?clazz?=?loader.loadClass("com.baobaotao.reflect.PrivateCar");??
  • ???????PrivateCar?pcar?=?(PrivateCar)clazz.newInstance();??
  • ?????????
  • ???????Field?colorFld?=?clazz.getDeclaredField("color");??
  • ????????//①取消Java語言訪問檢查以訪問private變量??
  • ???????colorFld.setAccessible(true);???
  • ???????colorFld.set(pcar,"紅色");??
  • ?????????
  • ???????Method?driveMtd?=?clazz.getDeclaredMethod("drive",(Class[])null);??
  • ????????//Method?driveMtd?=?clazz.getDeclaredMethod("drive");?JDK5.0下使用??
  • ?????????
  • ????????//②取消Java語言訪問檢查以訪問protected方法??
  • ???????driveMtd.setAccessible(true);???
  • ????????driveMtd.invoke(pcar,(Object[])null);??
  • ??}??
  • }??

  • 運行該類,打印出以下信息:

    引用 drive private car! the color is:紅色



    在訪問private、protected成員變量和方法時必須通過setAccessible(boolean access)方法取消Java語言檢查,

    否則將拋出IllegalAccessException。如果JVM的安全管理器設置了相應的安全機制,調用該方法將拋出SecurityException。

    轉載于:https://www.cnblogs.com/fyboke/p/6428692.html

    總結

    以上是生活随笔為你收集整理的学习spring之前必学之反射技术(IOC)(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 午夜黄色影院 | 少妇av网 | 精品久久久久久中文字幕人妻最新 | 在线观看中文字幕一区二区 | 日本女优中文字幕 | 美国一级大黄一片免费中文 | 中文字幕 视频一区 | 欧美精品高清 | www国产精品内射老熟女 | 草草影院在线观看视频 | 偷拍一区二区三区 | 中文字幕在线播放日韩 | 误杀1电影免费观看高清完整版 | 秋霞欧美一区二区三区视频免费 | 亚洲日本国产精品 | 国产精品秘 | 成人毛片18女人毛片 | 爱情岛av | www视频免费观看 | 在线观看日韩av | 国产在线国偷精品免费看 | www天天操 | 男女网站在线观看 | 丰满人妻翻云覆雨呻吟视频 | av免费在线观看不卡 | 国产成人精品一区二区三区在线观看 | 亚洲va久久久噜噜噜久久天堂 | 欧美视频性 | 毛片aaaaaa| 亚洲美女高潮久久久 | 日韩精品久久久久久免费 | 午夜生活片 | a级片网站| 91嫩草欧美久久久九九九 | 五月在线| 中文字幕网址在线 | 性色生活片 | a视频免费在线观看 | 直接看的av网站 | 日韩在线视频在线 | 成人一区三区 | 91视频免费网站 | 丝袜av在线播放 | 国产天天操 | 国产调教| 性色av无码久久一区二区三区 | 久久亚洲网 | 国产一区毛片 | a人片 | 毛片88| 国产123| 亚洲欧美激情小说另类 | 国产农村妇女毛片精品 | 久久久久久久综合 | 97超级碰碰碰 | 免费黄网站在线 | 简单av网 | www日日日| 瑟瑟视频免费观看 | 中国老妇性视频 | 麻豆久久久9性大片 | 国产在线观看免费高清 | 人人草人人搞 | 99亚洲国产精品 | 日本三级理论片 | 午夜视频大全 | 91精品国产91久久久 | 午夜视频入口 | 亚洲一区二区三区电影在线观看 | 91久久精品视频 | 伊人网五月天 | 国产精品视频网 | 色久影院 | 黄色日韩视频 | 免费久久网站 | 免费在线观看av片 | 亚洲AV成人午夜无码精品久久 | 国产伦精品一区二区三区视频我 | 久久久精品视频在线 | 性色在线 | 毛片网站有哪些 | 久久这里有精品 | 乳色吐息在线观看 | 日韩精品观看 | 欧美亚洲中文精品字幕 | 亚洲日日骚| 人妻少妇精品无码专区久久 | 冲田杏梨一区二区三区 | 夜夜操天天干 | 中文字幕一区二区三区四区不卡 | 免费黄色在线 | 色婷婷激情综合 | 免费看黄色a级片 | 先锋影音一区二区三区 | 久色88 | 日日夜夜干| 亚洲成人精品在线 | av影院在线观看 | 超碰97在线资源站 |