spring源码学习笔记,要点归纳和代码理解
前言
在前面的学习中,一直以BeanFatory为中心,分析了配置文件的加载、解析过程和BeanFactory对注入对象的创建过程。
Spring提供了另一个接口ApplicationContext接口,它提供了所有BeanFactory的功能,并进一步扩展了作为容器的功能。
本节将跟随源码探究其提供的扩展以及实现原理。
一. ApplicationContext容器的概览和refresh()方法中的行为
-
选用XmlApplicationContext作为切入点进行分析。照例看一下继承结构。
debug跟一下构造方法,发现其核心功能全部在AbstractApplicationContext
的refresh()
方法中.
![](https://img.haomeiwen.com/i3507249/91a14e900144d14d.png)
- refresh方法的中的行为
这里贴出refresh方法的代码
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 准备刷新的上下文环境
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 通知实现类初始化BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 对BeanFactory的各种功能进行填充
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 对实现类覆盖的方法做额外处理
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 激活BeanFactory处理器
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册拦截Bean创建的Bean处理器,这里只进行注册,调用在getBean时
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 为上下文环境初始化Message源,国际化处理
initMessageSource();
// Initialize event multicaster for this context.
// 初始化事件广播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 留给子类重写其他需要在刷新上下文环境时做的
onRefresh();
// Check for listener beans and register them.
// 注册监听器
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 初始化剩下的非懒加载的单实例对象
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 完成初始化
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
refresh中的各方法行为解析
- 初始化的环境准备:prepareRefresh
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
// Initialize any placeholder property sources in the context environment.
// 初始化配置源,子类可重写此方法
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
// 校验环境参数
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()方法可以由子类重写,贴一个简单的应用场景.
假如某工程中需要一个环境变量机房编号roomnumber
,此变量缺失将导致工程崩溃,要求缺失此变量时无法启动工程.
我们可以自定义MyClassPathXmlApplicationContext
,重写initPropertySources
方法,其中加入相关逻辑如下:
public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {
public MyClassPathXmlApplicationContext(String location) {
super(location);
}
@Override
public void initPropertySources() {
getEnvironment().setRequiredProperties("roomnumber");
}
}
则在启动时抛出异常
![](https://img.haomeiwen.com/i3507249/6ccffd7923cfd4f9.png)
启动参数中添加-Droomnumber=5,则正常启动
![](https://img.haomeiwen.com/i3507249/681920ff79967a0f.png)
- 加载BeanFactory :obtainFreshBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 刷新beanFactory
refreshBeanFactory();
return getBeanFactory();
}
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建一个DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 定制beanFactory功能
customizeBeanFactory(beanFactory);
// 加载BeanDefinition
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
加载的BeanFactory还是我们之前分析的DefaultListableBeanFactory, 之后客制化BeanFactory的功能,这里设置了是否允许循环依赖和是否允许方法重写,依旧支持子类重写
如下:
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
最后加载BeanDefinition,加载仍然使用了XmlBeanDefinitionReader,这里不再贴出代码
- 功能扩展 : prepareBeanFactory
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
// 添加EL表达式解析器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 添加属性解析器
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
// 把自己添加为beanPost处理器
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 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.
// 添加内置的监听器作为beanPost处理器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
// 添加几个对AspectJ的支持
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());
}
}
这里实现了对原BeanFactory功能的几个扩展:
- 添加SpEl表达式的支持
- 增加属性注册编辑器
在Spring 进行DI注入时,对Date对象注入属性时,无法被识别,可以添加自定义的属性编辑器:
public class DatePropertyEditorRegistrar implements PropertyEditorRegistrar {
@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
}
}
将属性编辑器注入到容器中:
<bean name="student" class="com.pctf.contextextend.bean.Student">
<property name="name" value="pctf"></property>
<property name="birth" value="1900-11-08"></property>
</bean>
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="propertyEditorRegistrars">
<list>
<bean class="com.pctf.contextextend.propertyeditorregister.DatePropertyEditorRegistrar"></bean>
</list>
</property>
</bean>
- 添加ApplicationContextAwareProcessor处理器
小结
本节讲解了ApplicationContext对BeanFactory的功能初始化扩展,对BeanFactory的后处理将在下节继续分析.
网友评论