控制反转(Inversion of Control, IoC)是 Spring 框架的基石。它将对象创建的主动权从应用代码转移给容器,通过依赖注入(Dependency Injection, DI)实现组件间的松耦合。深入理解 IoC 容器的运作机制,是掌握 Spring 框架的必经之路。
一、IoC 核心原理 1.1 控制反转 vs 依赖注入 传统方式: IoC 方式:
┌───────────┐ ┌───────────┐
│ Service │──new──→│ Dao │ │ Service │←──────│ 容器注入 │
└───────────┘ └───────────┘ └───────────┘ └───────────┘
↑ ↑
主动创建 被动接收
方式 说明 示例 构造器注入 通过构造器传入依赖 推荐(不可变、必填) Setter 注入 通过 setter 方法注入 可选依赖 字段注入 @Autowired 直接标注字段便捷但不推荐
1.2 BeanFactory vs ApplicationContext // BeanFactory:基础 IoC 容器
BeanFactory factory = new XmlBeanFactory ( new ClassPathResource ( "beans.xml" ));
UserService service = factory . getBean ( UserService . class );
// ApplicationContext:高级容器,继承 BeanFactory
ApplicationContext ctx = new AnnotationConfigApplicationContext ( AppConfig . class );
// 额外能力:
// - 国际化(MessageSource)
// - 事件发布(ApplicationEventPublisher)
// - 资源加载(ResourceLoader)
// - 自动后处理(BeanPostProcessor)
特性 BeanFactory ApplicationContext Bean 实例化 延迟加载(Lazy) 预实例化(非 Lazy) 事件发布 不支持 支持 AOP 集成 需手动注册 自动集成 使用场景 资源受限环境 企业级应用(默认)
二、Bean 生命周期 2.1 完整生命周期图 1. 实例化(Instantiation)
└─→ new / 反射 / CGLIB 子类
2. 属性赋值(Populate)
└─→ DI:@Autowired、@Value、@Resource
3. 初始化(Initialization)
├─→ Aware 接口回调(BeanNameAware, ApplicationContextAware...)
├─→ @PostConstruct
├─→ InitializingBean.afterPropertiesSet()
└─→ 自定义 init-method
4. 使用(In Use)
└─→ Bean 处于就绪状态
5. 销毁(Destruction)
├─→ @PreDestroy
├─→ DisposableBean.destroy()
└─→ 自定义 destroy-method
2.2 生命周期代码示例 @Component
public class LifecycleDemoBean implements
BeanNameAware ,
ApplicationContextAware ,
InitializingBean ,
DisposableBean {
@Autowired
private DependencyBean dependency ;
// 1. 构造器(实例化)
public LifecycleDemoBean () {
System . out . println ( "① 构造器:实例化" );
}
// 2. 依赖注入完成后
@Autowired
public void setDependency ( DependencyBean dep ) {
System . out . println ( "② Setter 注入:" + dep );
}
// 3. Aware 接口回调
@Override
public void setBeanName ( String name ) {
System . out . println ( "③ BeanNameAware: " + name );
}
@Override
public void setApplicationContext ( ApplicationContext ctx ) {
System . out . println ( "④ ApplicationContextAware: " + ctx );
}
// 5. @PostConstruct(JSR-250)
@PostConstruct
public void postConstruct () {
System . out . println ( "⑤ @PostConstruct" );
}
// 6. InitializingBean
@Override
public void afterPropertiesSet () {
System . out . println ( "⑥ afterPropertiesSet()" );
}
// 7. 自定义 init
public void customInit () {
System . out . println ( "⑦ customInit()" );
}
// 8. Bean 就绪,开始工作
public void doWork () {
System . out . println ( "⑧ 工作中..." );
}
// 9. @PreDestroy
@PreDestroy
public void preDestroy () {
System . out . println ( "⑨ @PreDestroy" );
}
// 10. DisposableBean
@Override
public void destroy () {
System . out . println ( "⑩ destroy()" );
}
// 11. 自定义 destroy
public void customDestroy () {
System . out . println ( "⑪ customDestroy()" );
}
}
2.3 BeanPostProcessor 扩展 @Component
public class MetricsBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization ( Object bean , String beanName ) {
// 初始化前:属性已注入,@PostConstruct 未执行
if ( bean instanceof ServiceLayer ) {
System . out . println ( "BeforeInit: " + beanName );
}
return bean ;
}
@Override
public Object postProcessAfterInitialization ( Object bean , String beanName ) {
// 初始化后:所有初始化完成,返回的 bean 将被放入容器
if ( bean instanceof ServiceLayer ) {
// 可生成代理(AOP 就在这里实现)
return Proxy . newProxyInstance (
bean . getClass (). getClassLoader (),
bean . getClass (). getInterfaces (),
new TimingInvocationHandler ( bean )
);
}
return bean ;
}
}
三、依赖注入详解 3.1 @Autowired 解析机制 @Service
public class OrderService {
// 1. 按类型注入(默认)
@Autowired
private PaymentGateway paymentGateway ;
// 2. 按名称注入
@Autowired
@Qualifier ( "alipayGateway" )
private PaymentGateway alipay ;
// 3. 构造器注入(Spring 4.3+ 推荐,可省略 @Autowired)
private final InventoryService inventoryService ;
private final NotificationService notificationService ;
public OrderService ( InventoryService inventoryService ,
NotificationService notificationService ) {
this . inventoryService = inventoryService ;
this . notificationService = notificationService ;
}
// 4. 可选注入
@Autowired ( required = false )
private AuditService auditService ;
// 5. 集合注入(所有该类型的 Bean)
@Autowired
private List < Validator < Order >> validators ;
// 6. Map 注入(key 为 beanName)
@Autowired
private Map < String , PaymentGateway > gatewayMap ;
}
3.2 @Resource vs @Autowired 特性 @Autowired @Resource 来源 Spring 注解 JSR-250 标准 匹配规则 先按类型,再按名称 先按名称,再按类型 适用场景 Spring 项目 追求标准兼容性 @Qualifier支持 通过 name 属性
3.3 @Value 注入 @Component
public class AppConfig {
// 基本类型
@Value ( "${app.name}" )
private String appName ;
@Value ( "${app.version:1.0.0}" ) // 带默认值
private String version ;
@Value ( "${server.port:8080}" )
private int port ;
// SpEL 表达式
@Value ( "#{systemProperties['user.home']}" )
private String userHome ;
@Value ( "#{T(java.time.LocalDate).now().plusDays(7)}" )
private LocalDate nextWeek ;
// 集合
@Value ( "${app.allowed-origins:http://localhost}" )
private List < String > allowedOrigins ;
@Value ( "#{${app.rate-limits:{api:100,admin:1000}}}" )
private Map < String , Integer > rateLimits ;
}
四、循环依赖解决 4.1 问题场景 @Service
public class ServiceA {
@Autowired
private ServiceB serviceB ; // A 依赖 B
}
@Service
public class ServiceB {
@Autowired
private ServiceA serviceA ; // B 依赖 A → 循环!
}
4.2 Spring 的三级缓存解决 ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 一级:singletonObjects │ │ 二级:earlySingletonObjects │ │ 三级:singletonFactories │
│ 完整 Bean(可用) │ │ 早期引用(未初始化) │ │ ObjectFactory(代理) │
│ Map<String, Object> │ │ Map<String, Object> │ │ Map<String, ObjectFactory>│
└─────────────────┘ └─────────────────┘ └─────────────────┘
// DefaultSingletonBeanRegistry.java
protected Object getSingleton ( String beanName , boolean allowEarlyReference ) {
Object singletonObject = this . singletonObjects . get ( beanName ); // 一级
if ( singletonObject == null && isSingletonCurrentlyInCreation ( beanName )) {
singletonObject = this . earlySingletonObjects . get ( beanName ); // 二级
if ( singletonObject == null && allowEarlyReference ) {
ObjectFactory <?> singletonFactory = this . singletonFactories . get ( beanName ); // 三级
if ( singletonFactory != null ) {
singletonObject = singletonFactory . getObject ();
this . earlySingletonObjects . put ( beanName , singletonObject ); // 提升到二级
this . singletonFactories . remove ( beanName );
}
}
}
return singletonObject ;
}
4.3 构造器循环依赖无法解决 // 这种循环依赖 Spring 无法解决(因为构造器调用时对象还未实例化)
@Service
public class ServiceA {
private final ServiceB serviceB ;
public ServiceA ( ServiceB serviceB ) { // 构造器注入
this . serviceB = serviceB ;
}
}
@Service
public class ServiceB {
private final ServiceA serviceA ;
public ServiceB ( ServiceA serviceA ) { // 构造器注入
this . serviceA = serviceA ;
}
}
// 解决方案:
// 1. 改为 Setter 注入(有 setter 时 Spring 可先实例化)
// 2. 使用 @Lazy(延迟初始化)
// 3. 重构,打破循环(引入中间层)
4.4 @Lazy 解决构造器循环 @Service
public class ServiceA {
private final ServiceB serviceB ;
public ServiceA ( @Lazy ServiceB serviceB ) { // 注入代理对象
this . serviceB = serviceB ;
}
}
五、Bean 作用域 @Component
@Scope ( "singleton" ) // 默认:每个 Spring 容器一个实例
public class SingletonBean {}
@Component
@Scope ( "prototype" ) // 每次请求创建新实例
public class PrototypeBean {}
@Component
@Scope ( value = WebApplicationContext . SCOPE_REQUEST , proxyMode = ScopedProxyMode . TARGET_CLASS )
public class RequestBean {} // 每个 HTTP 请求一个实例
@Component
@Scope ( value = WebApplicationContext . SCOPE_SESSION , proxyMode = ScopedProxyMode . TARGET_CLASS )
public class SessionBean {} // 每个 HTTP Session 一个实例
作用域 说明 线程安全 singleton 全局唯一 需注意 prototype 每次获取新实例 无共享状态 request 每个请求 单线程内安全 session 每个会话 单用户线程安全 application ServletContext 级别 需注意
5.1 Prototype 注入 Singleton 的问题 @Service
public class SingletonService {
@Autowired
private PrototypeBean prototypeBean ; // 只注入一次,后续复用!
// 解决方案:ObjectFactory 或 @Lookup
@Autowired
private ObjectFactory < PrototypeBean > prototypeFactory ;
public void doSomething () {
PrototypeBean bean = prototypeFactory . getObject (); // 每次获取新实例
bean . action ();
}
// 或使用 @Lookup
@Lookup
protected PrototypeBean getPrototypeBean () {
return null ; // Spring 会生成代理实现
}
}
六、条件化装配 6.1 @Conditional 家族 @Configuration
public class ConditionalConfig {
@Bean
@ConditionalOnProperty ( name = "cache.type" , havingValue = "redis" )
public CacheManager redisCacheManager () {
return new RedisCacheManager ();
}
@Bean
@ConditionalOnProperty ( name = "cache.type" , havingValue = "caffeine" )
public CacheManager caffeineCacheManager () {
return new CaffeineCacheManager ();
}
@Bean
@ConditionalOnClass ( name = "com.mongodb.client.MongoClient" )
public MongoTemplate mongoTemplate () {
return new MongoTemplate ( mongoClient (), "mydb" );
}
@Bean
@Profile ( "dev" ) // 只在 dev 环境生效
public DataSource h2DataSource () {
return new EmbeddedDatabaseBuilder (). setType ( EmbeddedDatabaseType . H2 ). build ();
}
@Bean
@Profile ( "prod" )
public DataSource mysqlDataSource () {
return DataSourceBuilder . create (). url ( "jdbc:mysql://..." ). build ();
}
}
6.2 自定义条件 public class OnFeatureEnabledCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome ( ConditionContext context , AnnotatedTypeMetadata metadata ) {
String feature = ( String ) metadata . getAnnotationAttributes ( ConditionalOnFeature . class . getName ())
. get ( "value" );
boolean enabled = context . getEnvironment ()
. getProperty ( "feature." + feature + ".enabled" , Boolean . class , false );
return enabled
? ConditionOutcome . match ( "Feature " + feature + " is enabled" )
: ConditionOutcome . noMatch ( "Feature " + feature + " is disabled" );
}
}
@Retention ( RetentionPolicy . RUNTIME )
@Conditional ( OnFeatureEnabledCondition . class )
public @interface ConditionalOnFeature {
String value ();
}
// 使用
@Bean
@ConditionalOnFeature ( "new-payment" )
public PaymentGateway newPaymentGateway () {
return new NewPaymentGateway ();
}
七、容器事件机制 // 自定义事件
public class OrderCreatedEvent extends ApplicationEvent {
private final String orderId ;
private final Long userId ;
public OrderCreatedEvent ( Object source , String orderId , Long userId ) {
super ( source );
this . orderId = orderId ;
this . userId = userId ;
}
// getters...
}
// 发布事件
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher publisher ;
public void createOrder ( OrderRequest req ) {
// 创建订单...
publisher . publishEvent ( new OrderCreatedEvent ( this , orderId , req . getUserId ()));
}
}
// 监听事件(同步)
@Component
public class OrderEventListener {
@EventListener
public void onOrderCreated ( OrderCreatedEvent event ) {
// 发送通知邮件
notificationService . sendOrderConfirmation ( event . getOrderId (), event . getUserId ());
}
@EventListener
@Async // 异步处理
public void onOrderCreatedAsync ( OrderCreatedEvent event ) {
// 更新统计数据
analyticsService . trackOrder ( event . getOrderId ());
}
@EventListener ( condition = "#event.userId != null" )
public void conditionalHandle ( OrderCreatedEvent event ) {
// 有条件地处理
}
}
// 事务事件(事务提交后才触发)
@TransactionalEventListener ( phase = TransactionPhase . AFTER_COMMIT )
public void afterTransactionCommit ( OrderCreatedEvent event ) {
// 确保事务已提交
integrationService . syncToERP ( event . getOrderId ());
}
八、最佳实践 8.1 注入方式推荐 // ✅ 推荐:构造器注入
@Service
public class OrderService {
private final OrderDao orderDao ;
private final InventoryService inventoryService ;
public OrderService ( OrderDao orderDao , InventoryService inventoryService ) {
this . orderDao = orderDao ;
this . inventoryService = inventoryService ;
}
}
// ⚠️ 可用:Setter 注入(可选依赖)
@Service
public class OptionalService {
private OptionalDependency optionalDep ;
@Autowired ( required = false )
public void setOptionalDep ( OptionalDependency dep ) {
this . optionalDep = dep ;
}
}
// ❌ 不推荐:字段注入(测试困难、隐藏依赖)
@Service
public class BadPractice {
@Autowired
private SomeDependency dep ; // 无法通过构造器判断依赖
}
8.2 Bean 设计原则 原则 说明 单例无状态 Singleton Bean 不应持有可变状态 依赖明确 通过构造器清晰表达依赖关系 延迟初始化 非核心 Bean 可设置 @Lazy 作用域正确 根据使用场景选择合适作用域 避免循环 设计时避免循环依赖
九、总结 主题 核心要点 容器层级 BeanFactory < ApplicationContext 生命周期 实例化 → 注入 → Aware → PostConstruct → InitializingBean → 使用 → 销毁 注入方式 构造器(推荐)> Setter > 字段 循环依赖 三级缓存解决 Setter 循环,构造器循环用 @Lazy 或重构 条件装配 @ConditionalOnXxx、@Profile、自定义 Condition 事件机制 ApplicationEventPublisher + @EventListener
IoC 容器是 Spring 的灵魂所在。理解 Bean 的生命周期流转、依赖注入的机制原理、循环依赖的处理方式,以及如何利用容器的扩展点(BeanPostProcessor、Aware 接口等),才能真正驾驭 Spring 框架构建可扩展的企业级应用。
继续阅读
探索更多技术文章 浏览归档,发现更多关于系统设计、工具链和工程实践的内容。