ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Spring Framework 深度解析:从核心原理到源码实现的全面剖析

Spring Framework 深度解析:从核心原理到源码实现的全面剖析 一、引言Java 生态的基石在 Java 企业级开发领域Spring 早已不是一个框架而是一个生态。从最基础的 IoC 容器到 Spring Boot、Spring CloudSpring 重新定义了 Java 应用的开发方式。Spring Framework的核心定位提供一种轻量级的开发方式将应用程序的各个组件封装为可重用的对象并提供一套容器来管理这些对象的生命周期和依赖关系。Spring 最核心的设计理念可以概括为两点控制反转IoC/依赖注入DI将对象的创建和依赖关系的管理交给容器面向切面编程AOP处理横切关注点日志、事务、安全等它采用分层架构设计核心由七大模块构成Core Container、AOP、Messaging、Data Access/Integration、Web、Test 和 Instrumentation。这些模块通过松耦合方式协同工作开发者可以按需引入。二、IoC 容器Spring 的基石2.1 控制反转的本质控制反转并非具体技术而是一种设计思想。传统编程中调用者需要自行创建被调用者的实例// 传统方式强耦合 public class OrderService { private PaymentService paymentService new PaymentService(); // 手动 new强依赖 }一旦PaymentService更换实现或需要 Mock 测试就必须修改OrderService的代码违反了开闭原则。IoC 的思想正是为了解决这个问题——将对象的创建和绑定过程从代码中剥离交由外部容器统一管理。依赖注入DI是 IoC 的具体实现手段Service public class OrderService { private final PaymentService paymentService; // 构造器注入OrderService 不关心 PaymentService 如何创建 public OrderService(PaymentService paymentService) { this.paymentService paymentService; } }2.2 核心接口BeanFactory 与 ApplicationContextSpring IoC 容器有两个核心接口接口特点适用场景BeanFactory顶层接口延迟加载Bean轻量级资源有限的环境ApplicationContextBeanFactory 的子接口启动时预实例化单例 Bean支持国际化、事件传播等企业级应用最常用ApplicationContext是 Spring 中最常用的 IoC 容器。常见的启动方式包括// XML 配置方式 ApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml); // 纯注解方式Spring Boot 时代最常用 ApplicationContext context new AnnotationConfigApplicationContext(AppConfig.class);2.3 BeanDefinitionBean 的“设计蓝图”BeanDefinition定义了 Bean 的配置元数据包括类名、作用域、依赖关系、初始化方法、销毁方法等。// BeanDefinition 的核心方法源码 public interface BeanDefinition { String getBeanClassName(); void setBeanClassName(String beanClassName); String getScope(); boolean isSingleton(); boolean isPrototype(); boolean isLazyInit(); PropertyValues getPropertyValues(); ConstructorArgumentValues getConstructorArgumentValues(); String[] getDependsOn(); // ... }BeanFactory根据BeanDefinition中的配置信息来创建和管理 Bean 实例。2.4 refresh()容器的启动总入口AbstractApplicationContext#refresh()是 Spring 容器启动的核心方法定义了 IoC 容器的完整启动流程// AbstractApplicationContext.refresh() 源码简化 Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 1. 准备刷新上下文 prepareRefresh(); // 2. 创建并刷新 BeanFactory ConfigurableListableBeanFactory beanFactory obtainFreshBeanFactory(); // 3. 准备 BeanFactory设置类加载器、后置处理器等 prepareBeanFactory(beanFactory); try { // 4. 允许子类对 BeanFactory 进行后置处理 postProcessBeanFactory(beanFactory); // 5. 调用 BeanFactoryPostProcessor invokeBeanFactoryPostProcessors(beanFactory); // 6. 注册 BeanPostProcessorBean 后置处理器 registerBeanPostProcessors(beanFactory); // 7. 初始化 MessageSource国际化 initMessageSource(); // 8. 初始化 ApplicationEventMulticaster事件广播器 initApplicationEventMulticaster(); // 9. 刷新特定子类Spring Boot 在此启动内嵌 Tomcat onRefresh(); // 10. 注册监听器 registerListeners(); // 11. 完成 BeanFactory 初始化实例化所有非延迟加载的单例 Bean finishBeanFactoryInitialization(beanFactory); // 12. 完成刷新发布事件 finishRefresh(); } catch (BeansException ex) { // 异常时销毁已创建的 Bean destroyBeans(); cancelRefresh(ex); throw ex; } } }2.5 Bean 的生命周期Spring Bean 的完整生命周期以AbstractAutowireCapableBeanFactory#doCreateBean()为核心// AbstractAutowireCapableBeanFactory.doCreateBean() 简化流程 protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) { // 1. 实例化 Bean通过反射调用构造器 BeanWrapper instanceWrapper createBeanInstance(beanName, mbd, args); Object bean instanceWrapper.getWrappedInstance(); // 2. 提前暴露解决循环依赖→ 放入三级缓存 addSingletonFactory(beanName, () - getEarlyBeanReference(beanName, mbd, bean)); // 3. 属性填充依赖注入 populateBean(beanName, mbd, instanceWrapper); // 4. 初始化 Bean exposedObject initializeBean(beanName, exposedObject, mbd); // ├── 调用 Aware 方法BeanNameAware、BeanFactoryAware 等 // ├── 调用 BeanPostProcessor.postProcessBeforeInitialization() // ├── 调用 InitializingBean.afterPropertiesSet() // ├── 调用自定义 init-method // └── 调用 BeanPostProcessor.postProcessAfterInitialization() // 5. 注册 DisposableBean销毁时调用 registerDisposableBeanIfNecessary(beanName, bean, mbd); return exposedObject; }关键生命周期节点实例化通过反射创建对象属性填充依赖注入Aware 回调BeanNameAware、BeanFactoryAware等BeanPostProcessor 前置处理初始化InitializingBean 自定义 init 方法BeanPostProcessor 后置处理销毁DisposableBean 自定义 destroy 方法三、三级缓存循环依赖的优雅解法3.1 什么是循环依赖当 A 依赖 BB 又依赖 A 时就形成了循环依赖。Spring 通过三级缓存机制优雅地解决了单例 Bean 的循环依赖问题。3.2 三级缓存的结构核心实现在DefaultSingletonBeanRegistry中public class DefaultSingletonBeanRegistry { // 一级缓存完整单例对象已完全初始化 private final MapString, Object singletonObjects new ConcurrentHashMap(256); // 二级缓存早期暴露对象已实例化但未完成属性填充 private final MapString, Object earlySingletonObjects new ConcurrentHashMap(16); // 三级缓存ObjectFactory 工厂用于生成代理对象 private final MapString, ObjectFactory? singletonFactories new HashMap(16); }3.3 三级缓存的运作流程以 A 依赖 B、B 依赖 A 为例1. 创建 A 实例 → 放入三级缓存singletonFactories2. 填充 A 的属性 → 发现需要 B3. 创建 B 实例 → 放入三级缓存4. 填充 B 的属性 → 发现需要 A5. 从三级缓存获取 A 的 ObjectFactory → 生成 A 的代理对象 → 移入二级缓存6. B 完成初始化 → 放入一级缓存7. A 继续完成初始化 → 从二级缓存获取 A → 放入一级缓存为什么需要三级缓存而不是二级因为 Spring AOP 需要在 Bean 实例化后、但尚未完全初始化前就生成代理对象并提前暴露。ObjectFactory可以在真正需要时才去创建代理实现了延迟生成——这正是三级缓存存在的根本原因。四、AOP面向切面编程4.1 AOP 的核心思想AOPAspect Oriented Programming将横切关注点日志、事务、权限等从业务逻辑中剥离出来通过代理模式实现对目标对象的增强。Spring AOP 的实现依赖于动态代理JDK 动态代理目标类实现接口时使用CGLIB 代理目标类未实现接口时使用生成目标类的子类4.2 代理创建的源码剖析Spring AOP 通过ProxyFactory选择合适的代理方式// AopProxy 的两个实现类 // - JdkDynamicAopProxyJDK 动态代理 // - CglibAopProxyCGLIB 代理JDK 动态代理的核心JdkDynamicAopProxypublic class JdkDynamicAopProxy implements AopProxy, InvocationHandler { Override public Object getProxy(ClassLoader classLoader) { // 通过 JDK Proxy 创建代理对象 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); } Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 1. 获取当前方法对应的拦截器链 ListObject chain this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); if (chain.isEmpty()) { // 无拦截器 → 直接反射调用目标方法 return AopUtils.invokeJoinpointUsingReflection(target, method, args); } // 2. 创建 MethodInvocation执行拦截器链 MethodInvocation invocation new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); return invocation.proceed(); // 依次执行各拦截器前置通知 → 目标方法 → 后置通知 } }4.3 Spring AOP vs AspectJ特性Spring AOPAspectJ实现方式动态代理JDK/CGLIB编译时织入 / 加载时织入性能开销运行时反射调用零运行时开销支持切点方法执行点构造器、字段访问等Spring AOP 的性能损耗主要来自运行时反射调用。在追求极致性能的场景下可以考虑使用 AspectJ 的编译时织入。五、事务管理声明式事务的底层原理5.1 事务管理的两种方式Spring 支持两种事务管理方式编程式事务代码中显式调用PlatformTransactionManager的 API声明式事务通过Transactional注解由 Spring 自动管理推荐5.2 核心组件Spring 事务管理依赖三个核心组件协同工作组件职责PlatformTransactionManager事务管理器策略接口定义事务的基本操作TransactionDefinition封装事务的隔离级别、传播行为等属性TransactionStatus表示当前事务的运行状态5.3 Transactional 的底层实现Transactional的底层原理核心是基于AOP 事务管理器PlatformTransactionManager实现的。TransactionInterceptor是事务管理的核心拦截器// TransactionInterceptor 核心逻辑源码简化 protected Object invokeWithinTransaction(Method method, Class? targetClass, InvocationCallback invocation) { // 1. 获取事务属性从 Transactional 注解中解析 TransactionAttributeSource tas getTransactionAttributeSource(); TransactionAttribute attr tas.getTransactionAttribute(method, targetClass); // 2. 获取 PlatformTransactionManager PlatformTransactionManager ptm determineTransactionManager(attr); // 3. 开启事务 TransactionInfo txInfo createTransactionIfNecessary(ptm, attr, joinpointIdentification); Object retVal null; try { // 4. 调用目标方法执行业务逻辑 retVal invocation.proceedWithInvocation(); } catch (Throwable ex) { // 5. 发生异常 → 根据规则回滚 completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { // 清理事务上下文 cleanupTransactionInfo(txInfo); } // 6. 正常执行 → 提交事务 commitTransactionAfterReturning(txInfo); return retVal; }关键点只有public方法上的Transactional才会生效事务属性查找顺序方法上 → 类上 → 接口上默认情况下RuntimeException和Error触发回滚Exception不会六、Spring Boot 自动配置约定优于配置6.1 自动配置的本质Spring Boot 的自动配置是约定优于配置理念的集中体现。它根据 classpath 中的依赖智能地推断并应用合适的配置引入spring-boot-starter-web→ 自动配置嵌入式 Tomcat、Spring MVC引入spring-boot-starter-data-jpa→ 自动配置数据源、事务管理器6.2 源码剖析EnableAutoConfigurationEnableAutoConfiguration是自动配置的总开关Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) Documented Inherited AutoConfigurationPackage Import(AutoConfigurationImportSelector.class) // 核心 public interface EnableAutoConfiguration { Class?[] exclude() default {}; String[] excludeName() default {}; }Import(AutoConfigurationImportSelector.class)是激活机制的核心。AutoConfigurationImportSelector实现了ImportSelector接口// AutoConfigurationImportSelector 的核心方法简化 public class AutoConfigurationImportSelector implements DeferredImportSelector { Override public String[] selectImports(AnnotationMetadata annotationMetadata) { // 1. 获取所有候选的自动配置类 ListString configurations getCandidateConfigurations(annotationMetadata, attributes); // 2. 过滤根据 Conditional 条件判断 configurations filter(configurations, autoConfigurationMetadata); // 3. 排序AutoConfigureBefore / AutoConfigureAfter configurations sort(configurations); return configurations.toArray(new String[0]); } protected ListString getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { // 从 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports // 或 META-INF/spring.factories 加载自动配置类列表 return ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()) .getCandidates(); } }6.3 Conditional条件化配置自动配置的智能来源于Conditional系列注解注解条件ConditionalOnClassclasspath 中存在指定类ConditionalOnMissingBean容器中不存在指定 BeanConditionalOnProperty配置文件中存在指定属性ConditionalOnWebApplication当前是 Web 环境// 示例DataSourceAutoConfiguration 的部分源码 Configuration(proxyBeanMethods false) ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class }) ConditionalOnMissingBean(type io.r2dbc.spi.ConnectionFactory) public class DataSourceAutoConfiguration { // 只有 classpath 中有 DataSource 且没有 R2DBC ConnectionFactory 时才生效 }七、设计模式在 Spring 中的应用Spring 源码中大量使用了经典设计模式设计模式Spring 中的应用工厂模式BeanFactory、ApplicationContext负责创建和管理 Bean模板方法模式JdbcTemplate、RestTemplate封装资源管理逻辑代理模式AOP 的实现基础JDK 动态代理 / CGLIB单例模式默认 Bean 的作用域观察者模式事件驱动模型ApplicationEvent/ApplicationListener策略模式PlatformTransactionManager支持多种事务实现Spring 的可扩展性是其成功的另一关键——通过接口抽象、回调机制、事件监听等方式提供了丰富的扩展点。八、总结Spring Framework 是 Java 生态中最核心的框架它的设计体现了软件工程的诸多经典思想。维度核心要点IoC 容器BeanFactory→ApplicationContextrefresh()启动流程三级缓存解决循环依赖Bean 生命周期实例化 → 属性填充 → Aware 回调 → 初始化 → 使用 → 销毁AOPJDK 动态代理 CGLIB通过JdkDynamicAopProxy/CglibAopProxy实现事务管理TransactionalTransactionInterceptorPlatformTransactionManagerSpring Boot 自动配置EnableAutoConfigurationAutoConfigurationImportSelectorConditional设计原则开闭原则、依赖倒置、模块化、非侵入式一句话总结Spring 通过 IoC 容器和 AOP 两大支柱以模块化、非侵入式的设计哲学为 Java 企业级开发提供了统一、灵活、可扩展的基础设施。理解 Spring 的源码不仅能帮你写出更高质量的代码更能让你在面对复杂业务场景时知道如何利用 Spring 的扩展点实现定制化需求。
返回列表