一、Spring容器的启动:ApplicationContext的本质
Spring框架的核心是IoC容器,而ApplicationContext是其最常见表现形式。我们通常使用以下两种方式启动Spring容器:
java
// 传统XML配置方式(已逐渐过时)
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
// 现代注解配置方式(Spring Boot默认使用)
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
ApplicationContext在初始化时执行的关键操作:
-
解析配置信息:无论是XML还是注解配置,Spring都会解析配置中的扫描路径、Bean定义等信息
-
扫描并注册Bean定义 :遍历指定包路径下的所有类,识别带有
@Component、@Service等注解的类 -
构建BeanDefinitionMap :将扫描到的类信息以
beanName->BeanDefinition的形式存入Map,为后续Bean创建做准备
二、Bean的生命周期:从创建到销毁的完整旅程
当调用getBean()方法时,Spring会执行一系列复杂的创建流程,完整生命周期包括以下7个关键步骤:
1. 实例化(推断构造方法)
Spring首先需要决定使用哪个构造方法创建对象。其选择逻辑如下:
-
如果类只有一个构造方法(无论是否有参),则使用该构造方法
-
如果类有多个构造方法:
-
存在无参构造方法时,优先使用无参构造
-
不存在无参构造且未明确指定时,Spring会报错
-
如果某个构造方法标注了
@Autowired,则强制使用该构造方法
-
构造方法参数解析机制:
当使用有参构造时,Spring会从容器中查找匹配的Bean作为参数:
-
先按类型查找,找到唯一Bean则直接使用
-
类型匹配多个时,再按参数名确定
-
最终未找到则抛出异常
2. 依赖注入(DI)
实例化后,Spring会检查对象中所有被@Autowired标注的属性,并从容器中查找对应的Bean进行注入。这是控制反转(IoC)思想的核心体现。
3. Aware接口回调
如果Bean实现了BeanNameAware、BeanFactoryAware等Aware接口,Spring会调用相应方法,让Bean感知到自己在容器中的身份。
4. 初始化前(@PostConstruct)
执行被@PostConstruct注解标记的方法,这是Bean初始化前的最后自定义机会。
5. 初始化(InitializingBean)
如果Bean实现了InitializingBean接口,Spring会调用其afterPropertiesSet()方法,完成初始化逻辑。
6. 初始化后(AOP代理)
这是Spring最精妙的环节之一:Spring会判断当前Bean是否需要AOP增强:
-
不需要AOP:Bean创建完成
-
需要AOP:生成代理对象替换原始Bean
7. 单例Bean缓存
-
单例Bean:存入单例池(
SingletonBeanRegistry),后续直接从缓存获取 -
原型Bean:每次
getBean()都执行完整创建流程
三、AOP原理深度剖析:动态代理的魔法
AOP生效条件判断
Spring通过以下流程确定Bean是否需要AOP代理:
-
扫描所有切面Bean(标注
@Aspect的类) -
遍历切面中的通知方法(
@Before、@After等) -
匹配Pointcut表达式与当前Bean类
-
匹配成功则创建代理对象
CGLIB动态代理实现机制
java
// 简化的代理类结构示意
public class UserService$$EnhancerBySpringCGLIB extends UserService {
private UserService target; // 原始被代理对象
public void test() {
// 1. 执行@Before切面逻辑
// 2. 调用target.test()
// 3. 执行@After切面逻辑
}
}
关键点 :从容器中获取的实际上是代理对象,而target属性持有的是完成了依赖注入、初始化的原始对象。
四、Spring事务原理:@Transactional背后的故事
Spring事务基于AOP实现,其执行流程如下:
事务执行步骤
-
注解检测 :判断当前方法是否标注
@Transactional -
连接管理 :从事务管理器获取数据库连接,关闭自动提交(
autocommit=false) -
业务执行:执行原始方法中的SQL操作
-
事务裁决:无异常则提交,有异常则回滚(根据配置决定回滚哪些异常)
事务失效的常见场景
核心原则:事务必须由代理对象调用才生效
-
同一类内方法互相调用(非代理调用)会导致事务失效
-
私有方法上的
@Transactional注解无效 -
异常被捕获未抛出时事务不会回滚
五、总结:Spring设计的精妙之处
通过以上分析,我们可以看出Spring框架设计的几个核心特点:
-
分层设计:将Bean定义、创建、增强、管理各环节解耦
-
扩展性强:通过生命周期回调、Aware接口等提供丰富的扩展点
-
一致性处理:无论XML还是注解配置,底层处理逻辑保持一致
-
代理模式应用:AOP、事务等高级功能都基于动态代理实现,无侵入性增强
理解Spring底层原理不仅有助于解决实际开发中的疑难问题,更能让我们学习到优秀框架的设计思想。后续我们将针对每个模块进行源码级的深度解析,敬请期待!