在spring的实际应用中,我们经常将bean定义在xml的配置文件当中,那么,spring是如何从xml加载bean的呢?今天我们将从源码的层面进行简单的解读。假设,我们有如下一个spring的配置文件,这是我从一个dubbo的demo中获取的。
在spring 3.1的版本之前,我们可以使用XmlBeanFactory加载xml配置文件,比如:
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("dubbo-provider.xml"));
factory.getBean("guyService");
构造函数中xml配置文件作为Resource载入。
在spring 3.1之后的版本,建议使用DefaultListableBeanFactory和XmlBeanDefinitionReader来从xml中加载bean。DefaultListableBeanFactory是ListableBeanFactory接口和BeanDefinitionRegistry接口的默认实现,XmlBeanDefinitionReader顾名思义,从xml中解析bean的定义。使用这两个类,加载我们前述的配置文件则可以使用下面的代码:
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new ClassPathResource("dubbo-provider.xml"));
Object bean = factory.getBean("guyService");
从代码看,加载的核心代码是在第三行和第四行,我们进入到loadBeanDefinitions方法看它的源码,里面加入了一些我自己的注解:
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
//对Recource进行编码
return loadBeanDefinitions(new EncodedResource(resource));
}
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
//this.resourcesCurrentlyBeingLoaded是ThreadLocal的本地线程变量,存储当前在load的resources
Set currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
//检测是否是在循环load
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//真正的load从此进入
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
我们再仔细看一下doLoadBeanDefinitions的源码:
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//解析resource获取Document
Document doc = doLoadDocument(inputSource, resource);
//注册BeanDefinition
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
}
catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
}
catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//创建BeanDefinition的Document Reader
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//获取已经解析了的BeanDefiniton的数目
int countBefore = getRegistry().getBeanDefinitionCount();
//使用reource创建reader的上下文,注册当前的BeanDefinition
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
//真正register BeanDefinition的入口
doRegisterBeanDefinitions(root);
}
protected void doRegisterBeanDefinitions(Element root) {
//嵌套的将递归调用这个方法,为了能够传播和保存的default-*属性,需要跟踪当前的委托
//初始的委托为null
BeanDefinitionParserDelegate parent = this.delegate;
//创建委托,并初始化default-*属性
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
//供子类使用,作为前置处理
preProcessXml(root);
//使用委托从root节点解析BeanDefinition
parseBeanDefinitions(root, this.delegate);
//供子类使用,作为后置处理
postProcessXml(root);
this.delegate = parent;
}
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//判断是否是默认的namespace
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)) {
//解析默认的element
parseDefaultElement(ele, delegate);
}
else {
//解析自定义的element
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
我们这次看一下解析默认element的parseDefaultElement方法:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//处理import节点
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
//处理alias节点
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
//处理bean节点
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
//处理嵌套的beans节点
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// 此处会引入之前所说的递归
doRegisterBeanDefinitions(ele);
}
}
此处,我们主要看一下加载bean的方法:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//解析element,获得一个BeanDefinitionHolder作为BeanDefinition的容器,内有BeanDefinition、name和alias,这个方法详细解析了对应element的各个attribute,如autowired,scope等;同时,还解析了其的子节点,如constructor,property等
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//对BeanDefinitionHolder进行装饰,作为最终要注册进BeanFactory的实例,此处装饰的作用是解析一些自定义的标签
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 此处将BeanDefinitionHolder注册进入registry,也就是示例代码中的DefaultListableBeanFactory
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));
}
}
DefaultListableBeanFactory维护了一个beanDefinitionMap,其键值对形式为beanName->BeanDefinition,这是一个ConcurrentHashMap。注意,这个map维护的只是BeanDefinition,并不是我们要获取的bean对象,这两者是有区别的,bean对象的获取需要调用BeanFactory接口的getBean方法。spring中维护了大量的ConcurrentHashMap,作为本地缓存。至此,完成了整个XmlBeanDefinitionReader的loadBeanDefinitions方法。
在解读DefaultListableBeanFactory的getBean(String name)方法之前,我们看一下
接下来,我们看看DefaultListableBeanFactory的getBean(String name)方法,这个方法用于获取真正的我们使用的Bean Object:
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected T doGetBean(
final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
//转换beanName,这里主要是将FactoryBean的前缀&符号去除,此处不做详细的解释
final String beanName = transformedBeanName(name);
Object bean;
// 早期检查,尝试从缓存中获取实例,此处为了防止循环依赖的问题,会尝试从earlySingletonObjects中获取实例,没有的话再从ObjectFactory中获取,再将之放入earlySingletonObjects,此时获取到的对象是不完整的,即它的依赖还未创建完成
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//这个方法其实是获取到真正需要使用的bean,如果要获取的bean实现了FactoryBean接口,那么,获取到的bean其实是FactoryBean中getObject方法的吐出的object
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//检查父类的BeanFactory
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
//标记bean为已创建,实际是在alreadyCreated加入对应的beanName
markBeanAsCreated(beanName);
}
try {
//将GenericBeanDefinition装换为RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//检查RootBeanDefinition是否为抽象
checkMergedBeanDefinition(mbd, beanName, args);
// 要保证depend-on属性的bean先被初始化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
getBean(dep);
}
}
// 以下是创建bean的过程
//scope为singleton的创建
if (mbd.isSingleton()) {
//此处定义了一个内部类,实现ObjectFactory接口,ObjectFactory和FactoryBean都有getObject方法,前者重在创建object自身,后者重在获取其内部管理的object,此处的getObject方法的实现是调用了AbstractAutowireCapableBeanFactory中的createBean方法,为什么?因为DefaultListableBeanFactory是AbstractAutowireCapableBeanFactory的子类
sharedInstance = getSingleton(beanName, new ObjectFactory
从注释中看到,我们创建对象的过程是在getSingleton(String beanName, ObjectFactory> singletonFactory)方法中,其中ObjectFactory已经由匿名内部类进行定义.
public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
//在此尝试从缓存中获取bean
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//创建singleton bean之前,先检查inCreationCheckExclusions集合中不存在对应beanName,并将之放入当前正在创建的bean集合singletonsCurrentlyInCreation中
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet();
}
try {
//调用ObjectFactory的getObject方法,前面有提到,这个方法由匿名内部类定义过
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//无论是否完成singleton bean的创建,都要将之从singletonsCurrentlyInCreation移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
//如果完成创建,将之添加到缓存中,具体实现看源码,有好几个缓存的添加和移除
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
以上代码核心的创建singleton bean的过程定义在AbstractAutowireCapableBeanFactory中,具体如下:
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
//根据Beandefinition和beanName解析获取Class
Class> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// 标记和验证method的override属性,spring将配置中的lookup-method和replace-method在BeanDefinition中统一归类为override属性
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
//给BeanPostProcessors一个机会使其能返回代理用于代替目标bean
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
如果resolveBeforeInstantiation方法中的applyBeanPostProcessorsBeforeInstantiationd方法直接返回了一个bean,那么将直接使用这个bean,否则进入doCreateBean方法:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//根据beanName,BeanDefinition和参数集创建实例,并封装为BeanWrapper,这个函数具体也就是先解析出Class(因为此时的BeanDefinition经过了处理,已不是最初的BeanDefinition),然后拿到Constructor,使用反射newInstance出具体的实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// 允许后置处理器改变MergedBeanDefinition
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// 是否提前曝光,条件是单例 + 允许循环依赖 + 单例在创建中,其中allowCircularReferences是可以设置的;注意,此处是解决循环依赖的关键,如果读者没忘记的话,前文中最初尝试从缓存中获取bean的时候,就会从一个singletonFactories获取ObjectFactory,这里定义一个匿名内部类,并将实例bean提前曝光,此时曝光的bean是没有任何属性值的
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//填充bean的属性,这个函数会递归调用getSingleton的方法,也就是将我们前文分析的内容跑一遍,如果有循环依赖,那么在获取其属性时,就能获取到对应的bean
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
//初始化bean,其实说是初始化并不准确,这个方法主要做的事情是在进行一些接口方法的回调,如InitializingBean的afterPropertiesSet方法,BeanPostProcessor的postProcessAfterInitialization方法等
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
//注册DisposableBean,如果有destroy-method将作为销毁方法使用
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
这个方法返回的将是具有完整属性的bean,在前文我们提到过,真正给应用的bean需要经过getObjectForBeanInstance方法,这个方法来判断是返回当前的bean,还是FactoryBean,抑或是FactoryBean的getObect中获取的对象。
至此,spring从xml配置文件中获取bean的方法基本结束了,本文并没有非常详细的讲解每一个步骤,文中的注释也是作者自己的一些思考结合网络与书籍资料的结果,理解难免有偏差,如有问题,请联系[email protected]!