前言
- Spring 框架的兩大核心設計思想是 IOC(控制反轉) 和 AOP(面向切面編程)。
- 它們共同解決了代碼耦合度高、重復邏輯冗余等問題。
IOC(控制反轉)
1.核心概念
- 控制反轉(Inversion of Control):將對象的創建、生命周期管理和依賴關系的控制權從應用程序代碼轉移給外部容器(如 Spring的IOC容器)。
- 依賴注入(Dependency Injection, DI):IOC 的具體實現方式,容器通過構造函數、Setter 方法或字段反射等方式,自動將依賴對象注入到目標對象中。
2.解決的問題
- 傳統開發的問題:對象直接通過 new 創建依賴,導致代碼高度耦合(如 Service 直接依賴 Dao 的具體實現)。
- IOC 的優勢:
- 解耦:對象依賴由容器管理,開發者無需手動處理。
- 靈活配置:通過配置文件或注解動態替換實現類(如切換數據庫驅動)。
- 資源復用:Spring 容器默認以單例模式管理 Bean,減少資源消耗。
3.實現方式
- XML 配置:通過 <bean標簽定義 Bean 及其依賴。
- 注解驅動:如 @Component、@Autowired、@Service 等,簡化配置。
- Java Config:使用 @Configuration 和 @Bean 以編程方式定義 Bean。
4.核心容器
- BeanFactory:基礎容器,提供 Bean 的實例化和依賴注入。
- ApplicationContext:擴展了 BeanFactory,支持國際化、事件傳播、AOP 等高級功能。
AOP(面向切面編程)
1.核心概念
- 橫切關注點(Cross-Cutting Concerns):散布在多個模塊中的公共邏輯(如日志、事務、權限校驗)。
- AOP 的目標:將這些橫切邏輯從業務代碼中剝離,通過動態代理技術織入目標方法,實現代碼復用和解耦。
2.關鍵術語
- 切面(Aspect):封裝橫切邏輯的類(如日志切面)。
- 連接點(JoinPoint):程序執行中的特定位置(如方法調用、異常拋出)。
- 切點(Pointcut):通過表達式匹配需要增強的連接點(如 execution( com.example.service…*(…)))。
- 通知(Advice):
- 前置通知(Before):在目標方法執行前執行。
- 后置通知(After):在目標方法執行后執行(無論是否異常)。
- 返回通知(AfterReturning):在目標方法正常返回后執行。
- 異常通知(AfterThrowing):在目標方法拋出異常后執行。
- 環繞通知(Around):包裹目標方法,可控制其執行過程。
3.實現原理
- JDK 動態代理:基于接口代理,要求目標類實現接口。
- CGLIB 動態代理:通過生成目標類的子類實現代理,適用于無接口的類。
- 織入(Weaving):將切面邏輯與目標類結合的時機,支持編譯期、類加載期和運行期織入。
4.應用場景
- 日志記錄:統一記錄方法入參、出參和執行時間。
- 事務管理:通過 @Transactional 注解實現聲明式事務。
- 權限校驗:在方法執行前檢查用戶權限。
- 接口限流與冪等:防止重復提交或高并發場景下的資源爭搶。
IOC和AOP的協同
- IOC 提供基礎設施:Spring 容器管理 Bean 的創建和依賴,為 AOP 提供代理對象的生成環境。
- AOP 增強 Bean:通過動態代理技術,對容器管理的 Bean 進行功能擴展,實現非侵入式的邏輯增強。
代碼示例
- 傳統代碼(高耦合)
- 當修改了實現類的名稱時,所有代碼中new該對象的地方都要修改,不易于維護
public class UserService {private UserDao userDao = new UserDaoImpl();public void saveUser() {userDao.save();}
}
@Service
public class UserService {@Autowiredprivate UserDao userDao; public void saveUser() {userDao.save();}
}
@Aspect
@Component
public class LogAspect {@Before("execution(* com.example.service.*.*(..))")public void logBefore(JoinPoint joinPoint) {System.out.println("方法執行: " + joinPoint.getSignature().getName());}
}
總結
- IOC 通過控制反轉和依賴注入,解決了對象間的強耦合問題。
- AOP 通過動態代理和切面編程,實現了橫切邏輯的復用和解耦。
- 二者共同構建了 Spring 的輕量級、高擴展性架構,廣泛應用于企業級開發。