Skip to content
章节导航

Spring 核心: IOC 容器

IOC(Inversion of Control,控制反转)是 Spring 框架的核心思想,Spring 对它的实现通常被称作 DI(Dependency Injection,依赖注入)

为什么需要 IOC

Spring 需要 IOC 的根本原因是:将对象创建和依赖管理的控制权从业务代码中剥离,交给容器统一处理,从而实现解耦、可维护性、可测试性和灵活性。这种设计模式是 Spring 成为企业级开发事实标准的基础之一。

简单来说,IOC 让程序员从复杂的对象组装工作中解放出来,专注于业务逻辑的实现。

  • 面向对象的软件设计,是由 X 个对象组成,且对象之间彼此合作来完成某个功能

  • IOC将对象的创建、依赖关系的管理和生命周期的控制从应用程序代码中解耦出来

IOC 容器的核心设计:依赖注入

依赖注入的三种主要方式

  • 构造器注入:通过构造方法强制注入必需的依赖,确保对象在创建时就处于完整可用状态。
  • Setter 注入:通过 setter 方法提供可选或可变的依赖。
  • 字段注入:直接在字段上通过 @Autowired 注入依赖,简化代码但隐藏依赖关系。

Spring IOC 容器使用的是什么数据结构来存储 Bean (Object)

Spring IOC 容器主要使用多种数据结构的组合来存储和管理 Bean,不同容器实现略有差异。

  • 找到 BeanDefinitionRegistry,找到 int getBeanDefinitionCount(); 方法的任意一个实现类,源码如下
java
@Override
	public int getBeanDefinitionCount() {
		return this.beanDefinitionMap.size();
	}

怎么获取 bean

一、基础获取方式

1. ApplicationContext 直接获取

java
@Component
public class AppContextAware implements ApplicationContextAware {
    private static ApplicationContext ctx = null;

    public AppContextAware() {
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        AppContextAware.ctx = applicationContext;
    }

    public static ApplicationContext getInstance() {
        return ctx;
    }

    // 静态方法获取Bean
    public static <T> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }
    
    public static Object getBean(String beanName) {
        return context.getBean(beanName);
    }


// 使用
UserService userService = AppContextAware.getBean(UserService.class);

}

2. BeanFactory 获取

java
// 方式2:通过 BeanFactory(ApplicationContext的父接口)
ConfigurableListableBeanFactory beanFactory = 
    ((ConfigurableApplicationContext) context).getBeanFactory();

// 获取Bean
UserService userService = beanFactory.getBean(UserService.class);

// 检查Bean是否存在
boolean exists = beanFactory.containsBean("userService");

// 获取Bean的类型
Class<?> type = beanFactory.getType("userService");

二、自动注入方式(推荐)

1. 字段注入(Field Injection)

java
@Component
public class UserController {
    // 直接注入到字段
    @Autowired
    private UserService userService;
    
    // 使用 @Resource(JSR-250标准)
    @Resource
    private UserService userService;
    
    // 指定具体Bean名称
    @Autowired
    @Qualifier("primaryUserService")
    private UserService userService;
}

2. 构造器注入(Constructor Injection) - Spring 推荐

java
@Component
public class UserController {
    private final UserService userService;
    private final EmailService emailService;
    
    // Spring 4.3+ 自动注入,无需 @Autowired
    public UserController(UserService userService, EmailService emailService) {
        this.userService = userService;
        this.emailService = emailService;
    }
}

// 使用 Lombok 简化
@Component
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;
    private final EmailService emailService;
}

3. Setter 注入(Setter Injection)

java
@Component
public class UserController {
    private UserService userService;
    
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    
    // 可选依赖
    @Autowired(required = false)
    public void setOptionalService(OptionalService service) {
        // 可能为 null
    }
}