实现IoC容器

廖雪峰

资深软件开发工程师,业余马拉松选手。

Spring的核心就是能管理一组Bean,并能自动配置依赖关系的IoC容器。而我们的Summer Framework的核心context模块就是要实现IoC容器。

设计目标

Spring的IoC容器分为两类:BeanFactory和ApplicationContext,前者总是延迟创建Bean,而后者则在启动时初始化所有Bean。实际使用时,99%都采用ApplicationContext,因此,Summer Framework仅实现ApplicationContext,不支持BeanFactory。

早期的Spring容器采用XML来配置Bean,后期又加入了自动扫描包的功能,即通过的配置。再后来,又加入了Annotation配置,并通过@ComponentScan注解实现自动扫描。如果使用Spring Boot,则99%都采用@ComponentScan注解方式配置,因此,Summer Framework也仅实现Annotation配置+@ComponentScan扫描方式完成容器的配置。

此外,Summer Framework仅支持Singleton类型的Bean,不支持Prototype类型的Bean,因为实际使用中,99%都采用Singleton。依赖注入则与Spring保持一致,支持构造方法、Setter方法与字段注入。支持@Configuration和BeanPostProcessor。至于Spring的其他功能,例如,层级容器、MessageSource、一个Bean允许多个名字等功能,一概不支持!

下表列出了Spring Framework和Summer Framework在IoC容器方面的异同:

功能

Spring Framework

Summer Framework

IoC容器

支持BeanFactory和ApplicationContext

仅支持ApplicationContext

配置方式

支持XML与Annotation

仅支持Annotation

扫描方式

支持按包名扫描

支持按包名扫描

Bean类型

支持Singleton和Prototype

仅支持Singleton

Bean工厂

支持FactoryBean和@Bean注解

仅支持@Bean注解

定制Bean

支持BeanPostProcessor

支持BeanPostProcessor

依赖注入

支持构造方法、Setter方法与字段

支持构造方法、Setter方法与字段

多容器

支持父子容器

不支持

Annotation配置

从使用者的角度看,使用IoC容器时,需要定义一个入口配置,它通常长这样:

@ComponentScan

public class AppConfig {

}

AppConfig只是一个配置类,它的目的是通过@ComponentScan来标识要扫描的Bean的包。如果没有明确写出包名,那么将基于AppConfig所在包进行扫描,如果明确写出了包名,则在指定的包下进行扫描。

在扫描过程中,凡是带有注解@Component的类,将被添加到IoC容器进行管理:

@Component

public class Hello {

}

我们用到的许多第三方组件也经常会纳入IoC容器管理。这些第三方组件是不可能带有@Component注解的,引入第三方Bean只能通过工厂模式,即在@Configuration工厂类中定义带@Bean的工厂方法:

@Configuration

public class DbConfig {

@Bean

DataSource createDataSource(...) {

return new HikariDataSource(...);

}

@Bean

JdbcTemplate createJdbcTemplate(...) {

return new JdbcTemplate(...);

}

}

基于Annotation配置的IoC容器基本用法就是上面所述。下面,我们就一步一步来实现IoC容器。

觚的成语
古典日记:如何欣赏古典音乐——写在一切的开端(一)