当前位置:首页 > 热点

spring揭秘

Spring 最核心的揭秘竞争力,其实就一句话:它把 Java 企业级开发里最烦人的揭秘那部分——对象创建和依赖管理——从代码里抽走了,交给了容器。揭秘2003 年 Rod Johnson 写那本《Expert One-on-One J2EE Development without EJB》的揭秘时候,EJB 还是揭秘主流,但已经有人受不了那套笨重的揭秘编程模型了。Spring 就是揭秘从那个痛点里长出来的。

我最早接触 Spring 是揭秘 2008 年,当时项目里用 Struts + Hibernate,揭秘配置文件写到吐。揭秘第一次看到 Spring 的揭秘 XML 配置,觉得也没省多少事。揭秘但真正让我改变看法的揭秘是 ApplicationContext 启动时那一套 Bean 生命周期管理——实例化、属性注入、揭秘BeanPostProcessor 前后置处理、揭秘初始化方法回调。这一串流程把对象的创建权和装配权从业务代码手里拿走了,代码里只剩下纯粹的调用关系。

依赖注入是 Spring 的招牌。构造器注入、setter 注入、字段注入,三种方式各有各的坑。字段注入写起来最省事,但测试的时候没法直接 new 出来,得靠反射或者 Spring 容器。构造器注入能保证依赖不为 null,但循环依赖会直接报错。setter 注入介于两者之间,不过现在官方推荐构造器注入,原因很简单:它让对象在创建完成时就处于完整状态。

说到循环依赖,这是面试里绕不开的话题。Spring 用三级缓存来解决单例 Bean 的循环依赖:singletonObjects、earlySingletonObjects、singletonFactories。A 依赖 B,B 依赖 A,容器先创建 A,把 A 的工厂放进三级缓存,然后去创建 B,B 需要 A 的时候从三级缓存里拿到工厂提前生成 A 的早期引用,B 创建完成后 A 再完成属性填充。这套机制只对单例 Bean 有效,原型 Bean 的循环依赖直接抛 BeanCurrentlyInCreationException。

AOP 是另一块硬骨头。Spring AOP 底层用 JDK 动态代理或者 CGLIB。有接口用 JDK 代理,没接口用 CGLIB 生成子类。代理对象在调用目标方法前后插入通知逻辑,@Transactional 就是靠这个实现的。但这里有个经典陷阱:同一个类内部方法调用不走代理,事务注解会失效。我见过不少项目在这上面栽跟头,后来要么用 AopContext.currentProxy(),要么把方法拆到另一个 Bean 里。

Spring Boot 出来以后,配置方式从 XML 全面转向注解和 Java Config。@Configuration 类里用 @Bean 方法声明 Bean,@ComponentScan 自动扫描组件,@EnableAutoConfiguration 根据 classpath 上的依赖自动装配。这套组合拳把 Spring 的上手门槛拉低了一大截。但自动装配也不是没有代价,出问题的时候排查链路变长了,得打开 debug=true 看自动配置报告才能定位到底哪个 AutoConfiguration 生效了。

Spring 的生态已经远远超出了一个 DI 容器的范畴。Spring MVC 处理 Web 请求,Spring Data 统一数据访问,Spring Security 管认证授权,Spring Cloud 搞微服务。但不管上面叠了多少层,底下那套 IoC 容器和 AOP 机制始终是根基。理解了 Bean 的生命周期和代理机制,再看这些上层框架就不会觉得是在看天书。

最后说个实际感受:Spring 的源码值得读,但别一上来就啃 refresh() 方法。从 BeanFactory 和 BeanDefinition 入手,把 getBean() 的主流程跟一遍,比漫无目的地翻源码效率高得多。工具用熟了,原理自然就通了。

分享到: