Spring的IOC源码解读&UML

3 篇文章 0 订阅
2 篇文章 0 订阅
<spring.version>4.0.6.RELEASE</spring.version>
这一部分主要记录bean定义的解析和加载,包括注解方式定义的bean。

【UML】
首先以uml展示ioc过程的全貌,为避免干扰,每个类仅表述了核心的属性,方法和方法内的关键代码。
refresh()方法标橙色,是外部调用的入口,如ContextLoaderListener。
标红色的是一些关键属性和实现。

uml连接:[url]http://dl2.iteye.com/upload/attachment/0115/8766/bedf264c-a530-33b3-924a-2b1799eef3ac.png[/url]
[img]http://dl2.iteye.com/upload/attachment/0115/8766/bedf264c-a530-33b3-924a-2b1799eef3ac.png[/img]


【代码解读】
XmlWebApplicationContext继承了AbstractApplicationContext。AbstractApplicationContext的refresh()方法对外提供访问入口,定义了bean定义的解析,创建和一些过程处理,如aop等。使用方法模版的设计模式,由各子类实现一些过程的细节。


@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 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);

try {
// 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();
}

catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();

// Reset 'active' flag.
cancelRefresh(ex);

// Propagate exception to caller.
throw ex;
}
}
}


在refresh()方法中,obtainFreshBeanFactory()方法负责beanFactory的创建及bean定义的解析逻辑,并让applicationContext持有beanFactory。


protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}


refreshBeanFactory()是一个抽象方法,具体实现是由AbstractRefreshableApplicationContext实现的。在这个方法中,如果已经存在beanFactory,则销毁beanFactory持有的bean定义及bean实例,并销毁beanFactory,代码实现上就是附null。然后创建一个新的beanFactory,具体实现类为DefaultListableBeanFactory。


@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);
}
}


loadBeanDefinitions()方法负责bean定义的解析,在AbstractRefreshableApplicationContext中是个抽象方法,由XmlWebApplicationContext实现。因为我们项目在web.xml配的是XmlWebApplicationContext。在这个方法中,会将beanFacotry以BeanDefinitionRegistry接口的实现放到XmlBeanDefinitionReader中,并让XmlBeanDefinitionReader持有beanFactory,以方便后面解析出beanDefinition后,可以注册到beanFactory中。当然实际持有beanFactory的是XmlBeanDefinitionReader的父类AbstractBeanDefinitionReader,可以参看UML图。


@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(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);
}


根据在web.xml定义的contextConfigLocation,由XmlBeanDefinitionReader开始解析每个配置文件。整体流程的代码实现在XmlBeanDefinitionReader的父类AbstractBeanDefinitionReader中。但bean定义的解析和加载在XmlBeanDefinitionReader中。


protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
String[] configLocations = getConfigLocations();
if (configLocations != null) {
for (String configLocation : configLocations) {
reader.loadBeanDefinitions(configLocation);
}
}
}


实际的bean定义解析也不是由XmlBeanDefinitionReader完成的,XmlBeanDefinitionReader会创建DefaultBeanDefinitionDocumentReader,并将自己作为XmlReaderContext的一个属性,交由DefaultBeanDefinitionDocumentReader进行处理,并由DefaultBeanDefinitionDocumentReader持有XmlReaderContext。


public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
documentReader.setEnvironment(this.getEnvironment());
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}


在DefaultBeanDefinitionDocumentReader解析bean定义的过程中,遇到非http://www.springframework.org/schema/beans命名空间的标签,会交由BeanDefinitionParserDelegate 进行解析。BeanDefinitionParserDelegate会持有DefaultBeanDefinitionDocumentReader的readerContext。


BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(this.readerContext, root, parent);

preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);

this.delegate = parent;

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}


类似于注解和aop等的定义解析,都是由BeanDefinitionParserDelegate完成的,他会根据namespaceUri的不同,找到不同的NameSpaceHandler。查找的工作由readerContext持有的属性NamespaceHandlerResolver完成,对应的实现类是DefaultNamespaceHandlerResolver。而DefaultNamespaceHandlerResolver的创建,是在XMLBeanDefinitionReader在创建XmlReaderContext时,就已经指定的,可参考UML图,或者前面的代码解读。
NameSpaceHandler都放在DefaultNamespaceHandlerResolver的属性handlerMappings中,此处找到的实现类是NamespaceHandlerSupport。


public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}


NamespaceHandlerSupport的属性parsers中存放了所需的BeanDefinitionParser。以注解为例,会找到ComponentScanBeanDefinitionParser,处理注解的bean定义解析,并最终调用readerContext的fireComponentRegistered方法,向eventListener注册componentDefinition。


@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

// Actually scan for bean definitions and register them.
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

return null;
}

protected void registerComponents(
XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {

Object source = readerContext.extractSource(element);
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);

for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {
compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));
}

// Register annotation config processors, if necessary.
boolean annotationConfig = true;
if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
annotationConfig = Boolean.valueOf(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
}
if (annotationConfig) {
Set<BeanDefinitionHolder> processorDefinitions =
AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
}
}

readerContext.fireComponentRegistered(compositeDef);
}


未完,待续 -=^^=-
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值