以下说法若有不对的地方欢迎大家指正
我这里用的是断点不断跟进的方式
spring的版本为3.2.2
以下是一张方法的调用图 方便理解
最近在看spring的IoC具体实现
其实也没有什么太大的心得 就是不断进行断点调试 然后看一下过程
这个过程其实并不复杂 只是一层层不断调用有点头晕罢了
以下我来说说具体的BeanDefinition载入和注册的过程
首先我这边是以ClassPathXmlApplicationContext为IoC容器的 他底下是维护了一个DefaultListableBeanFactory
bean的注册工作其实是在DefaultListableBeanFactory中完成的
这个Map的定义和实现如下:
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
这边是主要的过程(如果我写错了 谢谢指正^_^)
1、 通过XML解析接到Document对象标准的(org.w3c.dom.Document)
2、 在documentReader中实现这个按照Spring的Bean规则进行解析的过程
3、 实际的解析工作是交给documentReader中的BeanDefinitionParserDelegate完成的
4、 BeanDefinitionParserDelegate把解析的beanDefinition交给BeanDefinitionHolder
5、 在documentReader中调用BeanDefinitionReaderUtils.registerBeanDefinition(,)向IoC容器中注册
为了直观 我把一些主要的代码放出来并写上自己的注释 以下:
// XmlBeanDefinitionsReader中的方法
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
int validationMode = getValidationModeForResource(resource);
// 标准的org.w3c.dom.Document对象
Document doc = this.documentLoader.loadDocument(
inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
// 完成标准的document到spring定义的bean规则解析的过程
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
... ...
// 同样是XmlBeanDefinitionsReader中的方法
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 得到一个BeanDefinitionDocumentReader的对象来按照bean规则解析
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
documentReader.setEnvironment(this.getEnvironment());
// 获取解析前的bean数目 第一次的话应该是0
int countBefore = getRegistry().getBeanDefinitionCount();
// 具体的解析过程以下完成
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
// 以上的documentReader.registerBeanDefinitions(,)方法调用了DefaultBeanDefinitionDocumentReader中的方法
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
// 得到根元素
Element root = doc.getDocumentElement();
// 这边开始做解析
doRegisterBeanDefinitions(root);
}
// 同样是调用了DefaultBeanDefinitionDocumentReader中的方法
protected void doRegisterBeanDefinitions(Element root) {
// 这部分是关于profile的(spring 3.1之后才有的吧?) 绕过
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
Assert.state(this.environment != null, "Environment must be set for evaluating profiles");
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!this.environment.acceptsProfiles(specifiedProfiles)) {
return;
}
}
// 解析中做着核心工作的就是BeanDefinitionParserDelegate的对象
// Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createHelper(this.readerContext, root, parent);
// 在DefaultBeanDefinitionDocumentReader中什么都不做
preProcessXml(root);
// 这边就是具体的解析了
parseBeanDefinitions(root, this.delegate);
// 在DefaultBeanDefinitionDocumentReader中什么都不做
postProcessXml(root);
// 还原
this.delegate = parent;
}
// DefaultBeanDefinitionDocumentReader中的方法
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);
}
}
// 以上方法的parseDefaultElement如下 同样是DefaultBeanDefinitionDocumentReader中的方法
// 根据不同的名称执行不同的操作
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
//同样是DefaultBeanDefinitionDocumentReader中的方法 这是以上的processBeanDefinition(ele, delegate)
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// bdHolder就是BeanDefinitionHolder
// 解析实际都是靠BeanDefinitionParserDelegate中的方法完成的 这里面的代码太多了就不跟进了
// 需要的可以自己去看下
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
// 这句话就是向BeanFactory注册bean
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
// BeanDefinitionReaderUtils中的静态方法
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
// 传入的这个registry其实就是在之前的DefaultListableBeanFactory实例 因为
// DefaultListableBeanFactory实现了BeanDefinitionRegistry接口可以注册bean
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String aliase : aliases) {
registry.registerAlias(beanName, aliase);
}
}
}
// DefaultListableBeanFactory中的方法
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
synchronized (this.beanDefinitionMap) {
Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
// 如果存在了同名的bean
if (oldBeanDefinition != null) {
//如果不允许bean的覆盖的话就会抛出异常
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
else {
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames = null;
}
// 可以看到其实内部还是一个Map的结构来维护的
this.beanDefinitionMap.put(beanName, beanDefinition);
}
resetBeanDefinition(beanName);
}
具体过程如上
这边只是阐述了一下这个过程 有兴趣的可以自己跟进查看更详细的解析过程