IOC 篇

一、概念

Spring IOC(Inversion of Control,控制反转)是 Spring 框架的核心特性之一,它是一种设计理念,用于实现对象的创建和依赖关系的管理。以下为你详细介绍:

核心概念

  • 传统的对象创建方式:在传统的 Java 开发中,对象的创建和管理通常由程序员在代码中手动完成。例如,当一个类需要依赖另一个类的对象时,通常会在该类中使用 new 关键字来创建依赖对象。这种方式会导致类与类之间的耦合度较高,代码的可维护性和可测试性较差。
  • 控制反转:而在 Spring IOC 中,对象的创建、初始化、销毁等生命周期管理工作不再由程序员手动控制,而是交给 Spring 容器来完成。Spring 容器会根据配置信息(如 XML 配置文件、Java 注解等)来创建和管理对象,并将这些对象注入到需要使用它们的类中。这样,对象之间的依赖关系由 Spring 容器来控制,实现了控制的反转。

实现方式

Spring IOC 主要通过以下两种方式来实现:

1. 依赖注入(Dependency Injection,DI)

  • 介绍:依赖注入是 Spring IOC 的主要实现方式,它是指将一个对象所依赖的其他对象通过某种方式(如构造函数、Setter 方法等)注入到该对象中。
  • 示例

收起

java

// 定义一个接口
interface MessageService {
    String getMessage();
}

// 实现接口
class EmailService implements MessageService {
    @Override
    public String getMessage() {
        return "This is an email message.";
    }
}

// 依赖 MessageService 的类
class MessagePrinter {
    private MessageService messageService;

    // 通过构造函数进行依赖注入
    public MessagePrinter(MessageService messageService) {
        this.messageService = messageService;
    }

    public void printMessage() {
        System.out.println(messageService.getMessage());
    }
}

// 使用 Spring 进行配置和测试
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
class AppConfig {
    @Bean
    public MessageService messageService() {
        return new EmailService();
    }

    @Bean
    public MessagePrinter messagePrinter() {
        return new MessagePrinter(messageService());
    }
}

public class Main {
    public static void main(String[] args) {
        // 创建 Spring 容器
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        // 从容器中获取 MessagePrinter 对象
        MessagePrinter printer = context.getBean(MessagePrinter.class);
        // 调用方法
        printer.printMessage();
    }
}

在上述示例中,MessagePrinter 类依赖于 MessageService 接口的实现类。通过构造函数注入的方式,将 EmailService 对象注入到 MessagePrinter 类中。Spring 容器会根据 AppConfig 类中的配置信息来创建和管理这些对象。

2. 依赖查找(Dependency Lookup)

  • 介绍:依赖查找是指对象主动从容器中查找自己所依赖的对象。与依赖注入不同,依赖查找是对象主动去获取依赖,而不是由容器将依赖注入到对象中。
  • 示例

收起

java

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

// 定义一个接口
interface UserService {
    void sayHello();
}

// 实现接口
class UserServiceImpl implements UserService {
    @Override
    public void sayHello() {
        System.out.println("Hello!");
    }
}

public class DependencyLookupExample {
    public static void main(String[] args) {
        // 创建 Spring 容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 通过依赖查找获取 UserService 对象
        UserService userService = (UserService) context.getBean("userService");
        // 调用方法
        userService.sayHello();
    }
}

在上述示例中,通过 context.getBean("userService") 方法从 Spring 容器中查找 UserService 对象。

优点

  • 降低耦合度:通过将对象的创建和依赖关系的管理交给 Spring 容器,减少了类与类之间的直接依赖,降低了代码的耦合度,提高了代码的可维护性和可测试性。
  • 提高可扩展性:当需要更换依赖对象的实现时,只需要修改 Spring 容器的配置信息,而不需要修改使用该对象的类的代码,提高了代码的可扩展性。
  • 便于测试:由于对象的依赖关系可以通过配置进行管理,在进行单元测试时,可以很方便地替换依赖对象,进行模拟测试。

总之,Spring IOC 是一种强大的设计理念,通过依赖注入和依赖查找等方式,实现了对象的创建和依赖关系的管理,为 Java 开发带来了很大的便利。

二、注入方式

  1. 字段注入
  2. 构造方法注入
  3. setter注入
  4. 方法注入

三、BeanFactory VS ApplicationContext

在 Spring 框架中,BeanFactory 和 ApplicationContext 是两个核心接口,它们都是 Spring IoC(控制反转)容器的基础实现,但功能和使用场景有所不同。以下是它们的详细对比:


1. 定义与核心职责

特性BeanFactoryApplicationContext
定位Spring 最基础的 IoC 容器接口,提供基本的依赖注入功能。BeanFactory 的子接口,扩展了企业级功能(如事件、国际化、资源加载等)。
核心职责管理 Bean 的生命周期(创建、配置、组装)。在 BeanFactory 的基础上,提供更丰富的应用上下文功能。

2. 功能对比

BeanFactory
  • 基本功能

    • 加载 Bean 定义(如 XML、注解配置)。

    • 管理 Bean 的依赖注入(构造器、Setter 注入)。

    • 支持 Bean 的作用域(Singleton、Prototype 等)。

  • 特点

    • 延迟初始化:Bean 在首次请求时才会被创建。

    • 轻量级:占用资源少,适合资源受限环境(如移动设备)。

    • 功能有限:不直接支持 AOP、事件、国际化等高级特性。

ApplicationContext
  • 扩展功能

    • 继承 BeanFactory 的所有功能

    • 事件发布与监听:支持通过 ApplicationEvent 和 ApplicationListener 实现事件驱动。

    • 国际化(i18n):通过 MessageSource 支持多语言。

    • 资源访问:统一资源加载(如 ResourceLoader 支持类路径、文件系统、URL 等)。

    • AOP 集成:无缝支持 Spring AOP 和事务管理。

    • 环境配置:通过 Environment 接口管理 Profiles 和 Properties。

    • Web 支持:提供 WebApplicationContext 用于 Web 应用。

  • 特点

    • 预初始化单例 Bean:容器启动时即初始化所有单例 Bean(可通过配置调整)。

    • 功能全面:覆盖企业级开发所需的所有特性。


3. 使用场景

场景推荐容器理由
轻量级应用BeanFactory资源受限环境,只需基本依赖注入功能。
企业级应用ApplicationContext需要事件、AOP、国际化等高级功能。
Web 应用WebApplicationContext继承 ApplicationContext,支持 Web 相关特性。
测试环境ApplicationContext结合 @ContextConfiguration 简化集成测试。

4. 代码示例

使用 BeanFactory

java

复制

// 1. 创建 BeanFactory(XML 配置)
Resource resource = new ClassPathResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);

// 2. 获取 Bean
MyService service = factory.getBean("myService", MyService.class);
使用 ApplicationContext

java

复制

// 1. 创建 ApplicationContext(注解配置)
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

// 2. 获取 Bean
MyService service = context.getBean(MyService.class);

// 3. 发布事件
context.publishEvent(new CustomEvent("This is an event."));

5. 性能与初始化差异

特性BeanFactoryApplicationContext
初始化速度更快(延迟加载 Bean)。较慢(预初始化单例 Bean)。
运行时性能按需加载,适合轻量场景。启动时加载,运行时响应更快。
内存占用更低。更高(因预加载所有单例 Bean)。

6. 常见实现类

  • BeanFactory 实现

    • XmlBeanFactory(已弃用,建议使用 ApplicationContext 替代)。

    • DefaultListableBeanFactory(底层核心实现)。

  • ApplicationContext 实现

    • AnnotationConfigApplicationContext(基于注解配置)。

    • ClassPathXmlApplicationContext(基于 XML 配置)。

    • FileSystemXmlApplicationContext(文件系统 XML 配置)。

    • WebApplicationContext(Web 应用专用)。


7. 如何选择?

  • 默认选择 ApplicationContext

    • 99% 的场景下应使用 ApplicationContext,因为它功能全面且与 Spring 生态无缝集成。

    • 唯一的例外是极端资源受限环境(需手动权衡功能与资源开销)。

  • 避免直接使用 BeanFactory

    • 大多数高级特性(如 AOP、事务)依赖 ApplicationContext

    • Spring Boot、Spring MVC 等模块默认基于 ApplicationContext


总结

  • BeanFactory 是 Spring 的基础容器,提供核心的 IoC 功能,但功能有限。

  • ApplicationContext 是 BeanFactory 的扩展,整合了企业级开发所需的所有特性,是实际开发中的首选。

  • 两者关系类似于「基础版 vs 增强版」,实际开发中几乎总是使用 ApplicationContext

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值