Spring IoC 容器与依赖注入原理深度剖析

深入 Spring IoC 容器的实现机制,理解 Bean 生命周期、循环依赖解决、注入方式选型与容器的扩展点设计

控制反转(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)
特性BeanFactoryApplicationContext
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每个会话单用户线程安全
applicationServletContext 级别需注意

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 框架构建可扩展的企业级应用。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「java-enterprise」更多文章

  1. 限流算法深度解析:令牌桶、漏桶与滑动窗口计数
  2. Java 代码质量:SonarQube、Checkstyle 与 SpotBugs 工程化实践
  3. 分布式文件存储:MinIO、阿里云 OSS 与 Spring 集成实战