深入解析 Spring IOC & AOP:原理、源碼與實戰
Spring 框架的核心在于 IOC(控制反轉) 和 AOP(面向切面編程)。今天,我們將深入剖析它們的原理,結合源碼解析,并通過 Java 代碼實戰來掌握這兩個核心概念。
📌 1. 什么是 IOC(控制反轉)?
IOC(Inversion of Control)是 Spring 的核心思想,它將對象的創建和依賴關系的管理交給 Spring 容器,避免了傳統的 new
關鍵字實例化方式。
🔥 1.1 IOC 機制
Spring 使用 BeanFactory
和 ApplicationContext
管理 Bean 的生命周期,主要流程如下:
- 讀取配置(XML 或注解)
- 實例化 Bean(通過
BeanFactory
) - 依賴注入(通過
@Autowired
) - Bean 生命周期管理
📌 2. 手寫簡易 IOC 容器
我們用 Java 代碼手寫一個簡化版的 IOC 容器,模擬 Spring 依賴注入的實現。
📝 代碼示例:
import java.util.HashMap;
import java.util.Map;// 模擬 Spring 容器
class SimpleIOC {private Map<String, Object> beanContainer = new HashMap<>();// 注冊 Beanpublic void registerBean(String name, Object obj) {beanContainer.put(name, obj);}// 獲取 Beanpublic Object getBean(String name) {return beanContainer.get(name);}
}// 測試 IOC 容器
class UserService {public void sayHello() {System.out.println("Hello, Spring IOC!");}
}public class TestIOC {public static void main(String[] args) {SimpleIOC ioc = new SimpleIOC();ioc.registerBean("userService", new UserService());UserService userService = (UserService) ioc.getBean("userService");userService.sayHello();}
}
🔍 運行結果
Hello, Spring IOC!
? 分析:
SimpleIOC
充當 Spring 容器,存儲和管理 Bean 實例。registerBean()
方法模擬ApplicationContext
注冊 Bean 的功能。getBean()
方法模擬getBean(Class<T> clazz)
獲取對象。
📌 3. 什么是 AOP(面向切面編程)?
AOP(Aspect-Oriented Programming)通過 動態代理 在方法執行前后加入額外邏輯,常用于 日志、事務、權限控制 等場景。
🔥 3.1 AOP 機制
Spring AOP 主要通過 JDK 動態代理(基于接口)和 CGLIB(基于子類)實現。
📖 3.2 Spring AOP 代理模式
Spring AOP 主要使用 代理模式,在目標方法執行前后執行增強邏輯,如:
@Before
(前置通知)@AfterReturning
(后置通知)@Around
(環繞通知)
📌 4. 手寫 AOP 代理(JDK 動態代理)
我們使用 JDK 動態代理 實現 AOP,模擬 Spring @Transactional
事務管理。
📝 代碼示例:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;// 業務接口
interface UserService {void createUser();
}// 業務實現類
class UserServiceImpl implements UserService {public void createUser() {System.out.println("創建用戶...");}
}// AOP 代理類
class AOPProxy implements InvocationHandler {private Object target;public AOPProxy(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("開啟事務...");Object result = method.invoke(target, args);System.out.println("提交事務...");return result;}// 生成代理對象public static Object getProxy(Object target) {return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new AOPProxy(target));}
}// 測試 AOP 代理
public class TestAOP {public static void main(String[] args) {UserService userService = new UserServiceImpl();UserService proxyService = (UserService) AOPProxy.getProxy(userService);proxyService.createUser();}
}
🔍 運行結果
開啟事務...
創建用戶...
提交事務...
? 分析:
AOPProxy
通過 JDK 動態代理 在方法調用前后加入事務邏輯。getProxy()
生成代理對象,并攔截UserService
的方法調用。- 運行后,
createUser()
方法被代理增強,實現 AOP 事務管理功能。
📌 5. Spring AOP 實戰(@Aspect)
在 Spring 中,我們可以使用 @Aspect
和 @Around
注解實現 AOP 事務管理。
📝 代碼示例:
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Aspect
@Component
public class TransactionAspect {@Before("execution(* com.service.*.*(..))")public void beginTransaction() {System.out.println("開啟事務...");}@After("execution(* com.service.*.*(..))")public void commitTransaction() {System.out.println("提交事務...");}
}
🌟 關鍵點
@Aspect
:聲明 AOP 切面類@Before
/@After
:在方法執行前/后執行事務邏輯execution(* com.service.*.*(..))
:匹配com.service
包下的所有方法
📌 6. 總結
功能 | Spring 機制 | 手寫代碼 |
---|---|---|
IOC | 依賴注入(DI) | 手寫 BeanFactory |
AOP | 事務管理、日志 | JDK 動態代理 |
Spring AOP | @Aspect 切面 | @Before 、@After |
? 今日收獲:
- 理解了 IOC 機制,并手寫 IOC 容器
- 掌握了 AOP 代理機制,并手寫 JDK 動態代理
- 結合 Spring @Aspect 注解,掌握 AOP 事務管理
🚀 明日預告:Spring MVC 深度解析(DispatcherServlet、HandlerMapping、攔截器)
🔗 學習資料:
📖 Spring 官方文檔
💬 你對 Spring IOC & AOP 有什么疑問?歡迎留言交流! 🚀