导语
接着上一篇,继续看看spring源码,再菜也要坚持看完!
ConfigurationApplicationContext
CAC接口中的属性和方法:
从上图可以看出,属性和方法基本都是对上下文的配置和系统自带bean 的名字,值得注意的是getBeanFactroy()方法与AC接口的方法同名,同参,返回值类型不同但具有继承关系。还有就是refresh()方法,看了看方法上的注释,大致是想我们使用这个方法通过配置文件来加载或来刷新 persistent representation (大概就是配置的bean吧)。
AbstractApplicationContext
AAC是第一个实现spring上下文接口的抽象类,由于接口中累积了大量的方法,本着单一职责的设计思路,把功能细化,然后通过代理模式分配出去,而自身主要是对CAC和AC本身的方法进行实现。我们暂且忽略被代理出去的方法,因为在本类中也无法看出其具体实现,先看看类中的属性:
可以看出现在spring的上下文已经具备一些实质性的东西了,也就是上面的这些属性,实现的接口也基本基于这些属性的操作方法。由于类中方法数太多,绝大部分分都是通过代理或组合模式来实现的,就不进行截图也暂且丢一边,主要看refresh()方法的实现。
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
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();
上面是refresh()方法的主要代码,里面调用的方法名称跟其目的是一致的,perpareRefresh()是设置active,closed,startTime属性和初始化earlyApplicationEventj集合用于准备工作。由于BeanFactory使用是抽象代理,并没有明确到具体实例,obtainFreshBeanFactroy()则是告诉子类,要开始refresh了你得准备一下并把BeanFactory返回给我。从子类中得到BeanFactory后,perpareBeanFactory()开始对BeanFactory添加一些标准化设置及注册系统bean,截取方法中的注释。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
// Configure the bean factory with context callbacks.
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.;
// Register early post-processor for detecting inner beans as ApplicationListeners.
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
// Set a temporary ClassLoader for type matching.
}
// Register default environment beans.
}
到这里,BeanFactory的准备工作和初始化设置基本完成了,spring的容器也就已经准备好了,对于容器这个概念,也比较抽象,我也只是简单的将其理解为里面存放了很多类的实例对象,当你需要的时候就只需要去容器中拿,显然这些对象应该是无状态的。容器存在与context中的,context则是借助容器来实现对对象实例的共享管理。
BeanFactory创建好了,我们还需要往里面注册processors,用于对bean进行操作处理,毕竟工厂是工厂,有工人之后工厂才能发挥其能力。同时,消息资源和事件监听和推送也是属于共享且无状态的对象,也可以初始化后放入容器中,这些操作便在registerBeanPostProcessors(),initMessageSource(),initApplicationEventMulticaster()。
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for registering special
* BeanPostProcessors etc in certain ApplicationContext implementations.
* @param beanFactory the bean factory used by the application context
*/
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}
postProcessBeanFactory()方法并没有一行代码,注释中也表明,在BeanFactory标准化后允许子类覆盖这个方法,来使BeanFactory能操作自定义或特殊的Bean。
/**
* Template method which can be overridden to add context-specific refresh work.
* Called on initialization of special beans, before instantiation of singletons.
* <p>This implementation is empty.
* @throws BeansException in case of errors
* @see #refresh()
*/
protected void onRefresh() throws BeansException {
// For subclasses: do nothing by default.
}
onfresh()方法也是空,这部分也将陪分配到子类中,具体解释看注释吧。
protected void registerListeners() {
// Register statically specified listeners first.
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
// Publish early application events now that we finally have a multicaster...
}
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 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.
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// Stop using the temporary ClassLoader for type matching.
// Allow for caching all bean definition metadata, not expecting further changes.
// Instantiate all remaining (non-lazy-init) singletons.
}
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
// Initialize lifecycle processor for this context.
// Propagate refresh to lifecycle processor first.
// Publish the final event.
// Participate in LiveBeansView MBean, if active.
}
终于,在这个时候知道注释有多么的重要,特别是在大型的应用中,功能将被拆到多个类,多个方法中,真的无法凭记忆去感觉。在子类的onRefresh()执行之后,BeaFactory的工作也收尾了。也许还记得earlyApplicationEvent这个属性,因为在创建前没有消息的发布者(muticaster),context创建前的事件都被存到该集合,直到registerListener()后,再将其发布。finishBeanFactoryInitialization()则是开始实例话bean了,finishRefresh()则是清空resource case,classLoader等缓存。最后发布一个ContextRefreshedEvent事件,宣布上下文创建或刷新已经完成了。。(掌声!!)
AbstractRefreshableApplicationContext
ARAC继承自AAC,对一个R,也代表了它多一个Refreshable属性。但是在AAC中也有refresh,只不过AAC中的refresh只是对context的标准化,而ARAC是刷新BeanFactroy。
从上图看,ARAC完成了一个关键的操作,创建了BeanFactory,终于看到了BeanFactory的真身了,还为期定义了两个allow属性:
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
有了BeanFactory后,ARAC就得完成其父亲AAC的叮嘱,为AAC先刷新好BeanFactory(还记得// Tell the subclass to refresh the internal bean factory. 这个注释吗?)。
@Override
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的操作,里面没有注释是不是说这很j简单?确实,就连核心操作loadBeanDefinition都是抽象方法。好吧,我们也跳过这个类,感谢它带来的BeanFactoy和定义的几个刷新方法,还有两个allowsh属性。
AbstractRefreshableConfigApplicationContext
好吧,现在的context可以有自定义的配置文件了。
但还是注意一下,ARCAC还实现了BeanNameAware,InitializingBean两个接口。
/**
* Triggers {@link #refresh()} if not refreshed in the concrete context's
* constructor already.
*/
@Override
public void afterPropertiesSet() {
if (!isActive()) {
refresh();
}
}
上面是InitializingBean中的方法,大致是触发自动刷新,目前还没看见具体触发机制的实现。
AbstractXmlApplicationContext
AXAC是对context的最后一层抽象,实现了其父类最后一个为实现的抽象方法:
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
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));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
因为配置文件加载的次数有限,loadBeanFactory()也是直接new 一个对象来完成使命。现在的AXAC中并没有任何抽象方法,按理可以写成一个普通类,依旧定义成抽象类也决定了AXAC无法被实例化,设计的目的为何?
结尾
到此,从定义的接口到全部的实现,context这个巨大的角色框架基本已经清楚了,我们也看到了巨型角色构建的设计艺术。大致上从AAC对职责的划分,分配到各个代理中,再定义了一个总体的refresh对策,把核心的自定义配置加载(obtainFreshBeanFactory()),自定义刷新BeanFactory (onRefresh())功能抽象出去,分别让ARCAC和ARAC实现,最后由AXAC统一大业,不得不佩服AAC抽象类的设计。