spring源碼學習筆記,要點歸納和代碼理解
前言
在前面的學習中,一直以BeanFatory為中心,分析了配置文件的加載、解析過程和BeanFactory對注入對象的創(chuàng)建過程。
Spring提供了另一個接口ApplicationContext接口,它提供了所有BeanFactory的功能,并進一步擴展了作為容器的功能。
本節(jié)將跟隨源碼探究其提供的擴展以及實現(xiàn)原理。
一. ApplicationContext容器的概覽和refresh()方法中的行為
-
選用XmlApplicationContext作為切入點進行分析。照例看一下繼承結構。
debug跟一下構造方法,發(fā)現(xiàn)其核心功能全部在AbstractApplicationContext的refresh()方法中.

- refresh方法的中的行為
這里貼出refresh方法的代碼
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 準備刷新的上下文環(huán)境
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 通知實現(xiàn)類初始化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.
// 對實現(xiàn)類覆蓋的方法做額外處理
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 激活BeanFactory處理器
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注冊攔截Bean創(chuàng)建的Bean處理器,這里只進行注冊,調用在getBean時
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 為上下文環(huán)境初始化Message源,國際化處理
initMessageSource();
// Initialize event multicaster for this context.
// 初始化事件廣播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 留給子類重寫其他需要在刷新上下文環(huán)境時做的
onRefresh();
// Check for listener beans and register them.
// 注冊監(jiān)聽器
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中的各方法行為解析
- 初始化的環(huán)境準備: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
// 校驗環(huán)境參數(shù)
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()方法可以由子類重寫,貼一個簡單的應用場景.
假如某工程中需要一個環(huán)境變量機房編號roomnumber,此變量缺失將導致工程崩潰,要求缺失此變量時無法啟動工程.
我們可以自定義MyClassPathXmlApplicationContext,重寫initPropertySources方法,其中加入相關邏輯如下:
public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {
public MyClassPathXmlApplicationContext(String location) {
super(location);
}
@Override
public void initPropertySources() {
getEnvironment().setRequiredProperties("roomnumber");
}
}
則在啟動時拋出異常

啟動參數(shù)中添加-Droomnumber=5,則正常啟動

- 加載BeanFactory :obtainFreshBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 刷新beanFactory
refreshBeanFactory();
return getBeanFactory();
}
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 創(chuàng)建一個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的功能,這里設置了是否允許循環(huán)依賴和是否允許方法重寫,依舊支持子類重寫
如下:
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.
// 這只幾個自動裝配的特殊規(guī)則
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.
// 添加內置的監(jiān)聽器作為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()));
}
// 添加幾個默認的系統(tǒng)環(huán)境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());
}
}
這里實現(xiàn)了對原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處理器
小結
本節(jié)講解了ApplicationContext對BeanFactory的功能初始化擴展,對BeanFactory的后處理將在下節(jié)繼續(xù)分析.
