代码的入口:
@Test
public void testFileXmlApplicationContext() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring/spring.xml");
Person person = applicationContext.getBean("person", Person.class);
person.info();
}
其中 ClassPathXmlApplicationContext 的类的继承层次图:
Spring加载的时序图:
这个过程中关键的方法是 AbstractApplicationContext,这个方法中挂念的方法是 refresh()方法。这个方法中有13个步骤。refresh是一个典型的模板模式,其中对应ApplicationContext的加载是在AbstractApplicationContext中实现的。其中依赖的一个步骤是交给不同的子类来实现的。分别对这个13个步骤进行描述:
1.prepareRefresh();// Prepare this context for refreshing.准备一下,这个Context将会进行刷新。
//为刷新准备此上下文,设置其启动日期和
//活动标志以及执行属性源的初始化。
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// 初始化所有的上下文环境中的占位符属性元,点进去一看啥都没有。
initPropertySources();
// 验证所有的required属性被正确的设置。//这个到底干了啥呀?这个requred属性到底是那些呢?这个没有用过。
getEnvironment().validateRequiredProperties();
// 先将ApplicationEvent的队列给建立起来。
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
2、ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 这个是一个将BeanFactoy的加载的过程,这个方法执行完毕后,所有的定义的BeanDefinition和其他的对象都会被加载到当前BeanFactory中来
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();//刷新一下BeanFactory,这个方法是一个抽象方法,具体的实现是在其子类(AbstractRefreshableApplicationContext)中实现的。
ConfigurableListableBeanFactory beanFactory = getBeanFactory();//获取到对应的BeanFactory,然后返回。
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
可以看一下 (AbstractRefreshableApplicationContext)中的refreshBeanFactory()方法。
2.1、refreshBeanFactory()
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
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,如果有的话,将BeanFactory ,缓存等相关信息清空。
第二步:创建一个DefaultListableBeanFactory,其中BeanFactory就创建在AbstractRefreshableApplicationContext中进行维护。
第三步:定制当前的BeanFactory,这个主要是能否进行重写和循环引用。
第四步:加载所有的Beans到BeanFactory中来。loadBeanDefinitions(DefaultListableBeanFactory beanFactory)。这个方法是一个抽象方法。这个方法没有实现。交给了子类去实现。
这个方法没有实现的原因:当前的类是AbstractRefreshableApplicationContext中,当前的对象并不知道Resource是哪一个,没有办法确认应该将加载的任务委托给哪一个BeanDefinitionReader。对于 AbstractRefreshableApplicationContext 来讲,就是讲 refreshBeanFactory就是将BeanFactory创建好,并加载好。当时如何加载的还不能确定,这个需要交给底层的方法去实现。
2.2、loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
这个时候看下loadBeanDefinitions(beanFactory) 是如何实现的。
这个方法是在AbstractXmlApplicationContext中实现的。,从类名中可以看出这个方法是XML的,主要是处理以Xml的方式定义的BeanDefinition信息。AbstractXmlApplicationContext,这个类的两个子类是ClassPathXmlApplicationContext 和FileSystemXmlApplicationContext 。在子类中定义了Resource的类型。
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);//创建一个XmlBeanDefinitionReader,这个类的选择和 AbstractXmlApplicationContext 对应。
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());//设置当前的environment的对象。
beanDefinitionReader.setResourceLoader(this);//设置对应的ResourceLoader。 ApplicationContext是ResourceLoader的子类。
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);//设置 reader的属性validateing,设置是否使用xml验证。缺省是true。
loadBeanDefinitions(beanDefinitionReader);//加载对应的BeanDefinitionReader对象。
}
2.3、loadBeanDefinitions(XmlBeanDefinitionReader reader)
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();//首先是getResources().
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();//这里是所有定义的文件的地址。
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
其中:Resource[] getConfigResources() 这个方法是获取所有的Resource的方法。这个方法教给了子类ClassPathXmlApplicationContext或者是FilePathXmlApplicationContext实现的。
String[] getConfigLocations() 是AbstractRefreshableConfigApplicationContext,中定义的方法,这个其中在ClassPathXmlApplicationContext中的方法主要是通过这个 void setConfigLocations(String... locations)将配置文件地址的信息写到当前的对象中的。AbstractRefreshableConfigApplicationContext 类主要定义的就是当前FilePathXmlApplicationContext和ClassPathXmlApplicationContext中定义的locations地址。这个类一般是 ClassPathXmlApplicationContext 和FileSystemXmlApplicationContext 一起配套使用的。
3、prepareBeanFactory(beanFactory);//对Bean Factory中的一些其他的信息信息配置。
在上一步中主要是建立了一个DefaultListableBeanFactory,然后所有定义在xml文件中的 BeanDefinition的信息加载到当前的BeanDefinition中来。这个过程中BeanDefinition并没有被实例化,还是一些定义的信息。这里先对BeanFactoy中配置一些基础的参数。具体代码如下。将ClassLoader,一些其他的基础的类型加载到对应的系统中来。
4、postProcessBeanFactory(beanFactory)
在标准的 初始化之后,需要修改ApplicationContext中的内部BeanFactory的内容。所有的Bean Definition都被load,但是还没实例化。这能够实现将特定的 BeanPostProcessor注册到特定的 ApplicationContext的实现中去。这个方法是为了 AbstractApplicationContext 的子类来实现的。
5.invokeBeanFactoryPostProcessors(beanFactory);//触发后置处理器。
BeanFactoryPostProcessor这个类是BeanFactory 的PostProcessor的实现。BeanFactoryPostProcessor主要实现的可以对BeanDefinition的定义(配置数据,并不是实例化对象)进行处理。IOC容器允许BeanFactoryPostProcessor在实例化BeanDefinition之前对当前的配置数据进行修改。用户可以扩展多个BeanFactoryPostProcessor来实现对于BeanDefinition定义的数据进行修改。其中BeanFactoryPostProcessor主要是定义在了AbstractApplicationContext对象中。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
第一步是public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors)//将BeanFactoryPostProcessor 作用在当前的BeanFactory中去。
第二步是 其中如果当前的BeanFactoy中包含了 loadTimeWeaver bean的时候,这个时候需要配置一个LoadTimeWeaverAwareProcessor,同时添加一个 新的ClassLoader来实现加载是的Weaveer。
6、registerBeanPostProcessors(beanFactory);//注册BeanPostProcessor到当前的BeanFactory中去。
简单介绍下BeanPostProcessor;如果我们想对实例化后的BeanDefinition对象进行处理,可以通过实现一个 BeanPostProcessor的子类。BeanPostProcessor 是容器级别的,只有定义在一个容器中BeanPostProcessor才会作用。其中在ApplicationContext和BeanFactoy中是ApplicationContext会在refresh中将当前所有的BeanPostProcessor注册到BeanFactory中去。但是BeanFacoty需要自己手动的调用BeanFactoy中的addBeanPostProcessor来实现。
主要是调用 PostProcessorRegistrationDelegate 方法中对应的 registerBeanPostProcessors,方法来将所有的BeanProcessor注册到对应的BeanFactory中去的。
7.protected void initMessageSource()//初始化MesageSource
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {//如果BeanFactoy中已经定义了MessageSource的实例
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);//就使用这个MessageSource。
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {//然后看下如果这个Mesage是支持继承的,就把parenetBeanFactory(如果有)中的MessageSource放进去。
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isDebugEnabled()) {
logger.debug("Using MessageSource [" + this.messageSource + "]");
}
}
else {//如果没有定义,那么就使用一个默认的 DelegatingMessageSource 。
// Use empty MessageSource to be able to accept getMessage calls.
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
"': using default [" + this.messageSource + "]");
}
}
}
简而言之:MessageSource主要是首先看用户是否定义了,如果定义了再看下是否是支持继承的MessageSource,如果支持就把父BeanFacoty中的MessageSource设置进去。如果用户没有定义就设置一个默认的DelegatingMessageSource
8.initApplicationEventMulticaster();//初始化事件广播
主要实现是看用户是否自定了事件广播,如果定义了就设置为用户制定的事件广播,否知设置一个 默认的时间广播。
9.onRefresh()//这个方法是一个模板方法,是交给子类来扩展的。
10.registerListeners();//注册所有的Listener。
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
这个过程首先是将 当前AbstractApplicationContext中有的所有的ApplicationListener注册广播器中的Listener中去。
然后将所有的用户定义的ApplicationListener注册到广播中去。
然后将所有的 this.earlyApplicationEvents 中的定义的事件进行广播。
11.finishBeanFactoryInitialization(beanFactory);//实例化所有的非延迟加载的单例Bean对象。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
return getEnvironment().resolvePlaceholders(strVal);
}
});
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
首先为这个ApplicationContext设置 CONVERSIONSERVICE的BeanName。
然后对于 LoadTimeWeaverAware 的Bean进行加载。
将零时的ClassLoader设置为null。
清空缓存 frozenBeanDefinitionNames
初始化剩余的所有的 非懒加载的 单例Singleton的单实例。
12:finishRefresh();// 发布相关的事件
protected void finishRefresh() {
// 为这个ApplicationContext设置LifecycleProcessor。
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
第一步是如果当前容器中没有 定义LifeCleProcessor那么就使用一个默认的 DefaultLifecycleProcessor。关于LifeCycleProcessor的相关知识,会后面单独来将,这里按下不表。
第二步获取到所有的LifecycleProcessor对象,然后使用这个调用 onRefesh()对象来实现的。
第三步:发布最终实现的事件
第四步:不太了解,和LiveBeansView 相关。
13. resetCommonCaches()//将常用的cache都青空。
总结:
对于ApplicationContext的继承体系。
ClassPathXmlApplicationContext;类主要是确定当前的定义的Resource的位置。同时调用父类的方法来完成依赖注入的过程。
- protected Resource[] getConfigResources()//继承AbstractXmlApplicationContext;这个方法会被父类调用。
- public void setConfigLocations(String... locations)//调用了父类 AbstractRefreshableConfigApplicationContext的方法,这个方法是设置Resource对应的locations。
AbstractXmlApplicationContext:当前类主要是对于类的BeanDefinition的方法进行加载。
- protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)//这个方法是继承自AbstractRefreshableApplicationContext:这个方法的主要是从底层方法指定的Resoure信息,和父类中指定的DefaultListableBeanFactory,使用一个合适的BeanDefinitionReader来将BeanDefinition的继承信息填到对应的BeanFactoy中。当前类是AbstractXmlApplicationContext,所以用XmlBeanDefinitionReader来读取。其实这个方法是一个来料加工的过程。
- protected String[] getConfigLocations()//在loadBeanDefinitions(DefaultListableBeanFactory beanFactory) 的方法中调用了AbstractRefreshableConfigApplicationContext;中的方法,其中对应的locations地址是在ClassPathXmlApplicationContext中设置的。
AbstractRefreshableConfigApplicationContext:这个方法主要维护locations的属性。以及其他的一些配置信息。
AbstractRefreshableApplicationContext :这个方法中主要是维护了BeanFactory。其中DefaultListableBeanFactory就是在这个类中创建的。
- protected final void refreshBeanFactory();//当前方法继承自AbstractApplicationContext;主要工作是初始化 了DefaultListableBeanFactory。
- protected void cancelRefresh(BeansException ex);// 关闭refres的过程,同时将异常形象传递过来。
AbstractApplicationContext:这个方法是ApplicationContext体系的核心,其中refresh()方法是核心中的关键,实现了 IOC的依赖注入的关键步骤。同时依赖子类实现BeanDefinion的信息加载的过程。然后根据BeanFactoy ,对BeanFactoyPostProcessor,MessageSource,Listener,BeanPostProcessor等功能的实现,以及对于所有的非延迟加载的BeanDefinition进行实例化。