Ioc 容器系列的设计与实现
Ioc 容器的设计
-
BeanFactory:接口定义了基本的IoC容器规范,包括 getBean()这样的ioc容器的基本方法
-
HierarchicalBeanFactory: (Hierarchical (分层的))接口在继承BeanFactory接口之后,增加个 getParentBeanFactory() 方法,使BeanFactory具备了双亲 IoC容器的管理功能
-
ConfigurableBeanFactory:主要定义了beanFactory 的配置功能,setParentBeanFactory()设置双亲Ioc容器, addBeanPostProcessor() 配置bean的后置处理器等等
-
ListableBeanFactory: 细化了BeanFactory的接口功能,getBeanDefinitionNames()返回工厂中所有bean名称,
-
MessageSource:一个消息的策略接口,以用于支持信息的国际化和包含参数的信息的替换。(策略模式)
-
ApplicationEventPublisher:封装事件发布的接口(观察者模式)
-
ResourceLoader: 支持资源加载的策略接口
-
EnvironmentCapable: 提供了getEnvironment()方法 返回 表示当前应用程序运行的环境
-
ApplicationContext : 他实现了 EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, 具有了一个Ioc容器的基本能力, 同时实现了MessageSource, ApplicationEventPublisher, ResourcePatternResolver具有了更高级的Ioc 容器的特性
BeanFactory 的应用
BeanFactory 提供了最基本的 IOC 容器的功能,也制定了 IOC 容器所应遵守的最底层和最基本的编程规范
BeanFactory 使负责管理bean的,FanctoryBean是一个能产生或者修饰对象生成的工厂bean,我的理解他的存在是为了可以通过代码的实现来生成复杂的bean对象,通过 FanctoryBean 的beanName 获取到的 bean 是工厂bean生产出的bean,通过 & + FanctoryBean 的beanName 来获取工厂bean本身。
BeanFactory相关方法
方法 | 描述 |
---|---|
Object getBean(String name) throws BeansException | 通过 beanName 获取bean |
boolean containsBean(String name) | 判断容器中是否存在指定名称的bean |
boolean isSingleton(String name) | 判断bean 的scope 是否为 Singleton |
boolean isPrototype(String name) | 判断bean 的scope 是否为 Prototype |
boolean isTypeMatch(String name, ResolvableType typeToMatch) | 检查具有给定名称的 bean 是否与指定类型匹配 |
Class<?> getType(String name) throws NoSuchBeanDefinitionException; | 获取bean 的class类型 |
String[] getAliases(String name); | 获取 bean的所有别名 |
这些方法…代表最基本的容器入口
ApplicationContext
ApplicationContext 是一个更高级意义上的IoC容器
- 继承 EnvironmentCapable 可以获取程序运行环境
- 继承 ListableBeanFactory, HierarchicalBeanFactory 具有了容器的基本功能
- 继承 MessageSource 支持信息的国际化
- 继承 ApplicationEventPublisher 支持事件发布
- 继承 ResourceLoader 可以从不同位置加载bean定义资源
Ioc 容器的初始化过程
IoC容器的初始化是通过 refresh() 方法来启动的,这个启动包括了BeanDefinition的Resource定位、载入、注册三个过程。
-
resouce 资源定位: 它是由ResourceLoader通过统一的Resource接口来实现的
在文件系统中的bean可以使用FileSystemResourceLoader来进行抽象,在类路径下bean可以使用ClassPathContextResource 来抽象,这个过程就是容器在寻找数据的过程 -
第二个过程是BeanDefination的载入,这个过程就是把用户定义好的bean表示成IoC容器的内部的数据结构
- BeanDefination 实际上是bean在Ioc容器中的抽象,
-
第三个过程想IoC容器中注入这些BeanDefination的过程,这个过程是通过调用 BeanDefinitionRegistry 接口的实现来完成的,通俗来讲就是将 BeanDefination 保存(注册)到Ioc容器当中
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
/** bean 定义对象的映射,以 bean 名称为键. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
}
refreshBeanFactory()
refresh调用 refreshBeanFactory ,在这个方法中 通过 createBeanFactory() 构件了一个ioc 容器 供 ApplicationContext
使用,这个 容器 就是 DefaultListableBeanFactory , 之后 通过 loadBeanDefinitions(beanFactory); 来载入 BeanDifination,
// 创建一个ioc 容器
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
// 存在bean工厂 销毁bean工厂
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
// 创建并设置持有的 DefaultListableBeanFactory 的地方同时调用
try {
// 创建bean工厂
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 指定序列化 ID
beanFactory.setSerializationId(getId());
// 设置 beanFactoty 细节
// 1. 是否允许bean定义覆盖
// 2. 是否允许循环引用
customizeBeanFactory(beanFactory);
// 加载 beanDeanDefinitions
loadBeanDefinitions(beanFactory);
// 设置 beanFactory 持有
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
loadBeanDefinitions
这里我们以 AnnotationConfigWebApplicationContext 基于去讲解 其实这里 loadBeanDefinitions() 的不同实现就是为了 在不同的配置中加载 BeanDefinitions,最终目标还是将 BeanDefinitions注册到容器中
第一步初始化 BeanDefinitionReader 和 DefinitionScanner
// AnnotatedBeanDefinitionReade读取器用来加载class类型的配置
AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
// ClassPathBeanDefinitionScanner是一个扫描指定类路径中注解Bean定义的扫描器
ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);
第二步设置 BeanNameGenerator
// 设置 beanName 生成器 BeanNameGenerator 是一个策略接口用于为给定的 bean 定义生成一个 bean 名称
BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
if (beanNameGenerator != null) {
reader.setBeanNameGenerator(beanNameGenerator);
scanner.setBeanNameGenerator(beanNameGenerator);
beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
}
第三步 设置 ScopeMetadataResolver
// ScopeMetadataResolver 用于解析bean定义范围的策略接口
ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
if (scopeMetadataResolver != null) {
reader.setScopeMetadataResolver(scopeMetadataResolver);
scanner.setScopeMetadataResolver(scopeMetadataResolver);
}
第四步bean 注册
// 使用 reader 注册bean 配合传入的配置类
if (!this.componentClasses.isEmpty()) {
if (logger.isDebugEnabled()) {
logger.debug("Registering component classes: [" +
StringUtils.collectionToCommaDelimitedString(this.componentClasses) + "]");
}
reader.register(ClassUtils.toClassArray(this.componentClasses));
}
// 使用 scan注册bean 配合传入的配置类
if (!this.basePackages.isEmpty()) {
if (logger.isDebugEnabled()) {
logger.debug("Scanning base packages: [" +
StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
}
scanner.scan(StringUtils.toStringArray(this.basePackages));
}
// 用于 xml 配置 这种本地配置的bean 的注册
String[] configLocations = getConfigLocations();
if (configLocations != null) {
for (String configLocation : configLocations) {
try {
Class<?> clazz = ClassUtils.forName(configLocation, getClassLoader());
if (logger.isTraceEnabled()) {
logger.trace("Registering [" + configLocation + "]");
}
reader.register(clazz);
}
catch (ClassNotFoundException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Could not load class for config location [" + configLocation +
"] - trying package scan. " + ex);
}
int count = scanner.scan(configLocation);
if (count == 0 && logger.isDebugEnabled()) {
logger.debug("No component classes found for specified class/package [" + configLocation + "]");
}
}
}
}
beanDefination 的 register
registerBean 调用 doRegisterBean
// 给创建的bean 创建BeanDefinition 并且解析了注解数据
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName()); // 设置bean的作用域
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); // 生成beanName
// 扫描bean 的注解设置相关注解信息 这里已经根据bean上的注解设置了一次属性
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
// 根据Qualifier注解 强制更改bean的定义
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
// 带有名称和别名的 BeanDefinition 的持有者。可以注册为内部 bean 的占位符
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 判断是否为 代理对象bean 定义以那种模式生成代理对象
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 注册到 beanDefinitionRegister
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);