知識點:
1.自動裝配@Resource(3)
知識點 | 核心內容 | 重點 |
@Autowired與@Resource注入規則 | 默認注入邏輯:未指定參數時,@Resource優先按屬性名匹配(by name),失敗后按類型匹配(by type);兩者均失敗則報錯 | 名稱匹配優先級:屬性名需與容器中Bean的ID完全一致 |
多實例場景下的依賴注入 | 容器中存在多個同類型Bean時: - 僅當屬性名與某一Bean ID匹配時成功; - 類型匹配必然失敗(需唯一性) | 典型錯誤場景:存在3個UserService實例時,未明確指定名稱的注入 |
注解使用規范建議 | 1. 優先使用@Resource; 2. 屬性名需符合駝峰命名規范(如userService); 3. 泛型依賴等特殊場景仍需@Autowired | 版本差異:@Autowired未被廢棄但官方推薦替換 |
驗證實驗設計 | 通過修改Bean ID(如userService200)與屬性名對比: - 同名匹配成功案例; - 無匹配時的類型檢查報錯 | 調試技巧:輸出Bean哈希值驗證注入實例 |
面試高頻考點 | 1. 兩種注解的匹配順序差異; 2. 多實例沖突解決方案; 3. 官方推薦注解的演變 | 易錯點:認為@Resource會智能合并名稱與類型策略 |
2.自動裝配小結
知識點 | 核心內容 | 重點 |
自動裝配的注意事項 | 當待裝配類型在IOC容器中有多個實例時,使用屬性名作為ID值進行查找 | 裝配失敗會拋出異常 |
@Autowired與@Qualifier配合使用 | 通過@Autowired+@Qualifier("指定ID")實現精確裝配 | 需要同時使用兩個注解 |
@Resource注解使用 | 通過@Resource(name="指定ID")單注解實現裝配 | 優先按name匹配,其次按類型 |
裝配規則對比 | @Autowired:先類型后名稱 @Resource:先名稱后類型 | 兩種注解的匹配順序差異 |
最佳實踐建議 | 推薦使用@Resource+規范屬性名 | 保證命名規范性可避免混淆 |
3.泛型依賴注入(1)
知識點 | 核心內容 | 重點 |
泛型依賴注入 | Spring提供的基于泛型的自動裝配機制,通過父類泛型標識實現子類依賴注入 | 泛型類型傳遞與父類自動裝配邏輯的關聯性 |
BaseDAO設計模式 | 支持泛型的基類DAO,子類通過繼承并指定泛型類型實現具體操作 | 泛型類繼承時的類型確定時機(創建對象/繼承時) |
BaseService與DAO關聯 | 通過泛型依賴注入自動將BookDAO裝配到BookService,避免重復聲明屬性 | 父類泛型參數如何映射到子類依賴關系 |
泛型基礎回顧 | 自定義泛型類、泛型類型擦除等Java基礎概念 | 泛型類與普通類的實例化差異 |
實際應用場景 | 繼承關系復雜的項目(如家居購項目)中簡化依賴配置 | 傳統裝配方式與泛型注入的代碼量對比 |
4.泛型依賴注入(2)
知識點 | 核心內容 | 重點 |
泛型依賴注入機制 | 通過泛型傳遞實現自動裝配(如BaseService<T>注入BaseDao<T>子類) | 泛型類型推導與普通@Autowired的區別 |
Spring注解應用 | @Repository標記DAO層、@Service標記業務層 | @Autowired在泛型場景下的強制使用 |
IOC容器調試 | 通過斷點查看singletonObjects驗證依賴關系 | 動態綁定機制與運行時類型識別 |
分層架構設計 | BaseDao→BookDao/PhoneDao,BaseService→BookService/PhoneService | 抽象類與泛型的聯合應用 |
配置文件管理 | 多配置文件拆分(beans06.xml→beans07.xml) | 包掃描路徑與注解掃描范圍 |
5.AOP文檔說明
知識點 | 核心內容 | 重點 |
AOP(切面編程) | 通過動態代理機制實現功能解耦,核心支撐技術包括反射和動態綁定 | 動態代理的實現原理與反射機制的關系 |
動態代理 | 支撐AOP的核心技術,涉及反射和動態綁定 | 動態代理與靜態代理的區別及適用場景 |
Spring AOP文檔 | 官方文檔位置:reference中的aspect oriented programming with spring章節及org.springframework.aop包API | API查找路徑與實際開發中的高頻使用類 |
學習難點 | 理解底層機制(動態代理、反射)及實際應用場景 | 切面編程的抽象概念與具體代碼實現的對應關系 |
6.動態代理需求說明
知識點 | 核心內容 | 重點 |
動態代理 | AOP的核心支撐技術,需通過案例理解其實現邏輯 | 代理模式與原生調用的區別 InvocationHandler接口的作用 |
傳統方案實現 | 直接在Car/Ship的run()方法中硬編碼"開始/停止"邏輯 | 代碼重復問題 違反開閉原則 |
動態代理優勢 | 通過代理類統一處理公共邏輯(如"交通工具開始/停止運行") | 反射調用的性能損耗 接口代理的限制 |
案例需求 | 對Vehicle接口的run()方法增強: 1. 統一前置/后置輸出 2. 保留子類特有邏輯 | 增強邏輯與業務邏輯的分離 JDK動態代理與CGLIB的區別 |
重點 | 通過對比傳統方案與動態代理方案突出解耦價值 | AOP底層原理的關聯性 Spring AOP的代理選擇策略 |
7.傳統方法解決需求
知識點 | 核心內容 | 重點 |
動態代理概念 | 通過接口編程實現方法調用的統一控制,解決代碼冗余問題 | 動態綁定機制與接口多態性 |
傳統實現方式 | 直接在實現類中硬編碼前后置邏輯(Car/Ship類) | 接口引用指向實現類對象的OOP特性 |
代碼冗余問題 | 相同的前后置日志出現在所有實現類中 | 維護成本與統一管理難點 |
動態代理優勢 | 統一管理方法調用的前后置操作(日志/權限/事務等) | AOP編程思想的實現基礎 |
Vehicle接口示例 | 定義run()抽象方法,Car/Ship分別實現 | 編譯類型與運行類型的動態綁定 |
開發場景應用 | 權限校驗/安全驗證/事務管理等橫切關注點 | 代理模式與裝飾器模式區別 |
教學演示步驟 | 1. 創建接口 2. 編寫實現類 3. 暴露冗余問題 4. 引入代理方案 | 測試用例中接口引用的多態應用 |
8.動態代理解決問題(1)
知識點 | 核心內容 | 重點 |
動態代理實現原理 | 通過Proxy.newProxyInstance()生成代理對象,底層基于反射機制 | 接口必須保持不變,代理對象需實現相同接口 |
代理對象創建流程 | 1. 獲取類加載器 2. 獲取接口信息 3. 實現InvocationHandler處理調用邏輯 | InvocationHandler匿名內部類實現是關鍵步驟 |
InvocationHandler作用 | 通過invoke()方法攔截目標方法調用,可插入前置/后置邏輯(如日志) | method.invoke(target,args)反射調用原始方法易遺漏 |
反射調用與動態代理關系 | 動態代理通過反射調用目標方法(method.invoke(target,args)) | 需確保目標類實現接口,否則無法代理 |
匿名內部類應用場景 | 快速實現InvocationHandler接口,避免單獨創建類文件 | 匿名類中訪問外部變量需final修飾(JDK8+隱式支持) |
代理模式優勢 | 解耦核心邏輯與橫切關注點(如日志、事務) | 動態代理 vs 靜態代理(需手動編寫代理類) |
9.動態代理解決問題(2)
知識點 | 核心內容 | 重點 |
動態代理(Proxy)實現原理 | 通過Proxy.newProxyInstance創建代理對象,傳入目標對象和InvocationHandler,代理對象執行方法時會觸發invoke方法 | 編譯類型與運行類型的區別:代理對象編譯類型仍是接口,但運行類型變為$Proxy0等動態生成的代理類 |
代理對象執行流程 | 調用代理對象方法時,先執行InvocationHandler.invoke,再通過反射調用目標對象方法(如ship.run()) | 易混淆點:直接調用目標對象方法不會觸發代理邏輯,必須通過代理對象調用 |
類型判定關鍵代碼 | 通過proxy.getClass()獲取代理對象的運行類型,對比編譯類型(接口)與運行類型($Proxy0) | 重點驗證方法:斷點調試觀察getClass()結果,結合反射驗證方法調用鏈 |
代理模式應用場景 | 演示通過代理對象增強原始方法(如添加“交通工具開始/停止運行”日志) | 典型場景:日志記錄、權限校驗、事務管理(AOP底層實現) |
調試技巧 | 通過斷點+表達式估算(proxy.getClass())觀察運行類型,對比直接調用與代理調用的堆棧差異 | 易錯點:未正確傳入InvocationHandler或目標對象導致代理失效 |
10.動態代理機制Debug(1)
知識點 | 核心內容 | 重點 |
動態代理機制 | 通過Proxy類創建代理對象,代理對象的運行類型決定方法調用路徑 | 運行類型≠編譯類型時方法調用路徑變化 |
反射調用流程 | 通過Method.invoke()實現方法動態調用,最終執行被代理對象的方法 | invoke參數傳遞機制(target對象+arguments數組) |
調試技巧 | 使用step into/step over跟蹤代理調用鏈,需關閉"step into"過濾設置 | IDE調試配置差異導致無法進入JDK源碼的問題 |
動態綁定驗證 | 通過修改被代理對象(Ship→Car)驗證運行時的動態綁定效果 | 代理對象不變情況下僅target對象變化即可改變執行邏輯 |
void方法處理 | 無返回值方法執行后result為null的反射特性 | 基本類型返回值與對象返回值的處理差異 |
11.動態代理機制Debug(2)
知識點 | 核心內容 | 重點 |
動態代理機制 | target對象動態變化:傳入不同對象執行對應方法 方法動態調用:通過代理對象調用的方法會動態傳入 | 代理對象與實際執行對象的映射關系 反射機制在動態代理中的應用 |
方法調用過程 | 包含參數傳遞、返回值處理的完整調用鏈演示 關鍵步驟: 1. 參數類型轉換(int→Integer) 2. 方法反射調用 3. 返回值多層傳遞 | Debug技巧: - 需要兩次step into進入核心邏輯 - 參數傳遞的隱式類型轉換 |
動態性體現 | 1. 被代理對象可替換(Car/Ship) 2. 調用方法可擴展(run/fly) 3. 參數動態傳遞(高度參數) | 代理接口與實現類的松耦合關系 |
調試技巧 | 關鍵斷點: - 方法調用入口 - 參數轉換節點 - 返回值傳遞路徑 特殊操作: - step out后需立即step into | Integer.valueOf的自動裝箱過程 反射調用時的參數封裝 |
框架應用 | MyBatis等框架底層原理: - 動態代理實現接口映射 - 方法攔截與增強 | 動態代理在AOP中的應用場景 |