91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot如何實現使用反射模擬IOC和getBean

發布時間:2023-04-03 11:13:19 來源:億速云 閱讀:145 作者:iii 欄目:開發技術

這篇文章主要介紹“SpringBoot如何實現使用反射模擬IOC和getBean”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“SpringBoot如何實現使用反射模擬IOC和getBean”文章能幫助大家解決問題。

spring基礎思想IOC

其次就是java的反射,反射機制是spring的重要實現核心,今天我看spring的三級緩存解決循壞引用的問題時,發現一個bean的生命周期與java對象的產生流程具備高度相似性,接著我就去重溫了一下bean的創建流程,發現一個bean實例從無到有經歷的過程非常有意思,spring用極其優雅的代碼實現了用反射和各種map數據結構實現了bean的流水線式生產,非常優雅,于是我就嘗試用反射寫一個逆向生成實例對象的小玩意。

那么前置需要了解一個對象生成的過程:

我將對象的創建過程總結為:

檢查常量池是否存在該對象的符號引用并確定是否經過類加載過程,都沒有則進行類加載過程。

為新生對象分配內存(兩種方式:指針碰撞和空閑列表<指針碰撞涉及到當指針調動頻繁時為了避免出現臟讀,采取本地線程分配緩沖TLAB的優先分配情況>)并將除對象頭外的其他內存空間賦值W為0。

設置對象頭。

對象的初始化,這個就是執行你的構造方法的過程,給你需要的字段賦值你想要定義的值。

補充一下其中的細節:為新生對象分配內存過程中,首先一個對象在類加載完成后它所需要的內存大小是完全確定的,分配內存的過程實際上就是在java堆里劃分一塊等大的內存給它,但是該怎么劃分呢?如果java堆的內存布局是嚴格的順序分配,即一邊是使用過的,一邊是空閑的,那么就會采取指針碰撞的方式分配內存,所謂的指針在空閑區與使用區的分界線處,收到內存需求時,指針向后移動直到移動所覆蓋的長度等于java對象所需要的內存大小時停止并進行分配。但如果java堆的內存布局是碎片化的不連續的呢?我們就只能維護一個列表,這個列表記錄了所有java堆空閑區的大小與位置信息,分配時只需要查找最適合新生對象的區域分配即可。

注意:java堆是否規整是由垃圾收集器的能力決定的,是否帶有空間壓縮整理的能力。當我們采用的收集器是Serial與Parnew時是用指針碰撞的方式分配的,當采用的是CMS垃圾收集器的時候,則是需要使用麻煩的空閑區表分配。

這里我們著重的去關注屬性與方法的填充即可:一個對象的靈魂就是它的屬性與方法:

整個工具用到的核心屬性:

    private static volatile Constructor<?> constructor;
    private static volatile Object newInstance;
    private static volatile Map<String, Method> methodMap;

我們先看看這幾個方法的作用:

  public static Constructor<?> getConstructor(Object dataType) {
        Class<?> typeClass = dataType.getClass();
        try {
            Constructor<?> constructor = typeClass.getConstructor();
            constructor.setAccessible(true);
            return constructor;
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            return null;
        }
    }

獲取類型的構造器,注意這可是無參構造,如果你沒有無參構造那么很有可能報錯,因為我們也不知道它有多少屬性對吧?(時刻記住咱們是逆向!!!不知道這個類型里有什么!!!一切都是反射帶來的信息)

public static void fillValueToNewInstance(Object dataType, Map<String, Object> initialMap) throws Exception {
        constructor = getConstructor(dataType);
        Class<?> typeClass = dataType.getClass();
        Field[] declaredFields = typeClass.getDeclaredFields();
        Iterator<Field> fieldIterator = Arrays.stream(declaredFields).iterator();
        newInstance = constructor.newInstance();
        while (fieldIterator.hasNext()) {
            Field field = fieldIterator.next();
            field.setAccessible(true);
            if (initialMap != null)
                field.set(newInstance, initialMap.get(field.getName()));
        }
    }

獲取屬性并填充屬性值,這里也順帶著將屬性給進去了。

 public static Method[] getMethodArray(Object dataType) {
        return dataType.getClass().getDeclaredMethods();
    }

獲取一切方法組成方法數組。

  public static void fillMethodMap(Object dataType) {
        methodMap = new HashMap<>();
        Method[] methodArray = getMethodArray(dataType);
        Iterator<Method> iterator = Arrays.stream(methodArray).iterator();
        while (iterator.hasNext()) {
            Method method = iterator.next();
            method.setAccessible(true);
            methodMap.put(method.getName(), method);
        }
    }

將方法存到方法集合中去存儲。

 public static Object useMethod(String methodName, @Nullable Object... parameters) throws Exception {
        return methodMap.get(methodName).invoke(newInstance, parameters);
    }

使用方法要通過名稱。

    @SneakyThrows
    public static Object getBean(Object dataType, Map<String, Object> parameterMap) {
        fillValueToNewInstance(dataType, parameterMap);
        fillMethodMap(dataType);
        return newInstance;
    }

getBean方法。

  public static void main(String[] args) throws Exception {
        Map<String,Object> map = new HashMap<>();
        map.put("name","xu");
        map.put("age",Integer.valueOf(18));
        map.put("sex",'女');
        Person bean = (Person) getBean(new Person(), map);
        System.out.println(bean.toString());
        System.out.println(useMethod("toString"));
    }

測試方法。類型信息如下:

class Person {
    private String name;
    private Integer age;
    private Character sex;
    //無參構造絕對不能少
    public Person() {
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }
}

測試結果如下:

SpringBoot如何實現使用反射模擬IOC和getBean

這里我們可沒有用Person person = new Person();的方式實例化對象,用反射實現了對象的實例化。

里面用到關于反射的方法我列下來:

getDeclaredFields 獲取域屬性對象

getName 獲取屬性名稱

getType 獲取屬性類型的字節碼文件

setAccessible(true) 設置暴力破解,獲取對私有屬性的使用

getDeclaredMethods 獲取全部方法數組

getClass 獲取字節碼文件

getConstructor 獲取無參構造器

關于“SpringBoot如何實現使用反射模擬IOC和getBean”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

陇南市| 莎车县| 平舆县| 射洪县| 绥芬河市| 探索| 淳化县| 中江县| 资源县| 肇源县| 阜康市| 盱眙县| 裕民县| 太和县| 六盘水市| 临清市| 元朗区| 齐河县| 金昌市| 乾安县| 孝昌县| 石门县| 攀枝花市| 临猗县| 木兰县| 福鼎市| 尉氏县| 烟台市| 高邮市| 介休市| 成安县| 宜君县| 保山市| 湖北省| 房产| 孝感市| 漠河县| 巴塘县| 湘阴县| 云林县| 金乡县|