写在前面
作为一个 Java 后端开发,你每天都在用 Spring,但你真的理解它吗?
-
为什么在类上加个 @Component 注解,Spring 就能自动创建对象?
-
为什么在方法上加个 @Transactional,方法执行失败就会自动回滚?
-
为什么 @Autowired 能自动注入依赖,背后到底发生了什么?
今天,我们深入 Spring 源码,揭开这三大核心机制的神秘面纱:
-
IoC 容器: Bean 的生命周期、循环依赖、三级缓存
-
AOP 实现: 动态代理、切面织入、拦截器链
-
事务传播: 七种传播行为、底层实现原理
准备好了吗?让我们开始这场源码探险!
一、IoC 容器:Spring 的"心脏"
1.1 核心问题:Spring 如何管理对象?
传统方式:手动 new 对象
public class OrderService {
private UserService userService = new UserService(); // 强耦合
private ProductService productService = new ProductService();
}
问题:
-
对象创建逻辑散落各处
-
难以替换实现(比如测试时替换为 Mock)
-
对象生命周期难以管理
Spring 的解决方案:IoC(控制反转)
@Service
public class OrderService {
@Autowired
private UserService userService; // Spring 自动注入
@Autowired
private ProductService productService;
}
核心思想: 把对象的创建和依赖关系的管理交给 Spring 容器,你只管用!
1.2 Spring IoC 容器的核心接口
Spring IoC 容器的设计是典型的分层架构:
BeanFactory (最顶层接口)
↓
ApplicationContext (扩展接口,增加了更多企业级特性)
↓
AnnotationConfigApplicationContext (基于注解的实现)
ClassPathXmlApplicationContext (基于 XML 的实现)
核心接口:BeanFactory
public interface BeanFactory {
Object getBean(String name); // 根据名称获取 Bean
<T> T getBean(Class<T> requiredType); // 根据类型获取 Bean
boolean containsBean(String name); // 是否包含某个 Bean
}
扩展接口:ApplicationContext
public interface ApplicationContext extends BeanFactory {
// 继承了 BeanFactory 的所有能力,并新增:
// 1. 事件发布机制
// 2. 国际化支持
// 3. 资源加载
// 4. 环境抽象
}
1.3 Bean 的完整生命周期(源码级解析)
这是面试高频问题!完整的 Bean 生命周期有 11 个步骤:
1. 实例化 Bean (createBeanInstance)
↓
2. 设置属性值 (populateBean)
↓
3. 调用 BeanNameAware.setBeanName()
↓
4. 调用 BeanFactoryAware.setBeanFactory()
↓
5. 调用 ApplicationContextAware.setApplicationContext()
↓
6. 调用 BeanPostProcessor.postProcessBeforeInitialization() (前置处理)
↓
7. 调用 @PostConstruct 注解的方法
↓
8. 调用 InitializingBean.afterPropertiesSet()
↓
9. 调用 init-method 指定的方法
↓
10. 调用 BeanPostProcessor.postProcessAfterInitialization() (后置处理)
↓
11. Bean 可以使用了
↓
12. 容器关闭时,调用 @PreDestroy、DisposableBean.destroy()、destroy-method
核心源码:AbstractAutowireCapableBeanFactory.doCreateBean()
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) {
// 1. 实例化 Bean
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
Object bean = instanceWrapper.getWrappedInstance();
// 2. 属性注入
populateBean(beanName, mbd, instanceWrapper);
// 3. 初始化 Bean(执行各种 Aware 接口、@PostConstruct、init-method)
Object exposedObject = initializeBean(beanName, bean, mbd);
return exposedObject;
}
1.4 循环依赖问题:三级缓存的精妙设计
场景重现:
@Service
public class A {
@Autowired
private B b; // A 依赖 B
}
@Service
public class B {
@Autowired
private A a; // B 依赖 A
}
问题: A 需要 B,B 需要 A,谁先创建?这就是经典的循环依赖!
Spring 的解决方案:三级缓存
public class DefaultSingletonBeanRegistry {
// 一级缓存:成品 Bean(完全初始化完成)
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 二级缓存:半成品 Bean(实例化完成,但属性未注入)
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
// 三级缓存:Bean 工厂(用于生成代理对象)
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
}
解决流程(以 A、B 循环依赖为例):
1. 创建 A:
- 实例化 A(此时 A 是半成品,属性 b 为 null)
- 将 A 的工厂放入三级缓存
- 开始注入属性 b
2. 创建 B:
- 实例化 B(此时 B 是半成品,属性 a 为 null)
- 将 B 的工厂放入三级缓存
- 开始注入属性 a
3. 注入 A 到 B:
- 从三级缓存中获取 A 的工厂
- 调用工厂创建 A 的早期引用(可能是代理对象)
- 将早期引用放入二级缓存
- 注入到 B 的属性 a
4. B 创建完成:
- 将 B 从三级缓存移除
- 将 B 放入一级缓存
5. 继续创建 A:
- 注入 B 到 A 的属性 b(B 已在一级缓存中)
- A 创建完成,移入一级缓存
为什么需要三级缓存?
-
一级缓存不够? 无法解决循环依赖(A 需要 B,但 A 还没创建完)
-
二级缓存不够? 无法处理 AOP 代理(需要提前暴露代理对象)
-
三级缓存: 延迟创建代理对象,只有在循环依赖时才提前创建代理
核心源码:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 1. 先从一级缓存获取(成品)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 2. 从二级缓存获取(半成品)
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// 3. 从三级缓存获取工厂,创建早期引用
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject(); // 可能返回代理对象
// 放入二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
// 从三级缓存移除
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
1.5 @Autowired 注入原理
核心问题:Spring 如何知道哪些字段需要注入?
答案: AutowiredAnnotationBeanPostProcessor(后置处理器)
执行流程:
1. 扫描类,找到所有 @Autowired 注解的字段/方法
↓
2. 将注入点信息缓存(InjectionMetadata)
↓
3. 在 Bean 初始化时,调用 postProcessProperties()
↓
4. 根据类型从容器中查找 Bean
↓
5. 通过反射设置字段值
简化源码:
public class AutowiredAnnotationBeanPostProcessor {
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 1. 获取需要注入的元数据
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
// 2. 执行注入
metadata.inject(bean, beanName, pvs);
return pvs;
}
private void inject(Object target, String beanName, PropertyValues pvs) {
Field field = ...; // 获取字段
// 3. 从容器中解析依赖
Object value = resolveFieldValue(field, target, beanName);
// 4. 反射设置值
ReflectionUtils.makeAccessible(field);
field.set(target, value);
}
}
二、AOP 实现:方法拦截的魔法
2.1 AOP 的核心概念
业务场景:
public class OrderService {
public void createOrder() {
// 1. 记录日志
// 2. 开启事务
// 3. 业务逻辑
// 4. 提交事务
// 5. 记录日志
}
}
问题: 日志、事务这些横切关注点散落在各个方法中,代码重复、难以维护。
AOP 的解决方案:
@Aspect
@Component
public class LogAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("方法执行前");
Object result = joinPoint.proceed(); // 执行目标方法
System.out.println("方法执行后");
return result;
}
}
五大核心概念:
-
Aspect(切面): 横切关注点的模块化(如日志切面、事务切面)
-
Join Point(连接点): 程序执行的某个点(如方法调用)
-
Pointcut(切点): 匹配连接点的表达式(决定在哪些方法上应用)
-
Advice(通知): 在切点执行的代码(Before、After、Around 等)
-
Weaving(织入): 将切面应用到目标对象的过程
2.2 动态代理:AOP 的底层实现
Spring AOP 底层有两种代理方式:
| 代理方式 | 使用场景 | 优缺点 |
| JDK 动态代理 | 目标类实现了接口 | 只能代理接口方法 |
| CGLIB 代理 | 目标类没有接口 | 通过子类继承,不能代理 final 方法 |
JDK 动态代理示例:
public class JdkProxyFactory implements InvocationHandler {
private Object target;
public Object getProxy(Object target) {
this.target = target;
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法执行前");
Object result = method.invoke(target, args); // 调用真实方法
System.out.println("方法执行后");
return result;
}
}
CGLIB 代理示例:
public class CglibProxyFactory implements MethodInterceptor {
public Object getProxy(Class<?> clazz) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz); // 设置父类
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) {
System.out.println("方法执行前");
Object result = proxy.invokeSuper(obj, args); // 调用父类方法
System.out.println("方法执行后");
return result;
}
}
2.3 Spring AOP 创建代理的时机
核心问题:什么时候创建代理对象?
答案: 在 Bean 初始化的后置处理阶段!
还记得 Bean 生命周期的第 10 步吗?BeanPostProcessor.postProcessAfterInitialization()
核心类:AbstractAutoProxyCreator
public abstract class AbstractAutoProxyCreator implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
// 1. 判断是否需要代理(是否匹配切点表达式)
if (shouldProxy(bean, beanName)) {
// 2. 获取所有匹配的 Advisor(包含 Pointcut + Advice)
Object[] advisors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName);
// 3. 创建代理对象
return createProxy(bean.getClass(), beanName, advisors, bean);
}
return bean; // 不需要代理,返回原对象
}
protected Object createProxy(Class<?> beanClass, String beanName, Object[] advisors, Object target) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvisors(advisors);
// 决定使用 JDK 还是 CGLIB
if (beanClass.isInterface() || hasInterface(beanClass)) {
return proxyFactory.getJdkProxy(); // JDK 动态代理
} else {
return proxyFactory.getCglibProxy(); // CGLIB 代理
}
}
}
2.4 拦截器链的执行流程
场景: 一个方法上有多个切面(事务、日志、权限校验...)
@Transactional
@Log
@CheckPermission
public void createOrder() {
// 业务逻辑
}
执行顺序: Spring 会将所有 Advice 组成一个拦截器链(责任链模式)
1. 事务切面 - Before
↓
2. 日志切面 - Before
↓
3. 权限切面 - Before
↓
4. 执行目标方法
↓
5. 权限切面 - After
↓
6. 日志切面 - After
↓
7. 事务切面 - After
核心源码:ReflectiveMethodInvocation
public class ReflectiveMethodInvocation implements MethodInvocation {
private final List<Object> interceptorsAndDynamicMethodMatchers; // 拦截器链
private int currentInterceptorIndex = -1; // 当前执行到第几个
@Override
public Object proceed() throws Throwable {
// 所有拦截器执行完,调用目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint(); // 反射调用目标方法
}
// 获取下一个拦截器
Object interceptor = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 执行拦截器(拦截器内部会再次调用 proceed(),形成递归)
return ((MethodInterceptor) interceptor).invoke(this);
}
}
执行原理(递归调用):
// 第一个拦截器
public Object invoke(MethodInvocation invocation) {
doBefore(); // 前置通知
Object result = invocation.proceed(); // 递归调用下一个拦截器
doAfter(); // 后置通知
return result;
}
三、事务传播机制:嵌套事务的艺术
3.1 核心问题:事务方法互相调用怎么办?
场景 1:转账 + 记录日志
@Transactional
public void transfer(String from, String to, BigDecimal amount) {
deductBalance(from, amount); // 扣款
addBalance(to, amount); // 加款
logTransfer(from, to, amount); // 记录日志(这个失败了不应该回滚转账!)
}
场景 2:批量插入
@Transactional
public void batchInsert(List<User> users) {
for (User user : users) {
saveUser(user); // 一个失败,其他还要不要保存?
}
}
问题核心: 内部方法的事务该如何处理?
3.2 七种事务传播行为
| 传播行为 | 说明 | 使用场景 |
| REQUIRED (默认) | 如果有事务,加入;没有则新建 | 99% 的场景 |
| REQUIRES_NEW | 总是新建事务,挂起当前事务 | 日志记录(失败不影响主业务) |
| NESTED | 嵌套事务,外部回滚,内部也回滚;内部回滚,外部可捕获异常决定 | 批量操作(部分失败) |
| SUPPORTS | 有事务就用,没有就不用 | 查询方法 |
| NOT_SUPPORTED | 以非事务方式执行,挂起当前事务 | 不需要事务的操作 |
| MANDATORY | 必须在事务中执行,否则抛异常 | 强制事务约束 |
| NEVER | 不能在事务中执行,否则抛异常 | 禁止事务的操作 |
3.3 实战案例:REQUIRED vs REQUIRES_NEW
REQUIRED(默认):
@Service
public class OrderService {
@Autowired
private LogService logService;
@Transactional(propagation = Propagation.REQUIRED)
public void createOrder() {
// 插入订单
orderRepository.save(order);
// 记录日志(加入当前事务)
logService.log("订单创建"); // 如果这里抛异常,订单也会回滚!
}
}
@Service
public class LogService {
@Transactional(propagation = Propagation.REQUIRED)
public void log(String message) {
logRepository.save(message);
throw new RuntimeException("日志失败"); // 导致整个事务回滚
}
}
REQUIRES_NEW(日志不影响主业务):
@Service
public class LogService {
@Transactional(propagation = Propagation.REQUIRES_NEW) // 新建独立事务
public void log(String message) {
logRepository.save(message);
throw new RuntimeException("日志失败"); // 只回滚日志,不影响订单
}
}
@Service
public class OrderService {
@Transactional
public void createOrder() {
orderRepository.save(order);
try {
logService.log("订单创建"); // 独立事务
} catch (Exception e) {
// 捕获异常,订单事务不受影响
}
}
}
3.4 NESTED:嵌套事务的精妙设计
场景:批量导入用户,部分失败不影响其他
@Service
public class UserService {
@Transactional
public void batchImport(List<User> users) {
int successCount = 0;
for (User user : users) {
try {
saveUser(user); // 嵌套事务
successCount++;
} catch (Exception e) {
log.error("用户 {} 导入失败", user.getName(), e);
// 继续处理下一个用户
}
}
log.info("成功导入 {} 个用户", successCount);
}
@Transactional(propagation = Propagation.NESTED)
public void saveUser(User user) {
// 验证用户
if (user.getAge() < 0) {
throw new IllegalArgumentException("年龄不能为负数");
}
// 保存用户
userRepository.save(user);
}
}
NESTED 的特点:
-
内部事务回滚不影响外部(通过 Savepoint 实现)
-
外部事务回滚会影响内部
-
底层原理: 数据库的 Savepoint 机制
-- 外部事务开始
BEGIN;
-- 设置保存点
SAVEPOINT sp1;
-- 内部事务操作
INSERT INTO user ...;
-- 内部事务失败,回滚到保存点
ROLLBACK TO sp1;
-- 继续外部事务
INSERT INTO user ...;
-- 外部事务提交
COMMIT;
3.5 事务传播的底层实现
核心类:TransactionInterceptor
public class TransactionInterceptor extends TransactionAspectSupport {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
// 1. 获取目标类和方法
Class<?> targetClass = invocation.getThis().getClass();
Method method = invocation.getMethod();
// 2. 执行事务逻辑
return invokeWithinTransaction(method, targetClass, invocation::proceed);
}
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, InvocationCallback invocation) {
// 3. 获取事务属性(传播行为、隔离级别等)
TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
// 4. 获取事务管理器
PlatformTransactionManager tm = determineTransactionManager(txAttr);
// 5. 根据传播行为决定如何处理事务
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal;
try {
// 6. 执行目标方法
retVal = invocation.proceedWithInvocation();
} catch (Throwable ex) {
// 7. 异常时回滚
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
} finally {
cleanupTransactionInfo(txInfo);
}
// 8. 成功时提交
commitTransactionAfterReturning(txInfo);
return retVal;
}
}
核心方法:handleExistingTransaction(处理已存在的事务)
private TransactionStatus handleExistingTransaction(TransactionAttribute definition, Object transaction) {
// REQUIRES_NEW:挂起当前事务,创建新事务
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
SuspendedResourcesHolder suspendedResources = suspend(transaction); // 挂起
TransactionStatus status = startTransaction(definition, transaction); // 新建
return status;
}
// NESTED:创建保存点
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
Object savepoint = transaction.createSavepoint(); // 设置保存点
return prepareTransactionStatus(definition, transaction, false, savepoint);
}
// REQUIRED:加入当前事务
return prepareTransactionStatus(definition, transaction, false, null);
}
四、Spring 源码调试技巧
4.1 如何调试 Bean 创建过程?
在这些方法上打断点:
1. AbstractApplicationContext.refresh() // 容器启动入口
2. AbstractAutowireCapableBeanFactory.doCreateBean() // Bean 创建
3. AbstractAutowireCapableBeanFactory.populateBean() // 属性注入
4. AbstractAutowireCapableBeanFactory.initializeBean() // 初始化
4.2 如何调试 AOP 代理创建?
1. AbstractAutoProxyCreator.postProcessAfterInitialization() // 代理创建入口
2. ProxyFactory.getProxy() // 代理生成
3. ReflectiveMethodInvocation.proceed() // 拦截器链执行
4.3 如何调试事务传播?
1. TransactionInterceptor.invoke() // 事务拦截入口
2. TransactionAspectSupport.invokeWithinTransaction() // 事务处理
3. AbstractPlatformTransactionManager.getTransaction() // 获取/创建事务
4. DataSourceTransactionManager.doBegin() // 开启事务
五、常见面试题与最佳实践
5.1 高频面试题
Q1:Spring Bean 的作用域有哪些?
-
singleton(默认): 单例,整个容器只有一个实例
-
prototype: 原型,每次获取都创建新实例
-
request: 每个 HTTP 请求一个实例(Web 环境)
-
session: 每个 HTTP Session 一个实例
-
application: 整个 ServletContext 一个实例
Q2:Spring 如何解决循环依赖?
-
通过三级缓存
-
只能解决单例 setter 注入的循环依赖
-
不能解决构造器注入的循环依赖(死循环)
-
不能解决 prototype 作用域的循环依赖
Q3:@Transactional 失效的场景?
-
方法不是 public
-
同类内部调用(this.method())
-
异常被捕获没有抛出
-
抛出的是 checked 异常(需配置 rollbackFor)
-
数据库不支持事务(如 MyISAM)
5.2 最佳实践
1. 避免循环依赖
// ❌ 不推荐:构造器注入导致循环依赖
@Service
public class A {
public A(B b) {}
}
// ✅ 推荐:setter 注入或 @Lazy
@Service
public class A {
@Autowired
@Lazy
private B b;
}
2. 事务方法不要过长
// ❌ 不推荐:事务范围过大
@Transactional
public void longRunningTask()
{
// 大量业务逻辑
complexCalculation(); // 耗时 5 秒
callExternalApi(); // 耗时 3 秒
sendEmail(); // 耗时 2 秒
saveToDatabase(); // 真正需要事务的操作
}
// ✅ 推荐:只在必要的地方加事务
public void longRunningTask() {
complexCalculation();
callExternalApi();
sendEmail();
// 只在数据库操作时开启事务
transactionalService.saveToDatabase();
}
@Service
class TransactionalService {
@Transactional
public void saveToDatabase()
{
// 数据库操作
}
}
3. 合理使用事务传播行为
// ❌ 错误:日志失败导致业务回滚
@Transactional
public void createOrder() {
saveOrder();
logService.log(); // 日志失败,订单也回滚了
}
// ✅ 正确:日志使用独立事务
@Transactional
public void createOrder() {
saveOrder();
try {
logService.logWithNewTransaction(); // REQUIRES_NEW
} catch (Exception e) {
// 日志失败不影响订单
}
}
4. 注意同类调用事务失效
@Service
public class OrderService {
// ❌ 错误:内部调用,事务不生效
public void createOrder() {
this.saveOrder(); // 直接调用,没有走代理
}
@Transactional
public void saveOrder() {
// 事务不生效!
}
// ✅ 解决方案 1:注入自己
@Autowired
private OrderService self;
public void createOrderV2() {
self.saveOrder(); // 通过代理调用
}
// ✅ 解决方案 2:使用 AopContext
public void createOrderV3() {
((OrderService) AopContext.currentProxy()).saveOrder();
}
// ✅ 解决方案 3:拆分到不同类
@Autowired
private OrderRepository orderRepository;
public void createOrderV4() {
orderRepository.saveOrder(); // 调用其他 Bean
}
}
六、进阶话题:从源码中学习设计模式
6.1 Spring 中的设计模式
1. 工厂模式(Factory)
// BeanFactory:创建 Bean 的工厂
public interface BeanFactory {
Object getBean(String name);
}
// 简化版实现
public class SimpleBeanFactory implements BeanFactory {
private Map<String, Object> beanMap = new ConcurrentHashMap<>();
@Override
public Object getBean(String name) {
if (!beanMap.containsKey(name)) {
beanMap.put(name, createBean(name));
}
return beanMap.get(name);
}
}
2. 单例模式(Singleton)
// DefaultSingletonBeanRegistry:单例注册表
public class DefaultSingletonBeanRegistry {
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
public void registerSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
}
}
public Object getSingleton(String beanName) {
return this.singletonObjects.get(beanName);
}
}
3. 代理模式(Proxy)
// AOP 的核心:JDK 动态代理 + CGLIB 代理
public class ProxyFactory {
public Object getProxy() {
if (hasInterface()) {
return createJdkProxy(); // 代理接口
} else {
return createCglibProxy(); // 代理类
}
}
}
4. 模板方法模式(Template Method)
// AbstractApplicationContext:定义容器刷新的模板流程
public abstract class AbstractApplicationContext {
public void refresh() {
// 1. 准备刷新
prepareRefresh();
// 2. 刷新 BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 准备 BeanFactory
prepareBeanFactory(beanFactory);
// 4. 后置处理 BeanFactory(子类扩展点)
postProcessBeanFactory(beanFactory);
// 5. 执行 BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册 BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// 7. 初始化消息源
initMessageSource();
// 8. 初始化事件广播器
initApplicationEventMulticaster();
// 9. 刷新(子类扩展点)
onRefresh();
// 10. 注册监听器
registerListeners();
// 11. 实例化所有单例 Bean
finishBeanFactoryInitialization(beanFactory);
// 12. 完成刷新
finishRefresh();
}
// 子类可以重写的扩展点
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {}
protected void onRefresh() {}
}
5. 观察者模式(Observer)
// Spring 事件机制
public interface ApplicationListener<E extends ApplicationEvent> {
void onApplicationEvent(E event);
}
// 发布事件
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher publisher;
public void createOrder() {
// 业务逻辑
Order order = saveOrder();
// 发布事件
publisher.publishEvent(new OrderCreatedEvent(order));
}
}
// 监听事件
@Component
public class OrderListener implements ApplicationListener<OrderCreatedEvent> {
@Override
public void onApplicationEvent(OrderCreatedEvent event) {
// 发送通知、更新库存等
System.out.println("订单创建成功:" + event.getOrder().getId());
}
}
6. 责任链模式(Chain of Responsibility)
// AOP 拦截器链
public class ReflectiveMethodInvocation {
private List<MethodInterceptor> interceptors;
private int currentIndex = -1;
public Object proceed() {
// 所有拦截器执行完
if (currentIndex == interceptors.size() - 1) {
return invokeTargetMethod();
}
// 执行下一个拦截器
MethodInterceptor interceptor = interceptors.get(++currentIndex);
return interceptor.invoke(this); // 递归调用
}
}
6.2 从 Spring 源码学到的架构思想
1. 面向接口编程
// Spring 大量使用接口定义规范
BeanFactory → ApplicationContext → ConfigurableApplicationContext
// 好处:
// - 易于扩展(新增实现类)
// - 易于测试(Mock 实现)
// - 降低耦合
2. 扩展点设计
// Spring 提供大量扩展点,让框架具备高度可定制性
BeanPostProcessor // Bean 初始化前后扩展
BeanFactoryPostProcessor // BeanFactory 初始化后扩展
ApplicationListener // 事件监听扩展
3. 分层架构
接口层:定义规范(BeanFactory)
↓
抽象层:提供通用实现(AbstractApplicationContext)
↓
实现层:具体实现(AnnotationConfigApplicationContext)
4. 配置与代码分离
// 通过配置驱动,而不是硬编码
@Configuration
public class AppConfig {
@Bean
public DataSource dataSource() {
// 配置数据源
}
}
七、性能优化:Spring 容器调优
7.1 Bean 加载优化
问题: 容器启动慢,几千个 Bean 要加载几分钟?
优化方案 1:懒加载
// 只有在第一次使用时才创建
@Lazy
@Service
public class HeavyService {
// 初始化很重的服务
}
优化方案 2:按需加载
@Configuration
@Profile("dev") // 只在 dev 环境加载
public class DevConfig {
@Bean
public MockService mockService() {
return new MockService();
}
}
优化方案 3:异步初始化
@Component
public class AsyncBeanInitializer implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// 容器启动完成后,异步初始化重型 Bean
CompletableFuture.runAsync(() -> {
heavyService.init();
});
}
}
7.2 AOP 性能优化
问题: 代理对象性能损耗?
对比测试:
// 原始方法调用:100万次 → 50ms
// JDK 代理调用:100万次 → 80ms(性能损耗 60%)
// CGLIB 代理调用:100万次 → 120ms(性能损耗 140%)
优化建议:
-
减少不必要的切面
// ❌ 不推荐:对所有方法都切
@Around("execution(* com.example..*.*(..))")
// ✅ 推荐:只对需要的方法切
@Around("@annotation(com.example.Log)")
-
使用 JDK 代理而不是 CGLIB
// 让目标类实现接口,优先使用 JDK 代理
public interface UserService {
void createUser();
}
@Service
public class UserServiceImpl implements UserService {
@Override
public void createUser() {}
}
-
避免在高频方法上使用 AOP
// ❌ 不要在循环内的方法上加事务
for (int i = 0; i < 10000; i++) {
transactionalService.save(data); // 每次都开启/提交事务
}
// ✅ 批量操作在外层加事务
@Transactional
public void batchSave(List<Data> dataList) {
for (Data data : dataList) {
save(data); // 复用同一个事务
}
}
7.3 事务性能优化
问题 1:事务范围过大
// ❌ 不推荐:事务中包含耗时操作
@Transactional
public void processOrder() {
Order order = saveOrder(); // 50ms
callPaymentApi(); // 3000ms(网络调用)
sendEmail(); // 2000ms(邮件发送)
updateOrderStatus(order); // 50ms
}
// 问题:事务持有数据库连接 5 秒!
优化:缩小事务范围
// ✅ 推荐:只在数据库操作时开启事务
public void processOrder() {
Order order = orderService.saveOrder(); // 事务 1
callPaymentApi();
sendEmail();
orderService.updateOrderStatus(order); // 事务 2
}
问题 2:事务隔离级别过高
// ❌ 不必要的串行化隔离级别
@Transactional(isolation = Isolation.SERIALIZABLE)
public void query() {
// 只是查询,不需要这么高的隔离级别
}
// ✅ 根据业务需求选择合适的隔离级别
@Transactional(isolation = Isolation.READ_COMMITTED)
public void query() {
// 大部分场景用 READ_COMMITTED 足够
}
八、实战案例:手写简易版 Spring
为了加深理解,我们来手写一个简易版的 Spring IoC + AOP:
8.1 简易版 IoC 容器
public class SimpleApplicationContext {
// Bean 容器
private Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
// Bean 定义
private Map<String, BeanDefinition> beanDefinitions = new ConcurrentHashMap<>();
/**
* 注册 Bean 定义
*/
public void register(String beanName, Class<?> beanClass) {
BeanDefinition bd = new BeanDefinition(beanClass);
beanDefinitions.put(beanName, bd);
}
/**
* 获取 Bean
*/
public Object getBean(String beanName) {
// 1. 先从缓存获取
if (singletonObjects.containsKey(beanName)) {
return singletonObjects.get(beanName);
}
// 2. 创建 Bean
BeanDefinition bd = beanDefinitions.get(beanName);
Object bean = createBean(bd);
// 3. 属性注入
populateBean(bean, bd);
// 4. 初始化
initializeBean(bean, beanName);
// 5. 放入缓存
singletonObjects.put(beanName, bean);
return bean;
}
/**
* 创建 Bean 实例
*/
private Object createBean(BeanDefinition bd) {
try {
return bd.getBeanClass().getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException("创建 Bean 失败", e);
}
}
/**
* 属性注入
*/
private void populateBean(Object bean, BeanDefinition bd) {
// 获取所有字段
Field[] fields = bean.getClass().getDeclaredFields();
for (Field field : fields) {
// 查找 @Autowired 注解
if (field.isAnnotationPresent(Autowired.class)) {
String fieldName = field.getName();
Object dependentBean = getBean(fieldName); // 递归获取依赖
// 反射设置值
field.setAccessible(true);
try {
field.set(bean, dependentBean);
} catch (Exception e) {
throw new RuntimeException("属性注入失败", e);
}
}
}
}
/**
* 初始化 Bean
*/
private void initializeBean(Object bean, String beanName) {
// 查找 @PostConstruct 注解的方法
Method[] methods = bean.getClass().getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(PostConstruct.class)) {
method.setAccessible(true);
try {
method.invoke(bean);
} catch (Exception e) {
throw new RuntimeException("初始化方法执行失败", e);
}
}
}
}
}
// Bean 定义
class BeanDefinition {
private Class<?> beanClass;
public BeanDefinition(Class<?> beanClass) {
this.beanClass = beanClass;
}
public Class<?> getBeanClass() {
return beanClass;
}
}
测试:
public class SimpleIoCTest {
public static void main(String[] args) {
SimpleApplicationContext context = new SimpleApplicationContext();
// 注册 Bean
context.register("userService", UserService.class);
context.register("userRepository", UserRepository.class);
// 获取 Bean
UserService userService = (UserService) context.getBean("userService");
userService.createUser();
}
}
class UserService {
@Autowired
private UserRepository userRepository;
@PostConstruct
public void init() {
System.out.println("UserService 初始化完成");
}
public void createUser() {
System.out.println("创建用户");
userRepository.save();
}
}
class UserRepository {
public void save() {
System.out.println("保存到数据库");
}
}
8.2 简易版 AOP
public class SimpleAopProxy {
/**
* 创建代理对象
*/
public static Object createProxy(Object target, MethodInterceptor interceptor) {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
(proxy, method, args) -> {
// 执行拦截器
return interceptor.invoke(new SimpleMethodInvocation(target, method, args));
}
);
}
}
// 方法拦截器
interface MethodInterceptor {
Object invoke(MethodInvocation invocation) throws Throwable;
}
// 方法调用
class SimpleMethodInvocation implements MethodInvocation {
private Object target;
private Method method;
private Object[] args;
public SimpleMethodInvocation(Object target, Method method, Object[] args) {
this.target = target;
this.method = method;
this.args = args;
}
@Override
public Object proceed() throws Throwable {
return method.invoke(target, args);
}
}
interface MethodInvocation {
Object proceed() throws Throwable;
}
测试:
public class SimpleAopTest {
public static void main(String[] args) {
// 创建目标对象
UserService target = new UserServiceImpl();
// 创建代理对象
UserService proxy = (UserService) SimpleAopProxy.createProxy(target, invocation -> {
System.out.println("方法执行前");
Object result = invocation.proceed();
System.out.println("方法执行后");
return result;
});
// 调用代理对象
proxy.createUser();
}
}
interface UserService {
void createUser();
}
class UserServiceImpl implements UserService {
@Override
public void createUser() {
System.out.println("创建用户");
}
}
九、总结与展望
9.1 核心要点回顾
IoC 容器:
-
Bean 生命周期的 11 个步骤
-
三级缓存解决循环依赖
-
@Autowired 通过 BeanPostProcessor 实现
AOP 实现:
-
JDK 动态代理 vs CGLIB 代理
-
拦截器链的责任链模式
-
代理对象在 Bean 初始化后创建
事务传播:
-
七种传播行为的应用场景
-
REQUIRES_NEW 用于独立事务
-
NESTED 用于嵌套事务(Savepoint)
9.2 学习建议
-
看源码的方法:
-
先理解设计思想,再看实现细节
-
抓住核心流程,忽略边界处理
-
结合断点调试,追踪完整链路
-
-
从 Spring 学习架构设计:
-
面向接口编程
-
提供扩展点
-
分层架构
-
配置与代码分离
-
-
实践出真知:
-
手写简易版 Spring
-
阅读优秀开源项目
-
在实际项目中应用
-
3277

被折叠的 条评论
为什么被折叠?



