Spring培训入门到精通源码拆解
配置环境就卡半天,JDK版本冲突、Maven依赖地狱、端口被占用,这是无数人从Spring培训入门到精通路上最大的拦路虎。别急,今天咱们不聊虚的,直接扒开Spring Framework的源码底裤,看看它是怎么把Bean管理得井井有条的。
很多初学者觉得Spring是黑盒,觉得只要会写注解就行。但真正想从入门到精通,必须得懂它背后的ApplicationContext是怎么工作的。我见过太多人在Stack Overflow上问“为什么我的Bean没被注入”,结果一查源码,发现是BeanFactory的初始化顺序出了问题。
入口定位:一切始于refresh
Spring IoC容器的核心是ApplicationContext,但它的所有功能都建立在refresh()方法上。这是整个Spring生命周期中最重头戏的部分。
当你调用new ClassPathXmlApplicationContext("applicationContext.xml")时,底层其实调用了AbstractApplicationContext的refresh()方法。这个方法负责加载配置、创建Bean工厂、预实例化单例Bean等关键任务。
// 源码位置: org.springframework.context.support.AbstractApplicationContext
@Override
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// 1. 准备刷新环境,设置active状态,加载属性源prepareRefresh();// 2. 获取BeanFactory,这是核心中的核心ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 3. 配置BeanFactory,注册BeanPostProcessorsprepareBeanFactory(beanFactory);try {// 4. 执行BeanFactoryPostProcessors,处理@PropertySource等postProcessBeanFactory(beanFactory);// 5. 注册BeanPostProcessors,处理@Autowired等registerBeanPostProcessors(beanFactory);// 6. 初始化MessageSourceinitMessageSource(beanFactory);// 7. 注册应用事件监听器initApplicationEventMulticaster(beanFactory);// 8. 执行剩余BeanFactoryPostProcessorsonRefresh();// 9. 注册监听器registerListeners();// 10. 实例化所有非懒加载的单例BeanfinishBeanFactoryInitialization(beanFactory);// 11. 触发ContextRefreshedEventfinishRefresh();} catch (BeansException ex) {if (logger.isErrorEnabled()) {logger.error("Exception during context initialization: cancelling refresh attempt", ex);}// 取消已创建的Bean,防止脏数据destroyBeans();cancelRefresh(ex);throw ex;} finally {resetCommonCaches();}}
}
逐行解读:
- Line 1-2:
synchronized保证线程安全,防止并发刷新导致状态混乱。 - Line 5:
prepareRefresh()会检查active标志,确保容器处于可启动状态,并初始化environment,这是后续读取配置文件的基础。 - Line 8:
obtainFreshBeanFactory()是关键。它会销毁旧的BeanFactory,然后创建新的。如果是AnnotationConfigApplicationContext,这里会扫描@Component类。 - Line 11:
prepareBeanFactory()配置了BeanFactory的基本属性,比如类加载器、SpEL表达式解析器、BeanPostProcessor注册器等。 - Line 14:
postProcessBeanFactory()执行BeanFactoryPostProcessor接口实现类。这一步很重要,比如PropertySourcesPlaceholderConfigurer就是在这里把@Value("${xxx}")替换成实际值的。 - Line 17:
registerBeanPostProcessors()注册所有实现了BeanPostProcessor接口的Bean。AutowiredAnnotationBeanPostProcessor就是在这里注册的,它负责处理@Autowired、@Value等注解。 - Line 26:
onRefresh()是模板方法,子类可以重写。比如WebApplicationContext会在这里初始化Servlet上下文。 - Line 32:
finishBeanFactoryInitialization(beanFactory)是最耗时的一步。它会获取所有单例Bean的名称,然后逐个调用getBean()进行实例化。 - Line 35:
finishRefresh()触发ContextRefreshedEvent,通知监听器容器已经就绪。
核心片段:Bean的出生与注入
理解了refresh()流程,我们再深入看一个Bean是怎么被创建和注入的。以@Autowired为例,它的核心处理类是AutowiredAnnotationBeanPostProcessor。
// 源码位置: org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {injectBeans(bean, beanName);return bean;
}private void injectBeans(Object bean, String beanName) {// 获取Bean定义BeanDefinition beanDefinition = getBeanDefinition(beanName);// 查找所有带有@Autowired注解的字段和方法Map<String, Field> autowiredFields = findAutowiringCandidates(bean, null, Field.class);Map<String, Method> autowiredMethods = findAutowiringCandidates(bean, null, Method.class);// 处理字段注入for (Map.Entry<String, Field> entry : autowiredFields.entrySet()) {Field field = entry.getValue();Object dependency = resolveDependency(field, beanName);ReflectionUtils.makeAccessible(field);ReflectionUtils.setField(field, bean, dependency);}// 处理方法注入for (Map.Entry<String, Method> entry : autowiredMethods.entrySet()) {Method method = entry.getValue();Object[] args = resolveMethodArguments(method, beanName);ReflectionUtils.makeAccessible(method);ReflectionUtils.invokeMethod(method, bean, args);}
}
逐行解读:
- Line 2-5:
postProcessBeforeInitialization是BeanPostProcessor接口的一个回调方法,在Bean实例化之后、初始化之前调用。 - Line 8:
getBeanDefinition获取Bean的定义元数据,包括类名、作用域等信息。 - Line 11-12:
findAutowiringCandidates扫描类中的所有字段和方法,找出带有@Autowired、@Value等注解的成员。 - Line 15-19: 遍历字段,对每个字段调用
resolveDependency从容器中查找依赖,然后使用反射设置字段值。 - Line 22-26: 类似地处理方法注入,调用
resolveMethodArguments获取参数,然后调用方法。
注意:resolveDependency内部会调用beanFactory.resolveDependency,它会查找候选者、应用@Qualifier、处理@Primary等复杂逻辑。
设计思想:控制反转的本质
Spring的核心思想是控制反转(IoC)和依赖注入(DI)。传统写法中,对象自己创建依赖:
class OrderService {private UserDAO userDAO = new UserDAOImpl(); // 硬编码依赖
}
Spring的做法是:
class OrderService {@Autowiredprivate UserDAO userDAO; // 由容器注入
}
这种设计的优势在于:
- 解耦:
OrderService不再关心UserDAO的具体实现,只关心接口。 - 可测试性:在单元测试中,可以轻松替换为Mock对象。
- 灵活性:可以通过配置文件或注解动态切换实现类,无需修改代码。
从源码角度看,Spring通过BeanFactory实现了IoC。BeanFactory是一个工厂,它知道如何创建每一个Bean,包括它们的依赖关系。ApplicationContext扩展了BeanFactory,增加了事件发布、国际化、资源加载等功能。
关键设计模式:
- 工厂模式:
BeanFactory作为Bean的工厂。 - 代理模式:
AopContext使用动态代理实现AOP。 - 模板方法模式:
AbstractApplicationContext.refresh()定义了骨架,子类可以扩展特定步骤。
手写简化版:理解核心逻辑
为了真正理解Spring的精髓,我们可以手写一个极简版的IoC容器。
import java.util.HashMap;
import java.util.Map;public class SimpleIoCContainer {// 存储Bean定义private Map<String, Object> beanDefinitions = new HashMap<>();// 存储已实例化的单例Beanprivate Map<String, Object> singletonObjects = new HashMap<>();public void registerBean(String name, Class<?> clazz) {beanDefinitions.put(name, clazz);}public Object getBean(String name) {// 1. 检查是否已存在单例if (singletonObjects.containsKey(name)) {return singletonObjects.get(name);}// 2. 获取Bean定义Object beanDefinition = beanDefinitions.get(name);if (beanDefinition == null) {throw new RuntimeException("Bean not found: " + name);}// 3. 实例化Bean(简化版,不支持依赖注入)Object bean = instantiate((Class<?>) beanDefinition);// 4. 存入单例池singletonObjects.put(name, bean);return bean;}private Object instantiate(Class<?> clazz) {try {return clazz.getDeclaredConstructor().newInstance();} catch (Exception e) {throw new RuntimeException("Failed to instantiate " + clazz.getName(), e);}}public static void main(String[] args) {SimpleIoCContainer container = new SimpleIoCContainer();container.registerBean("userService", UserService.class);UserService userService = (UserService) container.getBean("userService");System.out.println(userService);}
}
这个简化版实现了基本的单例管理。真正的Spring还要处理依赖注入、作用域、AOP、事务等复杂功能。但核心思想是一致的:由容器统一管理对象的创建和生命周期。
应用场景:从入门到精通的关键
理解了源码,你就能更好地应对各种场景:
- 调试Bean未注入问题:检查
BeanPostProcessor是否正确注册,检查@Autowired字段是否被扫描到。 - 性能优化:
finishBeanFactoryInitialization是性能瓶颈,可以开启懒加载(lazy-init="true")减少启动时间。 - 自定义扩展:通过实现
BeanPostProcessor或BeanFactoryPostProcessor,可以自定义Bean的处理逻辑。例如,加密敏感信息、注入动态配置等。 - 微服务架构:Spring Cloud基于Spring IoC,通过
@FeignClient、@HystrixCommand等注解,实现了服务调用、熔断、限流等功能。理解IoC底层,才能深刻理解这些高级特性。
避坑指南:
- 循环依赖:Spring通过三级缓存解决A→B→A的循环依赖。理解这个机制,能帮你避免设计上的死循环。
- 懒加载陷阱:懒加载虽然能加快启动速度,但会推迟错误发现。生产环境慎用。
- 线程安全:
BeanFactory本身是线程安全的,但Bean实例不一定是。单例Bean如果有状态,需要额外处理。
Spring源码博大精深,不可能一次吃透。但从refresh()方法入手,逐步深入BeanFactory、BeanPostProcessor,你就能建立起完整的知识体系。
还有什么不懂的?评论区留言挨个回