首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Spring 框架核心原理:IoC 容器與 AOP 如何重塑企業級開發

     編輯:Java 程式設計入門

歷史背景:J2EE 的重與 Spring 的輕

早期 J2EE (EJB 2.x) 以**重量級**著稱:

  • EJB 強制繼承接口、部署描述符 XML 滿天飛、JNDI 查找樣板代碼、容器依賴強綁定。
  • 項目失敗率高,EJB 常成「替罪羊」。社區呼聲:更簡單、少 EJB、POJO 化。
  • 但企業應用仍需**事務、安全、遠程調用、資源管理**等基礎設施服務。

Rod Johnson 在《Expert One-on-One J2EE Design and Development》中展示**輕量級容器原型**,後演進為 Spring Framework:**非侵入式、基於 POJO、IoC + AOP 雙引擎驅動**。

IoC (控制反轉) / DI (依賴注入):核心容器

概念釐清

  • 控制反轉:對象創建、依賴獲取控制權從應用代碼移交給容器。
  • 依賴注入 (Martin Fowler 命名):容器在運行期將依賴關系「注入」組件,而非組件主動查找。
  • 三種注入方式:構造器注入 (強依賴、不可變)、**Setter 注入** (可選依賴、可重配置)、**字段注入** (僅測試/框架內部,生產代碼不推薦)。

Spring IoC 實戰:從 XML 到註解配置

// 1. 接口定義業務契約
public interface Action {
    String execute(String input);
}

// 2. POJO 實現,無任何 Spring 依賴
public class UpperAction implements Action {
    private String message; // 可注入配置
    public void setMessage(String message) { this.message = message; }
    public String execute(String input) {
        return (message + input).toUpperCase();
    }
}

// 3. XML 配置 (早期風格)
<beans>
  <bean id="theAction" class="com.example.UpperAction">
    <property name="message" value="HeLLo"/>
  </bean>
</beans>

// 4. 啟動容器獲取 Bean
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
Action action = ctx.getBean("theAction", Action.class);
System.out.println(action.execute("Rod Johnson")); // HELLO ROD JOHNSON

現代註解驅動配置 (Spring 3+)

@Configuration
@ComponentScan("com.example")
public class AppConfig {
    @Bean
    public Action theAction() {
        UpperAction action = new UpperAction();
        action.setMessage("HeLLo");
        return action;
    }
}

// 或組件掃描 + 注入
@Component
public class UpperAction implements Action {
    @Value("${app.message:HeLLo}")
    private String message;
    // ...
}

@Service
public class BusinessService {
    private final Action action; // 構造器注入,不可變、最終字段
    public BusinessService(Action action) { this.action = action; }
}

IoC 容器優勢總結

  1. 零侵入:業務類無 Spring 依賴,可獨立單元測試、移植。
  2. 解耦:依賴關系外部化配置,實現類可換裝 (如測試用 Mock 實現)。
  3. 生命週期管理:單例/原型/請求/會話作用域、初始化/銷毀回調 (@PostConstruct/@PreDestroy)。
  4. 統一資源注入:DataSource、JmsTemplate、RestTemplate、第三方客戶端統一由容器管理。
  5. 測試友好:@SpringBootTest 載入完整上下文,@MockBean 替換依賴。

AOP (面向切面編程):橫切關注點模塊化

核心概念

術語含義例子
Joinpoint (連接點)程序執行中可插入切面的點方法調用、異常拋出、字段訪問
Pointcut (切入點)匹配連接點的條件表達式execution(* com.example.service.*.*(..))
Advice (通知/增強)在切入點執行的具體邏輯事務開啟、日志記錄、性能計時
Aspect (切面)Pointcut + Advice 的模塊化封裝@Aspect 類
Weaving (織入)將切面應用到目標對象的過程編譯期/類加載期/運行期 (Spring 用運行期代理)

Spring AOP 實現機制:動態代理

  • JDK 動態代理:目標實現接口 → 生成實現同接口的代理類,攔截接口方法調用。
  • CGLIB 代理:目標無接口 → 生成目標子類,重寫非 final 方法。
  • 限制:僅支持**方法級連接點**;final 方法、私有方法、構造器、字段訪問無法攔截 (需 AspectJ 編譯期/類加載期織入)。

通知類型與執行順序

@Aspect
@Component
public class TxAspect {
    @Around("@annotation(Transactional)") // 環繞通知:最強大,可控制是否執行目標、捕獲異常、修改返回值
    public Object manageTransaction(ProceedingJoinPoint pjp) throws Throwable {
        TransactionStatus tx = txManager.getTransaction(new DefaultTransactionDefinition());
        try {
            Object result = pjp.proceed(); // 執行目標方法
            txManager.commit(tx);
            return result;
        } catch (Exception e) {
            txManager.rollback(tx);
            throw e;
        }
    }

    @Before("execution(* *.save*(..))") // 前置通知:目標方法前
    public void logBefore(JoinPoint jp) { log.info("Saving: {}", jp.getSignature()); }

    @AfterReturning(pointcut = "execution(* *.find*(..))", returning = "result")
    public void logAfterReturning(Object result) { log.debug("Found: {}", result); }

    @AfterThrowing(pointcut = "execution(* *.delete*(..))", throwing = "ex")
    public void logAfterThrowing(Exception ex) { log.error("Delete failed", ex); }

    @After("execution(* *.update*(..))") // 後置通知:finally 語義,無論正常/異常
    public void cleanup() { /* 釋放資源 */ }
}

聲明式事務:AOP 最經典應用

@Service
public class AccountService {
    @Transactional(rollbackFor = Exception.class)
    public void transfer(Long from, Long to, BigDecimal amount) {
        accountDao.debit(from, amount);
        accountDao.credit(to, amount);
    }
}
// 無需手動 try-catch-commit/rollback,AOP 透明織入

IoC + AOP = Spring 的有機整體

沒有 IoC 的 AOP 不完善:切面本身是 Bean,需容器管理生命週期、注入依賴 (如 PlatformTransactionManager)。
沒有 AOP 的 IoC 不健壯:事務、安全、緩存等企業級服務無法以聲明式方式應用於 POJO,將退化為樣板代碼散落業務邏輯。

與 EJB 對比:為什麼 Spring 贏了?

維度EJB 2.x/3.xSpring
組件模型重組件 (Session/Entity/Message Bean)POJO + 註解
容器依賴強綁定應用服務器可嵌入 Tomcat/Jetty/Undertow,無容器也能跑
事務管理CMT/BMT,僅限 EJB 方法聲明式 @Transactional,任意 POJO 方法
測試性需容器內測試 (Arquillian) 慢單元測試毫秒級,集成測試秒級
配置方式XML 描述符 (ejb-jar.xml 等)JavaConfig + 註解 + YAML,類型安全
生態擴展標準規範內Spring Boot/Data/Cloud/Security/Batch... 豐富生態

現代 Spring 生態:Boot、Cloud、GraalVM 原生

  • Spring Boot:約定優於配置、自動裝配、內嵌容器、健康檢查、指標暴露,**生產就緒**微服務基石。
  • Spring Cloud:服務發現、配置中心、網關、熔斷、分布式追蹤,**分佈式系統工具箱**。
  • Spring Native / GraalVM:AOT 編譯生成原生镜像,啟動毫秒級、內存極低、**Serverless/雲原生**首選。
  • Reactive (WebFlux):非阻塞背壓流、函數式路由、R2DBC 響應式數據庫訪問,**高併發低延遲**新范式。

總結

Spring 以 **IoC 容器管理對象圖、AOP 織入橫切關注點** 為雙核心,將**企業級基礎設施服務 (事務、安全、緩存、消息) 以聲明式方式應用於純 POJO**。它證明了:輕量級不等於功能輕,而是架構輕、耦合輕、認知輕。從 Rod Johnson 的原型到今日雲原生生態霸主,Spring 始終踐行一個信念:**讓開發者專注業務領域,基礎設施交給框架**。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved