随笔分类
容器扩展
本次主要来分析 AbstractApplicationContext.fresh()
前面的视角都主要放在了 BeanFactory接口之上,实际在工作开发过程中,并不会直接玩 BeanFactory,而是选择 ApplicationContext接口实现
这一次,让我们彻底来弄清楚 BeanFactory和 ApplicationContext二者之间的关系!
ApplicationContext内部持有了 BeanFactory,ApplicationContext会在 BeanFactory初始过程中进行一些相关的处理,让 BeanFactory能够去具备某些特性
fresh
fresh()中 规定了 IOC容器的启动流程
预处理上下文环境
prepareRefresh
/**
* 预处理上下文环境
*/
protected void prepareRefresh() {
// Switch to active.
// 设置容器的启动时间
this.startupDate = System.currentTimeMillis();
// 设置标志,表示容器是启动状态的
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Initialize any placeholder property sources in the context environment.
/** 留给子类去扩展的方法 **/
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
/** 校验必须有的环境变量 **/
/** 如果校验到缺少了某些环境变量的话, 会导致 IOC容器启动失败 **/
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
initPropertySources
留给子类去扩展的方法
/**
* 符合 Spring开放式结构设计, 给用户最大扩展 Spring的能力
* 用户可以根据自身需要来重写 initPropertySources方法, 并在方法中进行个性化的属性处理及其设置
* 如:重写了 该方法:
* 添加了验证要求: getEnvironment().setRequiredProperties("liangye")
* 那么就会在 getEnvironment().validateRequiredProperties() 时来进行验证是否存在 该环境变量. 不存在的话则会抛出异常, 容器启动失败
*/
protected void initPropertySources() {
// For subclasses: do nothing by default.
}
validateRequiredProperties
校验必须要有的环境变量
@Override
public void validateRequiredProperties() throws MissingRequiredPropertiesException {
this.propertyResolver.validateRequiredProperties();
}
@Override
public void validateRequiredProperties() {
MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
/**
* 可见 Spring容器初始化时,会从集合 requiredProperties中取出所有 key, 然后来获取这些 key的环境变量 (包括系统环境变量和进程环境变量)
* 如果有一个 key对应的环境变量为空的话,就会抛出异常,导致 Spring容器初始化失败
*/
for (String key : this.requiredProperties) {
if (this.getProperty(key) == null) {
ex.addMissingRequiredProperty(key);
}
}
if (!ex.getMissingRequiredProperties().isEmpty()) {
throw ex;
}
}
获取 DefaultListableBeanFactory
获取到一个功能最为强大的 BeanFactory
obtainFreshBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
/** refreshBeanFactory才是真正去干活的方法 **/
/** 初始化 beanFactory, 并进行 xml文件的读取, 并将得到的 BeanFactory记录在当前实体的属性中 **/
refreshBeanFactory();
// 返回当前实体 beanFactory属性
return getBeanFactory();
}
refreshBeanFactory
/**
* 这里会完成 销毁原有 beanFactory, 创建全新的 beanFactory以及相关逻辑操作
*/
@Override
protected final void refreshBeanFactory() throws BeansException {
/**
* 可以看出 ApplicationContext并非是去实现了 BeanFactory,而是持有了 BeanFactory的一个实现类
*/
/** true -> 说明当前 ApplicationContext内部拥有 BeanFactory接口实例, 当前需要去将该 BeanFactory实例完全释放掉 **/
if (hasBeanFactory()) {
// 销毁原 BeanFactory内部的实例的流程
destroyBeans();
/** 这里其实是去将 ApplicationContext内部的 beanFactory设置为 null, 因为后续还会去创建一个全新的 beanFactory **/
closeBeanFactory();
}
try {
// 创建了一个新的 beanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 这里会去检查 bd是否允许覆盖、是否允许循环依赖等
/** 这里已经开始了对 BeanFactory的扩展 **/
customizeBeanFactory(beanFactory);
/** 执行加载 bd信息的逻辑 **/
/** 通过 对应的 Reader(如:XmlBeanDefinitionReader)去读取配置并将其解析成 bd, 后将 bd注册到容器中去 **/
/** 这一步完成后, 所有的配置信息就已经注册到 beanFactory中去了, 注意的是, 此时还没有去创建 bean实例 **/
loadBeanDefinitions(beanFactory);
// 保留引用
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
destroyBeans
protected void destroyBeans() {
/** 销毁原 BeanFactory内部的单实例 **/
getBeanFactory().destroySingletons();
}
destroySingletons
# DefaultListableBeanFactory
@Override
public void destroySingletons() {
/** 会将 BeanFactory内部维护的单实例全部清除掉, 如果哪个 bean有实现 DisposableBean接口的话, 会去进行 析构回调 destroy **/
super.destroySingletons();
updateManualSingletonNames(Set::clear, set -> !set.isEmpty());
clearByTypeCache();
}
# DefaultSingletonBeanRegistry
/**
* 执行销毁单实例相关逻辑
*/
public void destroySingletons() {
if (logger.isTraceEnabled()) {
logger.trace("Destroying singletons in " + this);
}
synchronized (this.singletonObjects) {
// 设置该属性, 说明当前 beanFactory状态转为了销毁状态
this.singletonsCurrentlyInDestruction = true;
}
/**
* disposable? 创建单实例时, 会检查当前单实例类型是否实现了 DisposableBean接口, 如果实现了该接口
* 对应的, 当该单实例 bean销毁时 (容器销毁时), 会去执行相应的析构回调 destroy
*/
String[] disposableBeanNames;
synchronized (this.disposableBeans) {
/**
* 实现了 DisposableBean接口的 bean在销毁时,需要执行 destroy() 析构回调
* 因此, 这里会来获取实现了 Disposable接口的 单实例 beanName
*/
disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
}
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
this.containedBeanMap.clear();
/** 清空寻找依赖的那两个 map**/
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
clearSingletonCache();
}
destroySingleton
public void destroySingleton(String beanName) {
// Remove a registered singleton of the given name, if any.
/** 从缓存中移除当前 bean **/
removeSingleton(beanName);
// Destroy the corresponding DisposableBean instance.
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
/** bean在创建时如果满足了注册回调要求的话, 会将其存入 disposablesBeans中去 **/
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
/** 销毁当前 bean, 清除对应的依赖信息 **/
destroyBean(beanName, disposableBean);
}
removeSingleton
/**
* Remove the bean with the given name from the singleton cache of this factory,
* to be able to clean up eager registration of a singleton if creation failed.
* @param beanName the name of the bean
* @see #getSingletonMutex()
* 这里执行的是从缓存中移除对应 beanName的 单实例 bean
*/
protected void removeSingleton(String beanName) {
synchronized (this.singletonObjects) {
/** 从 1级 ... **/
this.singletonObjects.remove(beanName);
/** 从 3级 ... **/
this.singletonFactories.remove(beanName);
/** 从 2级 ... **/
this.earlySingletonObjects.remove(beanName);
/** 从 IOC注册的已创建的 bean实例缓存中移除 **/
this.registeredSingletons.remove(beanName);
}
}
destroyBean
protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
// Trigger destruction of dependent beans first...
Set<String> dependencies;
/** 这里会来处理当前 bean的依赖关系 **/
/**
* dependentBeanMap -> 表示依赖于当前 bean的其他 bean信息
* 假设 b、c、d依赖于 a, 那么 map中就会保存着 {key = 'a', {b、c、d}}的一个 数据
*/
synchronized (this.dependentBeanMap) {
// Within full synchronization in order to guarantee a disconnected Set
dependencies = this.dependentBeanMap.remove(beanName);
}
if (dependencies != null) {
if (logger.isTraceEnabled()) {
logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
}
/** 这里类似递归删除 bean的一个过程 **/
/** 因为依赖对象要被回收了, 因此依赖于当前 bean的其它 bean, 都要执行 destroySingleton逻辑 **/
for (String dependentBeanName : dependencies) {
destroySingleton(dependentBeanName);
}
}
// Actually destroy the bean now...
if (bean != null) {
try {
/** 执行当前 bean的析构方法 **/
bean.destroy();
}
catch (Throwable ex) {
if (logger.isWarnEnabled()) {
logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex);
}
}
}
/** 这部分逻辑先去忽略 **/
// Trigger destruction of contained beans...
Set<String> containedBeans;
synchronized (this.containedBeanMap) {
// Within full synchronization in order to guarantee a disconnected Set
containedBeans = this.containedBeanMap.remove(beanName);
}
if (containedBeans != null) {
for (String containedBeanName : containedBeans) {
destroySingleton(containedBeanName);
}
}
// Remove destroyed bean from other beans' dependencies.
/** 因为当前 bean被析构了, 因此它不应该存在于任何依赖信息里面了 **/
synchronized (this.dependentBeanMap) {
for (Iterator<Map.Entry<String, Set<String>>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) {
Map.Entry<String, Set<String>> entry = it.next();
Set<String> dependenciesToClean = entry.getValue();
dependenciesToClean.remove(beanName);
if (dependenciesToClean.isEmpty()) {
it.remove();
}
}
}
/** dependenciesForBeanMap 当前 bean依赖其它 bean的描述信息也需要被移除... **/
// Remove destroyed bean's prepared dependency information.
this.dependenciesForBeanMap.remove(beanName);
}
closeBeanFactory
@Override
protected final void closeBeanFactory() {
DefaultListableBeanFactory beanFactory = this.beanFactory;
/** 这里其实是去将 ApplicationContext内部的 beanFactory设置为 null, 因为后续还会去创建一个全新的 beanFactory **/
if (beanFactory != null) {
beanFactory.setSerializationId(null);
this.beanFactory = null;
}
customizeBeanFactory
/**
* 这里就已经开始了对 BeanFactory的扩展
* 增加了是否允许覆盖、是否允许循环依赖的配置
*/
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
// 是否允许设置 BeanDefinition的 重写覆盖
/**
* allowBeanDefinitionOverriding 默认为 true, 表示 beanFactory内部管理的 bd信息允许被重写
*/
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
// 是否去设置循环引用
/** beanFactory是默认允许循环依赖的 **/
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
预处理创建出来的 beanFactory
prepareBeanFactory
/**
* 总结:prepareBeanFactory主要做了哪些方面的扩展 ?
* 增加了对 SpEL语言的支持
* 增加了对 属性编辑器的支持
* 添加后置处理器 ApplicationContextAwareProcessor
* 设置了依赖功能可忽略的接口
* 注册一些固定依赖的属性
* and so on
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
/** 给当前 beanFactory设置一个用于加载 bd的 Class信息的 类加载器 **/
beanFactory.setBeanClassLoader(getClassLoader());
if (!shouldIgnoreSpel) {
/**
* 原来 Spring还支持 EL表达式... 长见识了...
* 默认可以使用 #{bean.xxx} 的形式来调用相关属性值
* 既然存在 Spring EL表达式, 那谁来进行解析? StandardBeanExpressionResolver
* 那什么时候会去调用 这个解析器来进行解析呢 ?
* 应用语言解析器的调用主要是在 依赖注入 populateBean方法中调用 applyPropertyValues函数来完成此功能
*/
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
/**
* BeanWrapper 本身就是属性编辑器注册中心(实现了 PropertyEditorRegistry), 属性编辑器作用于 beanWrapper内部管理的真实 bean 注入字段值时
* 当某个字段对应的类型 在 beanWrapper中有对应的 属性编辑器, 那么对于类型的字段值 就会由该 属性编辑器 代理写入
*/
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
/** 添加后置处理器, 该后置处理器主要用于向 bean内部注入一些框架级别的实例, 比如说:环境变量、ApplicationContext等 **/
/** 真正的逻辑还是在 ApplicationContextAwareProcessor中 **/
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
/** 忽略指定类型的依赖 **/
/** 设置了几个忽略自动装配的接口 **/
/** 即若是 bean内部有这些类型的字段的话, 这些字段是不会参与 依赖注入的 **/
/** 因为在上述已经添加了后置处理器 ApplicationContextAwareProcessor, 在处理器中调用的 Aware类不是一般的 bean, 因此要在此设置忽略 **/
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
/** 注册一些类型 依赖关系 **/
/** 设置了几个自动装配的特殊规则 **/
/** 如:一旦注册了对 BeanFactory.class的解析依赖后, 一旦在 bean的属性注入时检测到属性类型为 BeanFactory类型, 此时便会将 beanFactory的实例注册进去 **/
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
/** 该后置处理器将配置的监听者注册到 容器中 ac **/
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
/**
* 添加一些默认配置 默认 bean
*/
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}
注册属性编辑器 registerCustomEditors
/**
* 实现了批量注册的功能
*/
@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
/** 这里来注册了一系列常用的属性编辑器, 当某 bean中存在对应类型的 字段时, 在依赖注入时就会由 对应的属性编辑器来记性代理注入操作 (其实就是来转换类型) **/
ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver);
doRegisterEditor(registry, Resource.class, baseEditor);
doRegisterEditor(registry, ContextResource.class, baseEditor);
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
doRegisterEditor(registry, Path.class, new PathEditor(baseEditor));
doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));
ClassLoader classLoader = this.resourceLoader.getClassLoader();
doRegisterEditor(registry, URI.class, new URIEditor(classLoader));
doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader));
if (this.resourceLoader instanceof ResourcePatternResolver) {
doRegisterEditor(registry, Resource[].class,
new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver));
}
}
这里实际上就是来注册了一系列常用的属性编辑器,一旦 bean中存在某些字段类型与注册的类型相对应时, 那么在该字段的注入时会去调用对应的 属性编辑器来进行代理操作
虽然这个方法提供了一系列批量注册的功能,那么实际上在什么时候会进行 此方法的调用?
查看调用链可知:AbstractBeanFactory中的 initWarpper()时会去调用
protected void initBeanWrapper(BeanWrapper bw) {
bw.setConversionService(getConversionService() /** 类型转换器 **/);
/** 来注册一些属性编辑器 **/
registerCustomEditors(bw);
}
这下就能讲通了!
beanWrapper是什么? bean的封装类,将 bean封装起来,以便后续进行一些相关的操作
在 bean进行依赖注入前,就已将 bean封装成了 beanWrapper,此时会去调用 initBeanWrapper方法,此时便会去调用 registerCustomEditors
在 bean的依赖注入前,就会去调用 ResourceEditorRegistrar的 registerCustomEditors方法进行批量的通用的属性编辑器的注册
注册后,在 bean的属性填充环节,便可以让 Spring去使用这些属性编辑器来进行属性的解析操作了
这里再提一点:BeanWrapper 本身就是 属性编辑器注册中心
(实现了 PropertyEditorRegistry), 属性编辑器作用于 beanWrapper内部管理的真实 bean 注入字段值时
当某个字段对应的类型 在 beanWrapper中有对应的 属性编辑器, 那么对于类型的字段值 就会由该 属性编辑器 代理写入
添加 ApplicationContextAwareProcessor处理器
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
bean instanceof ApplicationStartupAware)) {
return bean;
}
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
/** 这才是核心方法 **/
invokeAwareInterfaces(bean);
}
return bean;
}
/** 根据实现的具体 Aware接口来激活指定方法,set某些信息进去 **/
/** 根据 bean实现的具体 Aware接口, 可以在 bean初始化之后, 可以来去的一些对应的资源 **/
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationStartupAware) {
((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}