前言

因为QF框架引入了IOC概念,这边阐述一下IOC的观念,以springboot为例子

欢迎来到 QFramework 的文档! — QFramework 1.0.60 文档

Spring IOC容器基本原理

IOC容器的概念

IOC容器是具有依赖注入功能的容器,负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。应用程序无需直接在代码中new相关的对象,而是由IOC容器进行组装。在Spring中,BeanFactory是IOC容器的实际代表者。

Spring IOC容器通过读取配置文件中的配置元数据来管理对象。配置元数据可以通过XML文件、注解、基于Java文件的配置或基于属性文件的配置来定义。

Bean的概念

由IOC容器管理的应用程序对象称为Bean。Bean是由Spring容器初始化、装配及管理的对象。IOC容器通过配置元数据(由BeanDefinition代表)来确定如何实例化Bean、管理Bean之间的依赖关系以及管理Bean。

开始Spring Hello World之旅

1. 准备需要的jar包

核心jar包

  • org.springframework.asm-3.0.5.RELEASE.jar
  • org.springframework.core-3.0.5.RELEASE.jar
  • org.springframework.beans-3.0.5.RELEASE.jar
  • org.springframework.context-3.0.5.RELEASE.jar
  • org.springframework.expression-3.0.5.RELEASE.jar

依赖的jar包

  • com.springsource.org.apache.log4j-1.2.15.jar
  • com.springsource.org.apache.commons.logging-1.1.1.jar
  • com.springsource.org.apache.commons.collections-3.2.1.jar

2. 创建标准Java工程

3. 开发接口

1
2
3
4
5
package com.ljq.test;

public interface HelloService {
public void sayHello();
}

4. 实现接口

1
2
3
4
5
6
7
package com.ljq.test;

public class HelloServiceImpl implements HelloService {
public void sayHello() {
System.out.println("Hello World!");
}
}

5. 配置文件helloworld.xml

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<bean id="helloService" class="com.ljq.test.HelloServiceImpl" />
</beans>

6. 获取IOC容器并调用Bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.ljq.test;

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

public class HelloServiceTest {
@Test
public void testHelloWorld() {
// 1. 读取配置文件实例化一个IOC容器
ApplicationContext context = new ClassPathXmlApplicationContext("helloworld.xml");
// 2. 从容器中获取Bean
HelloService helloService = context.getBean("helloService", HelloService.class);
// 3. 执行业务逻辑
helloService.sayHello();
}
}

详解IOC容器

在Spring中,BeanFactory接口提供了IOC容器的最基本功能,而ApplicationContext接口扩展了BeanFactory,提供了更多企业级功能支持,如AOP集成、国际化处理、事件传播等。

容器实现一览

  • XmlBeanFactory:提供基本的IOC容器功能,可以从classpath或文件系统获取资源。

    1
    2
    Resource resource = new ClassPathResource("classpath.xml");
    BeanFactory beanFactory = new XmlBeanFactory(resource);
  • ClassPathXmlApplicationContext:从classpath获取配置文件。

    1
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath.xml");
  • FileSystemXmlApplicationContext:从文件系统获取配置文件。

    1
    BeanFactory beanFactory = new FileSystemXmlApplicationContext("fileSystemConfig.xml");

ApplicationContext接口获取Bean的方法

  • Object getBean(String name):根据名称返回一个Bean,客户端需要自己进行类型转换。
  • <T> T getBean(String name, Class<T> requiredType):根据名称和指定的类型返回一个Bean,客户端无需自己进行类型转换。
  • <T> T getBean(Class<T> requiredType):根据指定的类型返回一个Bean,客户端无需自己进行类型转换。
  • Map<String, T> getBeansOfType(Class<T> type):根据指定的类型返回一个键值为名字和值为Bean对象的Map。

IOC容器的工作流程

  1. 准备配置文件:在配置文件中声明Bean定义,配置元数据。
  2. 解析元数据:IOC容器的Bean Reader读取并解析配置文件,生成BeanDefinition对象。
  3. 实例化IOC容器:客户端实例化容器,获取需要的Bean。

小结

  • 非入侵性:除了测试程序的代码外,所有代码都没有出现Spring任何组件,能够非常容易地替换掉Spring。
  • 低耦合:客户端代码完全面向接口编程,无需知道实现类,可以通过修改配置文件来更换接口实现。
  • 易测试:在开发初期没有真正的实现时,可以模拟一个实现来测试,不耦合代码。
  • 易重用:Bean之间几乎没有依赖关系,易于重用。

控制反转

控制:IOC意味着将你设计好的对象交给IOC容器控制,而不是传统的在你的对象内部直接控制;

IOC是有专门一个容器来创建这些对象,即由IOC容器来控制对象的创建;
谁控制谁?当然是IOC容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。

反转:传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;

反转则是由IOC容器来帮忙创建及注入依赖对象;
由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

IOC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。

传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;

有了IOC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是 松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

其实 IOC 对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在 IOC/DI 思想中,应用程序就变成被动的了,被动的等待 IOC 容器来创建并注入它所需要的资源了。

IOC与单例

一、IOC容器介绍

IOC(Inversion of Control,控制反转)容器是面向对象编程中实现依赖注入的核心框架,其核心思想是将对象的创建、依赖管理和生命周期控制从代码中剥离,交由容器统一管理。以下是其核心特性:

  1. 依赖注入(DI)
    通过构造函数、属性或方法参数自动注入对象所需的依赖,开发者只需声明依赖关系,无需手动实例化。例如,Spring框架通过@Autowired实现自动装配。
  2. 对象生命周期管理
    IOC容器负责对象的实例化、初始化、作用域管理(如单例、原型)及销毁。例如,Spring的BeanFactoryApplicationContext分别提供基础与高级生命周期管理功能。
  3. 配置元数据支持
    支持XML、注解或Java配置类定义Bean,容器通过解析元数据动态创建对象。例如,ClassPathXmlApplicationContext加载XML配置文件生成Bean实例。
  4. 解耦与扩展性
    将组件间的硬编码依赖转为松耦合关系,便于模块化开发和测试。例如,通过IOC容器解耦Service层与DAO层的直接依赖。

二、IOC容器与单例模式的区别

维度 IOC容器 单例模式
设计目标 管理对象全生命周期及依赖关系 确保一个类仅有一个实例
实现方式 通过容器自动管理(如Spring的Bean作用域) 手动编码实现(如双重校验锁、静态内部类)
作用域控制 支持多作用域(单例、原型、会话等) 仅单例
依赖管理 自动注入依赖,解决对象间复杂关系 需手动处理依赖
线程安全性 容器默认保证单例线程安全(如Spring单例Bean) 需开发者自行实现线程安全机制
灵活性 配置灵活,可通过注解或XML动态调整作用域 代码硬编码,扩展性受限

具体差异示例:

  • IOC容器的单例:Spring默认以单例模式管理Bean,但作用域为容器级别,同一容器内共享实例。例如,通过@Scope("singleton")定义单例Bean。
  • 传统单例模式:需开发者通过静态方法或锁机制确保全局唯一实例,如双重校验锁实现。

三、总结

IOC容器通过控制反转和依赖注入,实现了对象管理的自动化与解耦,而单例模式仅是确保类实例唯一性的设计模式。两者的核心差异在于:

  1. 功能范围:IOC容器涵盖依赖管理、生命周期等综合功能;单例模式仅解决实例唯一性问题。
  2. 实现层级:IOC容器是框架级机制,单例模式是代码级设计。

若需进一步了解IOC容器的源码实现(如反射机制)或单例模式的高并发优化(如CAS算法),可参考[网页5]与[网页9]的详细解析。

链接

https://www.cnblogs.com/linjiqin/p/3407126.html

IOC容器(底层原理解读)_ioc底层原理是什么-CSDN博客