SpringIOC容器设计
IOC简介
在Spring IoC容器的设计中,作者设计了两个接口来表示容器
-
BeanFactory
BeanFactory简单粗暴,可以理解为HashMap,key是BeanName,value是Bean实例,通常只提供put和get。这系列容器只实现了容器的最基本功能,可看做为简单容器。 -
ApplicationContext
ApplicationContext应用上下文,它作为容器的高级形态而存在。应用上下文在简单容器的基础上,增加了许多面向框架的特性,同时对应用环境做了许多适配。
Spring通过定义BeanDefinition来管理基于Spring的应用中的各种对象以及它们之间的相互依赖关系。对IoC容器来说,BeanDefinition就是依赖反转模式中管理的对象依赖关系的数据抽象,也是容器实现依赖反转功能的核心数据结构,依赖反转功能都是围绕这个BeanDefinition的处理来完成的。
两条设计主线
第一条
第一条接口设计的主线是从接口BeanFactory
到HierarchicalBeanFactory
再到ConfigurableBeanFactory
,是一条主要的BeanFactory
设计路径。在这条接口设计路径中,BeanFactory
接口定义了基本的IOC容器的规范。在这个接口定义中.包括了getBean()
这样的IOC容器的基本方法(通过这个方法可以从容器中取得Bean)。HierarchicalBeanFactory
接口在继承了BeanFactory
的基本接口之后,增加了getParentBeanFactory()
的接口功能,使BeanFactory
具备了双亲IOC容器的管理功能.在接下来的ConfigurableBeanFactory
接口中,主要定义了一些对BeanFactory
的配置功能,比如通过setParentBeanFactory()
设置双亲IOC容器,通过addBeanPostProcessor()
配置Bean后置处理器等等。通过这些接口设计的叠加,定义了BeanFactory
就是简单IOC容器的基本功能。
BeanFactory
package com.zqr.SpringDetail.org.springframework.beans.factory;
import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
public interface BeanFactory {
/**
* 用&符号获取BeanFactory本身,用来区分通过容器获取FactoryBean产生的对象和FactoryBean本身.
* 比如:myJndiObject是一个FactoryBean,使用&myJndiObject获取到的是FactoryBean,而不是myJndiObject产生的对象.
*
* Pass:
* BeanFactory与FactoryBean
* BeanFactory是一个Factory,用来管理Bean;
* FactoryBean是一个工厂Bean,能够产生和修饰对象生成.
*/
String FACTORY_BEAN_PREFIX = "&";
/**
* 使用不同的Bean检索方法,从IoC容器中得到所需要的Bean,从而忽略具体的IoC实现.
*这些检索方法代表的是最为基本的容器入口.
*/
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
/**
* 容器是否含有指定名字的Bean
*/
boolean containsBean(String name);
/**
* 指定名字的Bean是否是Singleton类型.
* Pass:对于Singleton属性,可以在BeanDefinition中指定.
*/
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
/**
* 指定名字的Bean是否是Prototype类型.
*/
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
/**
* 查询指定名字的Bean的Class类型是否是特定的Class类型.
*/
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
/**
* 查询指定名字的Bean的Class类型.
*/
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
/**
* 查询指定名字的Bean的所有别名.这些别名都是用户在BeanDefinition中定义的.
*/
String[] getAliases(String name);
}
HierarchicalBeanFactory
package org.springframework.beans.factory;
import org.springframework.lang.Nullable;
/**
* 定义了对BeanFactory层次结构的操作
*/
public interface HierarchicalBeanFactory extends BeanFactory {
/**
* 返回本Bean工厂的父工厂
*/
@Nullable
BeanFactory getParentBeanFactory();
/**
* 本地工厂(容器)是否包含这个Bean
*/
boolean containsLocalBean(String name);
}
ConfigurableBeanFactory
/**
* 定义BeanFactory的配置.
*
* 这边定义了太多太多的api,比如类加载器,类型转化,属性编辑器,BeanPostProcessor,作用域,bean定义,处理bean依赖关系,合并其他ConfigurableBeanFactory,bean如何销毁.
*
* @author DemoTransfer
* @since 4.3
*/
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {
//-------------------------------------------------------------------------
// 定义了两个作用域: 单例和原型.可以通过registerScope来添加.
// SCOPE_SINGLETON,SCOPE_PROTOTYPE
//-------------------------------------------------------------------------
/**
* 单例
*/
String SCOPE_SINGLETON = "singleton";
/**
* 原型
*/
String SCOPE_PROTOTYPE = "prototype";
/**
* 父容器设置.而且一旦设置了就不让修改
* 搭配HierarchicalBeanFactory接口的getParentBeanFactory方法
*/
void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;
/**
* 类加载器设置与获取.默认使用当前线程中的类加载器
* 设置、返回工厂的类加载器
*/
void setBeanClassLoader(ClassLoader beanClassLoader);
/**
* 类加载器设置与获取.默认使用当前线程中的类加载器
*/
ClassLoader getBeanClassLoader();
/**
* 为了类型匹配,搞个临时类加载器.好在一般情况为null,使用上面定义的标准加载器
* 设置、返回一个临时的类加载器
*/
void setTempClassLoader(ClassLoader tempClassLoader);
/**
* 为了类型匹配,搞个临时类加载器.好在一般情况为null,使用上面定义的标准加载器
*/
ClassLoader getTempClassLoader();
/**
* 是否需要缓存bean metadata,比如bean difinition 和 解析好的classes.默认开启缓存
* 设置、是否缓存元数据,如果false,那么每次请求实例,都会从类加载器重新加载(热加载)
*/
void setCacheBeanMetadata(boolean cacheBeanMetadata);
/**
* 是否需要缓存bean metadata,比如bean difinition 和 解析好的classes.默认开启缓存
* 是否缓存元数据
*/
boolean isCacheBeanMetadata();
/**
* 定义用于解析bean definition的表达式解析器
* Bean表达式分解器
*/
void setBeanExpressionResolver(BeanExpressionResolver resolver);
/**
* 定义用于解析bean definition的表达式解析器
*/
BeanExpressionResolver getBeanExpressionResolver();
/**
* 设置、返回一个转换服务
*/
void setConversionService(ConversionService conversionService);
/**
* 类型转化器
*/
ConversionService getConversionService();
/**
* 设置属性编辑登记员...
*/
void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);
/**
* 注册常用属性编辑器
*/
void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass);
/**
* 用工厂中注册的通用的编辑器初始化指定的属性编辑注册器
*/
void copyRegisteredEditorsTo(PropertyEditorRegistry registry);
/**
* BeanFactory用来转换bean属性值或者参数值的自定义转换器
* 设置、得到一个类型转换器
* @see #registerCustomEditor
*/
void setTypeConverter(TypeConverter typeConverter);
/**
* BeanFactory用来转换bean属性值或者参数值的自定义转换器
*/
TypeConverter getTypeConverter();
/**
* 增加一个嵌入式的StringValueResolver
*/
void addEmbeddedValueResolver(StringValueResolver valueResolver);
/**
* Determine whether an embedded value resolver has been registered with this
* bean factory, to be applied through {@link #resolveEmbeddedValue(String)}.
* @since 4.3
*/
boolean hasEmbeddedValueResolver();
/**
* string值解析器分解指定的嵌入式的值
*/
String resolveEmbeddedValue(String value);
/**
* BeanPostProcessor用于增强bean初始化功能
* /设置一个Bean后处理器
*/
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
/**
* 返回Bean后处理器的数量
*/
int getBeanPostProcessorCount();
/**
* 注册范围
*/
void registerScope(String scopeName, Scope scope);
/**
* 返回注册的范围名
* @see #registerScope
*/
String[] getRegisteredScopeNames();
/**
* 返回指定的范围
* @see #registerScope
*/
Scope getRegisteredScope(String scopeName);
/**
* 返回本工厂的一个安全访问上下文
*/
AccessControlContext getAccessControlContext();
/**
* 合并其他ConfigurableBeanFactory的配置,包括上面说到的BeanPostProcessor,作用域等
* 从其他的工厂复制相关的所有配置
*/
void copyConfigurationFrom(ConfigurableBeanFactory otherFactory);
/**
* 给指定的Bean注册别名
*/
void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException;
/**
* 根据指定的StringValueResolver移除所有的别名
*/
void resolveAliases(StringValueResolver valueResolver);
/**
* 返回指定Bean合并后的Bean定义
*/
BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
/**
* 判断指定Bean是否为一个工厂Bean
*/
boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException;
/**
* 设置一个Bean是否正在创建
*/
void setCurrentlyInCreation(String beanName, boolean inCreation);
/**
* 返回指定Bean是否已经成功创建
*/
boolean isCurrentlyInCreation(String beanName);
/**
* 注册一个依赖于指定bean的Bean
*/
void registerDependentBean(String beanName, String dependentBeanName);
/**
* 返回依赖于指定Bean的所欲Bean名
*/
String[] getDependentBeans(String beanName);
/**
* 返回指定Bean依赖的所有Bean名
*/
String[] getDependenciesForBean(String beanName);
/**
* 销毁指定的Bean
*/
void destroyBean(String beanName, Object beanInstance);
/**
* 销毁指定的范围Bean
*/
void destroyScopedBean(String beanName);
/**
* 销毁所有的单例类
*/
void destroySingletons();
}
第二条
第二条接口设计主线是以ApplicationContext
应用上下文接口为核心的接口设计。这里涉及到的主要接口设计有,从BeanFactory
到ListableBeanFactory
,再到ApplicationContext
,再到我们常用的WebApplicationContext
或者ConfigurableApplicationContext
接口。我们常用的应用上下文基本上都是ConfigurableApplicationContext
或者WebApplicationContext
的实现。在这个接口体系中,ListableBeanFactory
和HierarchicalBeanFactory
两个接口,连接BeanFactory
接口定义和ApplicationContext
应用上下文的接口定义。对于ApplicationContext
接口,它通过继承MessageSource
, ResourceLoader
,ApplicationEventPublisher
接口,在BeanFactory
简单IOC容器的基础上添加了许多对高级容器的特性的支持。
MessageSource
MessageSource是一个解析消息的策略接口,它支持参数化与国际化。
/**
* 用于解析消息的策略接口,支持此类消息的参数化和国际化
*/
public interface MessageSource {
/**
* 解析消息,如果没找到code对应的消息就返回defaultMessage
*/
@Nullable
String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
/**
* 解析消息,如果没找到code对应的消息就抛异常
*/
String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;
/**
* 使用MessageSourceResolvable中的所有属性解析消息
* MessageSourceResolvable用code[]是啥意思呢???
*/
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
}
ListableBeanFactory
BeanFactory定义的都是对单个bean进行的操作,而ListableBeanFactory定义的操作大多数都是返回多个bean或者bean相关元素。从“Listable”就可以看出来,它定义了一些对bean进行列表化的操作。因此,ApplicationContext也可以对bean进行一些列表化操作。
/**
* 可以枚举所有bean实例,而不是按客户端的请求逐个尝试按名称查找bean
*/
public interface ListableBeanFactory extends BeanFactory {
/**
* 是否存在指定name的BeanDefinition
*/
boolean containsBeanDefinition(String beanName);
/**
* 获取BeanFactory中BeanDefinition的数量
*/
int getBeanDefinitionCount();
/**
* 获取所有BeanDefinition的名字
*/
String[] getBeanDefinitionNames();
/**
* 获取指定类型的beanName数组
*/
String[] getBeanNamesForType(ResolvableType type);
/**
* 获取指定类型的beanName数组
*/
String[] getBeanNamesForType(@Nullable Class<?> type);
/**
* 获取指定类型的beanName数组,加了是否包含单例和非懒加载这几个限制
*/
String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
/**
* 获取指定类型的所有bean
*/
<T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException;
/**
* 获取指定类型的所有bean,加了是否包含单例和非懒加载这几个限制
*/
<T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
throws BeansException;
/**
* 获取指定注解类型的beanNames
*/
String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);
/**
* 获取指定类型的bean对象
*/
Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;
/**
* 根据beanName和指定注解类型获取注解bean对象
*/
@Nullable
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
throws NoSuchBeanDefinitionException;
}
ResourceLoader
ResourceLoader是一个资源加载的策略接口,继承这个接口说明ApplicationContext有资源加载的功能,这也是Spring容器的第一步操作——加载配置文件。因为配置文件定义了bean以及bean之间的关系,所以只有把配置文件加载进来才能创建、管理bean。
/**
* 资源加载的策略接口
*/
public interface ResourceLoader {
/** Pseudo URL prefix for loading from the class path: "classpath:". */
String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;
/**
* 返回指定路径的资源,这里只返回一个,说明不支持模式匹配
*/
Resource getResource(String location);
/**
* 返回统一的ClassLoader,而不是依赖于线程上下文ClassLoader
*/
@Nullable
ClassLoader getClassLoader();
}
ResourcePatternResolver
从名字就可以看出来,ResourcePatternResolver对ResourceLoader进行了扩展,它支持解析模式匹配的路径。
/**
* 解析模式匹配的路径,加载资源
*/
public interface ResourcePatternResolver extends ResourceLoader {
/**
* classpath url的前缀
*/
String CLASSPATH_ALL_URL_PREFIX = "classpath*:";
/**
* 解析模式匹配的路径,返回多个Resource
*/
Resource[] getResources(String locationPattern) throws IOException;
}
ApplicationEventPublisher
ApplicationEventPublisher定义了事件发布的功能,可以将事件发布给注册了此应用所有匹配的监听器。由此可见,ApplicationContet也可以发布事件。
/**
* 定义了事件发布功能
*/
@FunctionalInterface
public interface ApplicationEventPublisher {
default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
/**
* 通知在此应用程序中注册的所有匹配的listeners
*/
void publishEvent(Object event);
}
EnvironmentCapable
EnvironmentCapable中只定义了getEnvironment的方法,向外界暴露了Environment接口。Environment是Spring运行时的环境,它包含了profiles和properties。
public interface EnvironmentCapable {
Environment getEnvironment();
}