本文已收录在Github,关注我,紧跟本系列专栏文章,咱们下篇再续!
- 🚀 魔都架构师 | 全网30W技术追随者
- 🔧 大厂分布式系统/数据中台实战专家
- 🏆 主导交易系统百万级流量调优 & 车联网平台架构
- 🧠 AIGC应用开发先行者 | 区块链落地实践者
- 🌍 以技术驱动创新,我们的征途是改变世界!
- 👉 实战干货:编程严选网
Spring 框架最核心的就是IoC(Inversion of Control,控制反转)容器。站在上帝视角,一图看清 IoC 容器在开发中的地位:

此刻对该图可能还有疑惑,来开启本文的征程吧。
0 Bean是什么?
被 IoC 容器管理的这些源于你的应用中的对象即是 bean,通常是个 POJO 类。
1 IoC是什么?
IoC 也被称为依赖注入(DI,Dependency Injection)。它其实是一个流程,IoC 容器负责对 bean 进行实例化、装配和管理。
在此流程中的对象仅需通过如下方式之一:
- 构造器参数
- 工厂方法参数
- 在构造或从工厂方法返回后在对象实例上设置的属性
来定义其依赖(即该对象协作所需的其它对象)。然后,容器在创建 bean 时注入这些依赖项。 从本质上讲,该流程也是bean自身通过使用诸如类的直接构造或类似服务定位器模式的机制来控制其依赖项的实例化或位置的的逆过程,因此得名控制反转。
2 IoC的关键接口设计
在 Spring 源码中,IoC 容器实现主要基于如下两个包:
-
spring-beans模块的org.springframework.beans
-
spring-context模块的org.springframework.context
常见接口:

2.1 BeanFactory
提供了配置框架和基本功能。别看它其貌不扬,实则是种高级的配置机制,能够管理任意类型的对象。
2.2 ApplicationContext

BeanFactory
的子接口,基于父接口添加一些方便企业应用开发功能:
- 更方便集成 AOP
- 国际化处理
- 事件发布
- web使用的WebApplicationContext
该接口可算得上是BeanFactory
的一个较为完整的超集,因此我们常说的Spring容器也就是它。
现在,让我们再看看首图中的配置元数据的作用。
3 配置元数据(configuration metadata)
开发者能够通过配置元数据告知 Spring 容器应用中的对象及对象间依赖关系。籍此,容器读取 配置元数据后 ,便知晓哪些对象需要被实例化、配置和装配。
那么配置元数据从何而来?Spring 提供了如下三种引入方式:
- XML:远古的最初用法,由于繁琐,现代开发中基本不再使用。但这的确也是一种简单和直观的对象细节说明,所以本专栏有时也将沿用该方式描述 bean 信息
- Java注解:Spring 2.5开始提供
- Java代码:Spring 3.0开始提供
IoC容器本身是和元数据配置引入方式是 完全 解耦的,三种可混用,只是开发规范上建议统一。
配置中至少得包含一个(开发中一般都是多个)容器必须管理的bean定义。如用Java代码方式:通常在一个被@Configuration的类中,在方法上用@Bean
java
@Configuration
public class RabbitMsgConvertConfigure {
// 队列名称
public final static String SPRING_BOOT_QUEUE = "spring-b";
// 交换机名称
public final static String SPRING_BOOT_EXCHANGE = "sprin";
// 绑定的值
public static final String SPRING_BOOT_BIND_KEY = "sprin";
// 在RabbitMQ上创建queue,exchange,binding: 通过@Bean实现
// 定义队列
@Bean
Queue queue() {
return new Queue(SPRING_BOOT_QUEUE, durable: false);
}
}
4 如何实例化容器?
现代开发中基本也无需显式实例化IoC容器。即使在web.xml文件也只需简单几行样板式配置。
xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
easy cash!由于ApplicationContext
接口有多种实现,因此容器可从多种外部资源获取。比如,在我们初学 Spring 时的单体应用中一定都创建过如下实例,直接将位置路径传给容器的构造器即可让容器加载配置元数据:
ClassPathXmlApplicationContext:
java
ApplicationContext context = new ClassPathXmlApplicationContext(
"classpath:/org/springframework/web/context/WEB-INF/applicationContext.xml");
FileSystemXmlApplicationContext:
java
ConfigurableApplicationContext ctx =
new FileSystemXmlApplicationContext(new String[] {"file:" + tmpFile.getPath()}, refresh: false);
5 咋用容器?
通过ApplicationContext的实例,即可用来读取bean定义并访问其方法。
ApplicationContext 作为一种高级容器的工厂接口,关键在于可维护不同bean和它们之间的依赖关系。 在初学 Spring 时我们经常直接调用其 getBean 方法的各种不同重载形式,来方便地获取所需实例。
java
// 1. 创建并配置beans
ClassPathXmlApplicationContext ctx =
new ClassPathXmlApplicationContext(path: getClass().getSimpleName() + ".xml", getClass());
// 2. 取得配置的实例
testBeanProxy = (ITestBean) ctx.getBean(name: "testBean");
// 3. 使用实例
this.testBeanTarget = (TestBean) Objects.requireNonNull(((Advised) testBeanProxy).getTargetSource().getTarget());
为避免与Spring API过度耦合,实际代码不应直接调用getBean()。 因此Spring与Web框架的集成为Web组件比如控制器,也提供依赖注入方式,使得可通过@Autowired配置元数据声明对特定bean的依赖。
本文由博客一文多发平台 OpenWrite 发布!