spring中IOC容器中的xml加载过程

对于spring的控制反转,是利用JAVABEAN的方式,进行利用配置文件中设置来进行在需要时的对象注入。很多时候我们都是使用的是xml的配置文件,因此spring对于从xml文件的操作到bean的注入,这一些列过程的研究,其中一部分就是本次的写作内容。内容分为以下几部分:
-**对于xml文件由路径获取转换为resource资源**
-**由resource资源转变为相应的document对象**
-**对于document对象和element对象的处理**。
-------------------------------------------------------------------------------------------内容参考于《spring源码深度分析》


BeanFactory bf = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));这里以该句代码为例:
(1)这里由xml的文件路径获得转换成相应的resource资源
  通过分析的话,XMLBeanFactory有如下的构造方法,也就是上面要调用的,而ClassPathResource 的继承关系如下图:
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}

    
  对于new ClassPathResource("spring-config.xml");有如下的代码
  public ClassPathResource(String path) {
this(path, (ClassLoader) null);
}
public ClassPathResource(String path, ClassLoader classLoader) {..}
  (2)对于resource资源处理转换为Document
  当resource相关类完成了对于配置文件的封装后,就由XmlBeanDefinitionReader来操作。
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
执行:
  public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
loadBeanDefinitions(resource)为执行加载该resource。
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
loadBeanDefinitions方法,加载时调用的是loadBeanDefinitions方法,而new EncodedResource(resource)为其参数,该处对于source进行了新的编码,
符合于需要进行编码的条件。
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException 该方法则是对于专有格式xml文件的加载,然后
获得beandefinition定义的个数。
之后获得资源文件的验证格式,如下,如果是自定义格式,按照自定义格式验证;如果是自动默认的验证格式,则是按照默认格式操作
 getValidationModeForResource(Resource resource) 
然后是通过如下的方法,验证通过后,通过loadDocument转换成相应的Document
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
int validationMode = getValidationModeForResource(resource);
Document doc = this.documentLoader.loadDocument(
inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
return registerBeanDefinitions(doc, resource);
}
    这里会用到DefaultDocumentLoader,中的如下方法
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
if (logger.isDebugEnabled()) {
logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
}
DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
return builder.parse(inputSource);
}
(3)对于document和element的解析
之后由XmlBeanDefinitionReader 中的如下方法:
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
documentReader.setEnvironment(getEnvironment());
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
   读取(2)中生成的Document,利用document文档,进行beandefinitions的注册,并返回注册的个数。其中用到了接口 BeanDefinitionDocumentReader,DefaultBeanDefinitionDocumentReader实现了该接口中的方法, registerBeanDefinitions
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
进行处理Document,protected void doRegisterBeanDefinitions(Element root)只后由该方法处理每个beandefinition的root element,
protected void doRegisterBeanDefinitions(Element root) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getEnvironment().acceptsProfiles(specifiedProfiles)) {
return;
}
}
// 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 = createDelegate(this.readerContext, root, parent);
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}


protected BeanDefinitionParserDelegate createDelegate(
XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {
BeanDefinitionParserDelegate delegate = createHelper(readerContext, root, parentDelegate);
if (delegate == null) {
delegate = new BeanDefinitionParserDelegate(readerContext, getEnvironment());
delegate.initDefaults(root, parentDelegate);
}
return delegate;
}
BeanDefinitionParserDelegate 对于该类则是对于element进行处理的各种方法的实现,我们可以看到
public class BeanDefinitionParserDelegate {
public static final String BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans";
public static final String MULTI_VALUE_ATTRIBUTE_DELIMITERS = ",; ";
/** @deprecated as of Spring 3.1 in favor of {@link #MULTI_VALUE_ATTRIBUTE_DELIMITERS} */
@Deprecated
public static final String BEAN_NAME_DELIMITERS = MULTI_VALUE_ATTRIBUTE_DELIMITERS;
/**
* Value of a T/F attribute that represents true.
* Anything else represents false. Case seNsItive.
*/
public static final String TRUE_VALUE = "true";
public static final String FALSE_VALUE = "false";
public static final String DEFAULT_VALUE = "default";
public static final String DESCRIPTION_ELEMENT = "description";
public static final String AUTOWIRE_NO_VALUE = "no";
public static final String AUTOWIRE_BY_NAME_VALUE = "byName";
public static final String AUTOWIRE_BY_TYPE_VALUE = "byType";
public static final String AUTOWIRE_CONSTRUCTOR_VALUE = "constructor";
public static final String AUTOWIRE_AUTODETECT_VALUE = "autodetect";
public static final String DEPENDENCY_CHECK_ALL_ATTRIBUTE_VALUE = "all";
public static final String DEPENDENCY_CHECK_SIMPLE_ATTRIBUTE_VALUE = "simple";
public static final String DEPENDENCY_CHECK_OBJECTS_ATTRIBUTE_VALUE = "objects";
public static final String NAME_ATTRIBUTE = "name";
public static final String BEAN_ELEMENT = "bean";
public static final String META_ELEMENT = "meta";
public static final String ID_ATTRIBUTE = "id";
public static final String PARENT_ATTRIBUTE = "parent";
public static final String CLASS_ATTRIBUTE = "class";
...和我们的xml配置文件中<bean id="" class =""> <property name ="" ref =""/></bean>比较相似,其实这就是我们配置文件中所用到的标签,只不过这里是不要通过不同的方法获得这些标签的值,然后封装到BeanDefinition中,其中有些方法如:
/**
* Apply the attributes of the given bean element to the given bean * definition.
* @param ele bean declaration element
* @param beanName bean name
* @param containingBean containing bean definition
* @return a bean definition initialized according to the bean element attributes
*/
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
BeanDefinition containingBean, AbstractBeanDefinition bd) 
/**
* Create a bean definition for the given class name and parent name.
* @param className the name of the bean class
* @param parentName the name of the bean's parent bean
* @return the newly created bean definition
* @throws ClassNotFoundException if bean class resolution was attempted but failed
*/
protected AbstractBeanDefinition createBeanDefinition(String className, String parentName)
throws ClassNotFoundException {
基本上都是解析element的。
总之,对于xml解析到beandefinition的过程大体如下

(1)   首先由实现了接口ResourceLoader中方法的类AbstractBeanDefinitionReader,用该方法将给出的配置文件地址转化成resource资源文件。

(2)   然后由DocumentLoader接口中方法,实现后将resource资源文件转化成document文件

(3)   由实现接口BeanDefinitionDocumentReader的DefaultBeanDefinitionDocumentReader调用实现的方法解析document,同时又BeanDefinitionParserDelegate类解析element,直至形成BeanDefinition。

第一个类图画的其中涉及到UML聚合的关系可能有些问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值