1. Spring 核心概念
1.1 如何理解 Spring DI?
DI(依賴注入) 是 IoC(控制反轉) 的具體實現方式,由 Spring 容器在運行時通過以下方式自動注入依賴:
構造器注入(推薦)
Setter 注入
字段注入(不推薦,因測試困難)
開發者無需手動
new
依賴對象,降低耦合度。
1.2 基于注解配置作用域與延遲加載
注解 | 作用域示例 | 描述 |
---|---|---|
@Scope | @Scope("singleton") (默認) | 單例模式,全局唯一實例 |
@Scope("prototype") | 每次請求創建新實例 | |
@Scope(value="request") | 每個 HTTP 請求一個實例(Web 環境) | |
@Lazy | @Lazy(true) | 延遲初始化,首次使用時創建 Bean |
示例代碼:
@Component
@Scope("prototype")
@Lazy
public class MyBean { }
1.3 BeanFactory vs ApplicationContext
特性 | BeanFactory | ApplicationContext |
---|---|---|
加載時機 | 懶加載(調用?getBean() ?時) | 預加載(容器啟動時初始化所有單例 Bean) |
高級功能 | 無 | 支持國際化、事件傳播、AOP 等 |
適用場景 | 資源受限環境(如移動設備) | 企業級應用(99% 場景使用) |
1.4 Spring Bean 生命周期
實例化:通過反射創建 Bean 實例。
屬性賦值:DI 注入依賴。
初始化:
調用
@PostConstruct
方法實現
InitializingBean
的afterPropertiesSet()
使用:容器中的 Bean 被調用。
銷毀:
調用
@PreDestroy
方法實現
DisposableBean
的destroy()
1.5 Bean 作用域對比
作用域 | 描述 | 適用場景 |
---|---|---|
singleton | 默認作用域,容器內唯一實例 | 無狀態服務(如工具類、DAO) |
prototype | 每次請求創建新實例 | 有狀態對象(如用戶會話) |
request | 每個 HTTP 請求一個實例(Web 環境) | 表單數據、請求級緩存 |
session | 每個 HTTP Session 一個實例 | 用戶登錄狀態、購物車 |
application | 整個 Web 應用共享一個實例(ServletContext) | 全局配置、緩存 |
1.6 設計模式應用
模式 | 示例 |
---|---|
工廠模式 | BeanFactory ?創建 Bean 實例 |
單例模式 | 默認作用域?singleton |
代理模式 | AOP 動態代理(JDK/CGLIB) |
觀察者模式 | 事件監聽(ApplicationListener ) |
模板方法模式 | JdbcTemplate 、RestTemplate |
1.7 Controller 并發安全
無狀態設計:避免定義成員變量。
線程安全:所有數據通過方法參數或局部變量傳遞。
示例
@RestController public class SafeController {// 正確:無成員變量@GetMapping("/test")public String test(@RequestParam String param) {return "Result: " + param;} }
2. Spring MVC
2.1 處理流程
DispatcherServlet 接收請求。
HandlerMapping 根據
@RequestMapping
匹配 Controller。HandlerAdapter 調用 Controller 方法。
Controller 返回
ModelAndView
或 JSON(@ResponseBody
)。ViewResolver 解析視圖(如 JSP、Thymeleaf)。
渲染視圖 并返回響應。
2.2 與 AJAX 交互
后端:使用
@RestController
+@ResponseBody
返回 JSON。前端:AJAX 請求示例(jQuery)
$.get("/api/user/1", function(data) {console.log(data.name); });
2.3 與 Struts2 對比
特性 | Spring MVC | Struts2 |
---|---|---|
控制器 | 單例(線程安全) | 多例(每個請求一個 Action) |
配置 | 注解驅動(零 XML) | 基于 XML 和 OGNL |
性能 | 更高(無攔截器棧) | 較低(復雜 OGNL 解析) |
生態 | 與 Spring Boot 無縫集成 | 社區已停滯 |
3. Spring 事務管理
3.1 兩種方式對比
方式 | 優點 | 缺點 |
---|---|---|
聲明式 | 零侵入(@Transactional ) | 學習 AOP 和配置復雜 |
編程式 | 精確控制(TransactionTemplate ) | 代碼冗余、維護困難 |
3.2 優勢
傳播行為:支持
REQUIRED
、REQUIRES_NEW
等 7 種策略。隔離級別:
READ_COMMITTED
、SERIALIZABLE
等。多技術兼容:統一 JDBC、JPA、Hibernate 事務。
測試支持:測試時自動回滾(
@Rollback
)。
4. MyBatis
4.1 動態 SQL 解決的問題
SQL 注入:
#{}
預編譯參數(如#{id}
)。代碼冗余:
<if>
、<choose>
等標簽動態拼接 SQL。復雜查詢:
<foreach>
處理IN
語句。
示例:
<select id="findUser" resultType="User">SELECT * FROM user<where><if test="name != null">AND name = #{name}</if></where>
</select>
4.2 緩存機制
類型 | 范圍 | 生命周期 | 配置方式 |
---|---|---|---|
一級緩存 | SqlSession | 同一會話內有效,默認開啟 | 無需配置 |
二級緩存 | Mapper | 跨 SqlSession,需手動開啟 | <cache/> ?或注解?@CacheNamespace |
4.3 接口綁定
原理:通過 JDK 動態代理為 Mapper 接口生成實現類。
好處:
SQL 與 Java 代碼分離(XML 或注解)。
無需手動實現 DAO(如 JDBC 模板)。
支持動態 SQL 和結果映射。
4.4 JDBC 不足與 MyBatis 解決
JDBC 問題 | MyBatis 解決方案 |
---|---|
冗余代碼 | 封裝模板(SqlSessionTemplate ) |
手動事務管理 | 集成 Spring 聲明式事務 |
無連接池 | 集成 HikariCP、Druid |
手動 ORM | 自動結果映射(@Results ) |
4.5 優缺點
優點 | 缺點 |
---|---|
SQL 可控性強 | 需手寫 SQL |
輕量級(無過度封裝) | 二級緩存配置復雜 |
性能優化友好(如延遲加載) | XML 配置繁瑣(可用注解) |
5. Shiro 權限管理
5.1 認證與授權流程
認證:
Subject.login()
提交憑證(如用戶名/密碼)。Realm.doGetAuthenticationInfo()
驗證身份。成功后將用戶信息存入
Session
。
授權:
Realm.doGetAuthorizationInfo()
加載角色和權限。通過注解
@RequiresRoles("admin")
或標簽<shiro:hasPermission>
校驗權限。
6. 其他常見問題
6.1 Bean 工廠底層機制
反射:通過
Class.forName()
實例化 Bean。工廠模式:
BeanFactory
管理對象生命周期。動態代理:AOP 生成代理對象(JDK/CGLIB)。
資源釋放:調用
DisposableBean.destroy()
或@PreDestroy
避免內存泄漏。
6.2 內存泄漏
定義:已分配內存無法被 GC 回收(如未關閉的
Connection
、ThreadLocal
未清理)。預防:使用 try-with-resources、Spring 的
DisposableBean