反射在Spring IOC容器中的應用——動態創建Bean

今天在看Java八股文時,對這里產生了一些疑惑,因為在目前做的練手項目中還沒有用到過除了new以外的新建對象方式,在請教了其他前輩后對此有了新的理解,所以專門記錄以用于梳理思路和復習基礎。這里著重講解反射機制實現新建對象

這里用很經典的一個框架:Spring IOC容器來舉例講解

========================================================================

Spring的**控制反轉(IOC)**容器是反射最經典的應用場景。其核心邏輯是:通過反射動態加載用戶定義的類,創建對象,并注入依賴

1. 場景說明

假設我們有一個UserService類,依賴UserDao類(用戶定義的類):

// 用戶定義的Dao類(數據訪問層)
public class UserDao {public void save(User user) {System.out.println("保存用戶到數據庫:" + user);}
}// 用戶定義的Service類(業務層),依賴UserDao
public class UserService {private UserDao userDao; // 依賴注入的屬性// 構造器注入(或setter注入)public UserService(UserDao userDao) {this.userDao = userDao;}public void register(User user) {userDao.save(user); // 調用Dao的方法}
}

用戶通過Spring配置文件(或注解)聲明Bean:

<!-- applicationContext.xml 配置文件 -->
<beans><!-- 聲明UserDao Bean:類名是com.example.UserDao --><bean id="userDao" class="com.example.UserDao"/><!-- 聲明UserService Bean:依賴userDao --><bean id="userService" class="com.example.UserService"><constructor-arg ref="userDao"/> <!-- 構造器注入userDao --></bean>
</beans>

2. Spring IOC容器的工作流程(反射應用細節)

Spring容器(如ClassPathXmlApplicationContext)啟動時,會執行以下反射相關的步驟,創建UserServiceUserDao對象:

步驟1:加載配置文件,解析Bean定義

Spring讀取applicationContext.xml,解析出兩個Bean定義:

  • userDao:類名com.example.UserDao,無依賴;
  • userService:類名com.example.UserService,依賴userDao
步驟2:通過反射加載類(Class.forName()

①?解析配置文件,獲取類名

Spring的XmlBeanDefinitionReader(XML配置解析器)讀取applicationContext.xml,解析每個<bean>標簽的class屬性:

②?加載類的Class對象

  • 對于userDaoclass屬性的值是"com.example.UserDao"
  • 對于userServiceclass屬性的值是"com.example.UserService"

Spring使用Class.forName()加載每個類的Class對象(運行時動態加載):

// 加載UserDao類(com.example.UserDao)
Class<?> userDaoClass = Class.forName("com.example.UserDao", false, classLoader);
// 加載UserService類(com.example.UserService)
Class<?> userServiceClass = Class.forName("com.example.UserService", false, classLoader);
步驟3:通過反射獲取構造器(getConstructor()

Spring需要獲取類的構造器,才能創建對象。對于UserDao(無依賴),獲取無參構造器;對于UserService(依賴UserDao),獲取有參構造器(參數類型為UserDao):

// 獲取UserDao的無參構造器(UserDao有默認無參構造器)
Constructor<?> userDaoConstructor = userDaoClass.getConstructor();
// 獲取UserService的有參構造器(參數類型為UserDao)
Constructor<?> userServiceConstructor = userServiceClass.getConstructor(UserDao.class);
步驟4:通過反射創建對象(newInstance()
  • 創建UserDao對象:用無參構造器創建:
  •   // 創建UserDao對象(無參構造器)UserDao userDao = (UserDao) userDaoConstructor.newInstance();

  • 創建UserService對象:用有參構造器創建,傳入userDao對象(依賴注入):
  •   // 創建UserService對象(有參構造器,注入userDao)UserService userService = (UserService) userServiceConstructor.newInstance(userDao);

步驟5:將對象存入IOC容器

Spring將創建的userDaouserService對象存入IOC容器(如HashMap,鍵是bean id,值是對象):

// 模擬IOC容器(HashMap)
Map<String, Object> iocContainer = new HashMap<>();
iocContainer.put("userDao", userDao);
iocContainer.put("userService", userService);
步驟6:使用Bean(從容器中獲取)

用戶通過ApplicationContext從容器中獲取userService對象,無需手動new

// 啟動Spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 從容器中獲取userService對象(無需new)
UserService userService = (UserService) context.getBean("userService");
// 使用userService調用方法(依賴的userDao已注入)
userService.register(new User("zhangsan", 25));

為什么用反射?

  • Spring是通用框架,需要處理任意用戶定義的類(如UserServiceOrderServiceProductDao),無法在框架代碼中硬編碼new UserService()(因為框架開發者不知道用戶會定義哪些類)。
  • 反射的動態性Class.forName()加載任意類,newInstance()創建任意對象)滿足了這一需求,讓Spring能處理無限多的用戶類。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/93137.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/93137.shtml
英文地址,請注明出處:http://en.pswp.cn/web/93137.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

TRS(總收益互換)系統架構設計:多市場交易的技術實現分析

一、多市場交易環境的技術特征 1.1 市場機制差異&#xff08;技術視角&#xff09;技術維度典型實現差異交割周期T0/T1/T2等多種結算模式價格穩定機制部分市場存在波動率控制措施系統接入協議FIX 4.4/ITCH/OMD-C等協議族衍生品支持工具種類與中央對手方清算差異1.2 技術挑戰分析…

深度學習-卷積神經網絡CNN-批量歸一化 BatchNorm

為什么需要批量規范化層呢&#xff1f;讓我們來回顧一下訓練神經網絡時出現的一些實際挑戰&#xff1a;首先&#xff0c;數據預處理的方式通常會對最終結果產生巨大影響。 回想一下我們應用多層感知機來預測房價的例子。使用真實數據時&#xff0c;我們的第一步是標準化輸入特征…

機器學習-支持向量機器(SVM)

0.1 數字識別 from sklearn.svm import SVC from sklearn.metrics import silhouette_score import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.decomposition import PCA from sklearn.feature_extraction import DictVectorizer from sk…

昆山PCB板工廠有哪些?

在長三角電子信息產業版圖中&#xff0c;昆山憑借完整的產業鏈配套和精湛的制造工藝&#xff0c;成為國內PCB&#xff08;印制電路板&#xff09;生產的重要基地。本文精選五家具有代表性的本土工廠&#xff0c;從技術實力到服務特色展開深度剖析&#xff0c;為行業客戶提供精準…

rk3588 ubuntu20.04安裝包經常出現的問題總結(chatgpt回復)

問題1 問題 我在rk3588 ubuntu20.04安裝相關環境的時候經常出現下面類似的問題&#xff0c;如何系統的解決 The following packages have unmet dependencies : openssh-server : Depends: openssh-client ( 1:8.2p1-4ubuntu0.13) but 1:8.2p1-4ubuntu0.11 is to be installed …

從根源到生態:Apache Doris 與 StarRocks 的深度對比 —— 論開源基因與長期價值的優越性

在 OLAP 領域&#xff0c;Apache Doris 與 StarRocks 常被一同提及&#xff0c;兩者有著深厚的技術淵源 ——StarRocks 源自 Apache Doris 的代碼 Fork&#xff0c;卻在后續發展中走向了不同的路徑。本文將從代碼根源、架構演進、社區生態、功能特性等多維度展開對比。 一、代…

【從零開始學習Redis】項目實戰-黑馬點評D1

項目實戰-黑馬點評 項目架構短信登錄發送短信驗證碼 實現思路就是按照上圖左一部分&#xff0c; 實現類如下 Slf4j Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {/*** 驗證手機號發送驗證碼** param phone* pa…

自然語言處理的范式轉變:從Seq2Seq模型到Transformer架構

Seq2Seq 定義 Seq2Seq是一個Encoder-Decoder結構的網絡&#xff0c;它的輸入是一個序列&#xff0c;輸出也是一個序列&#xff0c; Encoder使用循環神經網絡(RNN,GRU&#xff0c;LSTM等)&#xff0c;將一個可變長度的信號序列(輸入句子)變為固定維度的向量編碼表達&#xff0c;…

【博客系統測試報告】---接口自動化測試

目錄 1、需求分析 2、挑選接口 3、設計博客系統的測試用例 4、設計自動化測試框架 test_add.py: test_detail.py: test_getAuthorInfo.py: test_getUserInfo: test_list.py: test_login.py: logger_util.py: request_util.py: yaml_util.py: 1、需求分析 根據業務…

Mysql數據庫遷移到GaussDB注意事項

mysql數據庫遷移高斯數據庫 建議開啟高斯數據庫M模式&#xff0c;mysql兼容模式&#xff0c;可以直接使用mysql的建表語句&#xff0c;自增主鍵可以使用AUTO_INCREMENT&#xff0c;如果不開啟M模式&#xff0c;只能使用高斯數據庫的序列添加自增主鍵1&#xff1a;如果使用數據庫…

蘋果正計劃大舉進軍人工智能硬件領域

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

Serverless 架構核心解析與應用實踐

Serverless 的核心定義與優勢??核心定義Serverless&#xff08;無服務器架構&#xff09;是一種云計算模型&#xff0c;開發者無需關注底層服務器管理&#xff0c;由云服務商自動分配資源、彈性擴縮容&#xff0c;并按實際使用量計費?。其核心特點包括&#xff1a;?按需計算…

Redis持久化機制詳解:RDB與AOF的全面對比與實踐指南

目錄 一、RDB持久化機制 1.1 RDB概述 1.2 RDB觸發機制 1) 手動執行save命令 2) 手動執行bgsave命令 3) Redis正常關閉時 4) 自動觸發條件滿足時 1.3 RDB詳細配置 1.4 RDB實現原理 1.5 RDB的優缺點分析 二、AOF持久化機制 2.1 AOF概述 2.2 AOF工作流程 2.3 AOF同步…

介紹一下jQuery的AJAX異步請求

目錄 一、核心方法&#xff1a;$.ajax() 二、簡化方法&#xff08;常用場景&#xff09; 1. $.get()&#xff1a;快速發送 GET 請求&#xff08;獲取數據&#xff09; 2. $.post()&#xff1a;快速發送 POST 請求&#xff08;提交數據&#xff09; 3. $.getJSON()&#xf…

Win10系統Ruby+Devkit3.4.5-1安裝

Win10系統RubyDevkit3.4.5-1安裝安裝步驟軟件工具安裝Ruby安裝gem mysql2處理libmysql.dll驗證mysql2安裝步驟 軟件工具 mysql-connector-c-6.1.11-winx64.zip rubyinstaller-devkit-3.4.5-1-x64.exe 安裝Ruby 執行rubyinstaller-devkit-3.4.5-1-x64.exe&#xff0c;期間可…

社交工程:洞穿人心防線的無形之矛

在網絡安全領域&#xff0c;一道無形的裂痕正在迅速蔓延。它不是復雜的零日漏洞&#xff0c;也不是精妙的惡意代碼&#xff0c;而是利用人性弱點進行攻擊的古老技藝——社交工程。當全球網絡安全支出突破千億美元大關&#xff0c;防火墻筑得越來越高&#xff0c;加密算法越來越…

Go 并發控制利器 ants 使用文檔

https://github.com/panjf2000/ants1.1 什么是 ants ants 是一個高性能的 Go 語言 goroutine 池&#xff0c;它能復用已完成任務的 goroutine&#xff0c;避免頻繁創建和銷毀 goroutine&#xff0c;節省 CPU 與內存開銷&#xff0c;并且能限制并發數量防止資源被耗盡。 1.2 安裝…

Day57--圖論--53. 尋寶(卡碼網)

Day57–圖論–53. 尋寶&#xff08;卡碼網&#xff09; 今天學習&#xff1a;最小生成樹。有兩種算法&#xff08;Prim和Kruskal&#xff09;和一道例題。 prim 算法是維護節點的集合&#xff0c;而 Kruskal 是維護邊的集合。 最小生成樹&#xff1a;所有節點的最小連通子圖&am…

解決海洋探測數據同步網絡問題的新思路——基于智能組網技術的探索

隨著海洋探測技術的不斷發展&#xff0c;數據同步網絡的穩定性和低延遲需求變得愈發重要。海洋探測數據來自多個分布式采集點&#xff0c;這些點需要高效的組網方式來實現實時數據傳輸。然而&#xff0c;由于海洋環境的特殊性&#xff08;如復雜的網絡拓撲、高濕度和極端溫度&a…

設計模式筆記_行為型_責任鏈模式

1. 責任鏈模式介紹責任鏈模式&#xff08;Chain of Responsibility&#xff09;是一種行為設計模式&#xff0c;它允許將多個處理器&#xff08;處理對象&#xff09;連接成一條鏈&#xff0c;并沿著這條鏈傳遞請求&#xff0c;直到有一個處理器處理它為止。職責鏈模式的主要目…