记spring的XmlBeanFactory加载机制

周日处理一个spring-security的问题。顺带把spring的类加载机制和spring的security也看了一遍。
觉得spring的整个设计还是蛮有意思的。用的spring是4.3.18,后续用到的源码也都是这个版本的。

先看spring的加载机制。
spring对象的管理生成是通过BeanFactroy来生成的,目前比较常用的有
BeanFactroy
最基础的 BeanFactory, 提供了根据 name , type 等获取一个 bean 对象的能力

ListableBeanFactory
继承 BeanFactroy, 额外提供了列出所有bean对象的能力

HierarchialBeanFacotry
继承BeanFactroy,额外使了 factory 拥有一个parent factory的能力, 可以存在层级关系

SingletonbeanRegistry
提供了单例对象缓存的能力

AutowireCapableBeanFacory
继承 BeanFactroy, 提供了在创建对象时, 通过set方式给 bean 初始化 autowired 或者声明了 dependon 的成员

ConfigurableBeanFactory
继承 ListableBeanFactory 和 HierarchialBeanFacotry, 给 factory 提供了很多配置的方法, 比如设置 BeanPostProcessor

AliasRegistry
支持了多个别名

我们的项目中使用的是ListableBeanFactory,更具体的实现类是 XmlBeanFactory(这个类在4.3.18版本中已经不推荐使用) 。XmlBeanFactory同时是ListableBeanFactory的子类。
因为系统初始化是通过xml,所以xml只处理那些在xml中定义的bean对象,那些通过标注生成的对象是通过AutowireCapableBeanFacory来处理的,这里不展开。

XmlBeanFactory对于spring的加载是通过构造函数来做初始化工作的。详细如下:

/**
* Create a new XmlBeanFactory with the given input stream,
* which must be parsable using DOM.
* @param resource XML resource to load bean definitions from
* @param parentBeanFactory parent bean factory
* @throws BeansException in case of loading or parsing errors
*/
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}

这个的Resource 就是classpath中的applicationContext.xml 文件。
通过成员变量来读取定义的resource

private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

XmlBeanDefinitionReader 的加载applicationContext.xml文件的逻辑
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();
}
}
}

中间又见过了多次的调用

loadBeanDefinitions -> doLoadBeanDefinitions -> doLoadDocument -> registerBeanDefinitions -> org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#registerBeanDefinitions

最终真正解析xml的是DefaultBeanDefinitionDocumentReader 这个类的doRegisterBeanDefinitions 方法来处理。


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)) {
//非xmlns定义的handler
parseDefaultElement(ele, delegate);
}
else {
//常用的handler
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}

在解析xml的过程中跟根据xml头部的ns定义,来获取对应的handler。


xml头部的xmlns 在parseDefaultElement方法中会被抽象成handler。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd">

xml中的每一个元素会被解析为 Element,常见的Element例如
<aop:aspectj-autoproxy />
<task:annotation-driven/>
<context:annotation-config/>
<aop:config proxy-target-class=”true”/>

每一个Element都会有对应的BeanDefinitionParserDelegate来处理。
BeanDefinitionParserDelegate做的事情就是把 对于的Element找到对应xmlns中定义的handler来处理


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

NamespaceHandler的handler有如图所示:

每一个handler就是把对应的element解析为BeanDefinition 对象来做初始化。到此为止 XmlBeanFactory的工作已经完成了。
由于继承之DefaultListableBeanFactory,其他工作都是在DefaultListableBeanFactory中处理的。

DefaultListableBeanFactory在preInstantiateSingletons来做类的前置工作。
public void preInstantiateSingletons() throws BeansException {

List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {

//真正的初始化bean。
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}

}

getBean 又经过了
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
try {
//正常的创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}

到此为止 通过applicationContext.xml的配置文件加载及其中的bean加载已经完成。
总结的说:
主要通过XmlBeanFactory 来加载类,xml头部的xmlns定义了xml中各种element的处理类。最终的对象初始化是通过各种继承关系中的DefaultSingletonBeanRegistry来处理的。
工程类对于xml加载的继承体系是
XmlBeanFactory -> DefaultListableBeanFactory -> AbstractAutowireCapableBeanFactory -> AbstractBeanFactory -> FactoryBeanRegistrySupport -> DefaultSingletonBeanRegistry -> SimpleAliasRegistry -> AliasRegistry

发表评论?

0 条评论。

发表评论


注意 - 你可以用以下 HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>