Spring读源码系列06----容器扩展功能--上
Posted 大忽悠爱忽悠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring读源码系列06----容器扩展功能--上相关的知识,希望对你有一定的参考价值。
Spring读源码系列06----容器扩展功能---上
- ApplicationContext
- ClassPathXmlApplicationContext构造函数
- AbstractRefreshableConfigApplicationContext#setConfigLocations---设置配置文件路径
- AbstractApplicationContext#refresh---刷新容器
- AbstractApplicationContext#prepareRefresh---环境准备
- AbstractApplicationContext#obtainFreshBeanFactory---加载BeanFactory
- AbstractApplicationContext#prepareBeanFactory---功能扩展
- 增加属性注册编译器
ApplicationContext
- 使用BeanFactory方式加载XML
ClassPathResource classPathResource = new ClassPathResource("bean.xml");
BeanFactory xmlBeanFactory = new XmlBeanFactory(classPathResource);
- 使用ApplicationContext方式加载XML
ApplicationContext bc=new ClassPathXmlApplicationContext("bean.xml");
ClassPathXmlApplicationContext构造函数
public ClassPathXmlApplicationContext(String configLocation) throws BeansException
this(new String[]configLocation, true, (ApplicationContext)null);
|
|
\\|/
|
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException
super(parent);
//设置配置文件路径
this.setConfigLocations(configLocations);
if (refresh)
//刷新容器
this.refresh();
AbstractRefreshableConfigApplicationContext#setConfigLocations—设置配置文件路径
public void setConfigLocations(@Nullable String... locations)
if (locations != null)
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for(int i = 0; i < locations.length; ++i)
//解析给定配置文件路径
this.configLocations[i] = this.resolvePath(locations[i]).trim();
else
this.configLocations = null;
protected String resolvePath(String path)
//ConfigurablePropertyResolver负责解析path路径
return this.getEnvironment().resolveRequiredPlaceholders(path);
AbstractApplicationContext#refresh—刷新容器
public void refresh() throws BeansException, IllegalStateException
//startupShutdownMonitor可以确保当前应用在刷新过程中是同步的
synchronized(this.startupShutdownMonitor)
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
//准备此上下文以进行刷新、设置其启动日期和活动标志以及执行任何属性源的初始化。
this.prepareRefresh();
//初始化BeanFactory,并进行xml文件读取---原beanFactory的初始化步骤在这一步完成
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//配置工厂的标准上下文特征,例如上下文的 ClassLoader 和后处理器。
this.prepareBeanFactory(beanFactory);
try
//子类覆盖父类方法做额外处理:
//在标准初始化之后修改应用程序上下文的内部 bean 工厂。
//所有 bean 定义都将被加载,但还没有 bean 被实例化。
//这允许在某些 ApplicationContext 实现中注册特殊的 BeanPostProcessors 等。
this.postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
//触发bean工厂后置处理器
this.invokeBeanFactoryPostProcessors(beanFactory);
//注册拦截bean创建的bean处理器,这里只是注册,真正调用是在getBean的时候
this.registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
//为上下文初始化Message源,即不同语言的消息体,国际化处理
this.initMessageSource();
//初始化应用消息广播器,并放入ApplicationEventMulticaster中
this.initApplicationEventMulticaster();
//保留给子类来初始化其他bean
this.onRefresh();
//在所有注册的bean中查找Listener bean,注册到消息广播器中
this.registerListeners();
//初始化剩下的单实例(非懒加载的bean)
this.finishBeanFactoryInitialization(beanFactory);
//完成此上下文的刷新,调用 LifecycleProcessor 的 onRefresh() 方法并发布 ContextRefreshedEvent。
this.finishRefresh();
catch (BeansException var10)
if (this.logger.isWarnEnabled())
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
this.destroyBeans();
this.cancelRefresh(var10);
throw var10;
finally
//重置 Spring 核心中的常见自省缓存,因为我们可能不再需要单例 bean 的元数据......
this.resetCommonCaches();
contextRefresh.end();
AbstractApplicationContext#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());
// 初始化上下文环境中的任何占位符属性源---该方法也是留给子类去覆盖的(例如:我们可以自定义占位符)
initPropertySources();
// 验证标记为必需的所有属性都是可解析的---需要的属性文件是否都已经放入环境中
getEnvironment().validateRequiredProperties();
//监听器的预处理
// Store pre-refresh ApplicationListeners...
//earlyApplicationListeners: 刷新前注册的本地侦听器
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<>();
设置状态为激活,初始化属性源,验证必须的属性是否都是可解析的,预处理监听器
AbstractApplicationContext#obtainFreshBeanFactory—加载BeanFactory
//告诉子类刷新内部 bean 工厂。返回:新鲜的 BeanFactory 实例
protected ConfigurableListableBeanFactory obtainFreshBeanFactory()
//初始BeanFactory,并对XML文件进行读取,并将得到的BeanFactory记录在当前实体的属性中
refreshBeanFactory();
//返回当前实体的BeanFactory属性
return getBeanFactory();
AbstractRefreshableApplicationContext#refreshBeanFactory—初始化BeanFactory,读取xml啥的
/**
* This implementation performs an actual refresh of this context's underlying
* bean factory, shutting down the previous bean factory (if any) and
* initializing a fresh bean factory for the next phase of the context's lifecycle.
*/
@Override
protected final void refreshBeanFactory() throws BeansException
//因为ApplicationContext内部会拥有一个BeanFactory实例(又因为ApplicationContext继承了BeanFactory,个人感觉有点像装饰器模式)
//这里判断当前ApplicationContext是否有旧的BeanFactory实例,如果有的话,就销毁BeanFactory工厂里面的单例bean,然后清空BeanFacotry
if (hasBeanFactory())
destroyBeans();
closeBeanFactory();
try
//创建DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
//为了序列化指定id,如果需要的话,让这个BeanFactory从id反序列化到BeanFactory对象
beanFactory.setSerializationId(getId());
//定制beanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及循环依赖
customizeBeanFactory(beanFactory);
//初始DocumentReader,并进行XML文件读取及解析
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
catch (IOException ex)
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
ApplicationContext与BeanFactory的关系
在ApplicationContext内部会维护一个BeanFactory的实例,并且ApplicationContext继承了BeanFactory,这是不是很像设计模式中的装饰器模式
因此在我看来,spring在此处就是运用了装饰器模式,对BeanFactory完成了功能的扩展
AbstractRefreshableApplicationContext#createBeanFactory—创建bean工厂
创建的就是DefaultListableBeanFactory,getInternalParentBeanFactory()方法是在设置了父类容器的情况下才会返回非NULL结果
protected DefaultListableBeanFactory createBeanFactory()
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
AbstractRefreshableApplicationContext#customizeBeanFactory—定制BeanFactory
//自定义此上下文使用的内部 bean 工厂。为每次 refresh() 尝试调用。
//默认实现应用此上下文的“allowBeanDefinitionOverriding”
//和“allowCircularReferences”设置(如果指定)。
//可以在子类中重写以自定义任何 DefaultListableBeanFactory 的设置。
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory)
//是否允许bean定义的覆盖
if (this.allowBeanDefinitionOverriding != null)
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
//是否允许循环依赖
if (this.allowCircularReferences != null)
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
AbstractXmlApplicationContext#loadBeanDefinitions—加载BeanDefinition
/**
* Loads the bean definitions via an XmlBeanDefinitionReader.
*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException
//xml--->BeanDefinition
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//允许子类提供阅读器的自定义初始化,然后继续实际加载 bean 定义。---这里只是简单对BeanDefinitionReader做个校验
initBeanDefinitionReader(beanDefinitionReader);
//这个方法比较重要
loadBeanDefinitions(beanDefinitionReader);
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException
Resource[] configResources = getConfigResources();
if (configResources != null)
reader.loadBeanDefinitions(configResources);
String[] configLocations = getConfigLocations();
if (configLocations != null)
reader.loadBeanDefinitions(configLocations);
AbstractApplicationContext#prepareBeanFactory—功能扩展
//配置工厂的标准上下文特征,例如上下文的 ClassLoader 和后处理器。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory)
//设置ApplicationContext内部的BeanFactory使用当前context的classLoader
beanFactory.setBeanClassLoader(getClassLoader());
//指示 Spring 是否需要忽略 SpEL,即不初始化 SpEL 基础结构。
//private static final boolean shouldIgnoreSpel = SpringProperties.getFlag("spring.spel.ignore");
//默认为false
if (!shouldIgnoreSpel)
//默认支持SPEL功能--即可以用#bean.xxx来调用相关属性值
//!!!
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//为BeanFactory增加一个ResourceEditorRegistrar
//PropertyEditorRegistrar:属性编辑器的登记注册,该类用来注册相关属性编辑器
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
//添加BeanPostProcessor
//这里默认添加的一个ApplicationContextAwareProcessor是用来处理实现aware接口的注入功能的
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//设置了几个忽略自动装配的接口---如果我们想在程序中自动注入这些接口的话,显然不太行
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);
//设置了几个自动装配的特殊规则---如果我们在程序中注入下面这个几个bean,是可以成功的
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
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.
//将用于检测内部 bean 的早期后处理器注册为 ApplicationListener。----检测实现 ApplicationListener 接口的 bean
//如果找到这样的bean,并且是单例的,那么就可以添加进applicationListeners集合中去
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
//增加对AspectJ的支持
// 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()));
// Register default environment beans.
//添加系统默认的环境bean,并且是在不存在的情况下才会去添加
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME))
//getEnvironment()默认返回Environent---这也是为什么我们可以直接注入使用
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以上是关于Spring读源码系列06----容器扩展功能--上的主要内容,如果未能解决你的问题,请参考以下文章
Spring读源码系列番外篇---06----类型转换---下---ConversionService相关家族
Spring读源码系列之AOP--06---AopProxy===>spring使用jdk和cglib生成代理对象的终极奥义