1、DefaultListableBeanFactory
1.1 类的结构
DefaultListableBeanFactory是整个bean加载的核心部分,是Spring注册及加载的bean的默认实现。DefaultListableBeanFactory继承了AbstractAutowireCapableBeanFactory并实现了ConfigurableListableBeanFactory以及BeanDefinitionRegistry接口。
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable
1.2 XmlBeanFactory
XmlBeanFactory对父类DefaultListableBeanFactory进行了扩展,主要用于从XML文档中读取BeanDefinition,对于注册及获取bean都是使用从父类DefaultListableBeanFactory继承的方法区实现,而唯独与父类不同的个性化实现就是增加了XmlBeanDefinitionReader类型的reader属性。在XmlBeanFactory中主要使用reader属性对资源文件进行读取和注册;
//## 对资源文件进行读取和注册 ##//
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
1.2.1 XmlBeanDefinitionReader
- 继承AbstractBeanDefinitionReader中的方法,来使用ResourceLoader将资源文件路径转换为对应的Resource文件。
- 通过DocumentLoader对Resource文件进行转换,将Resource文件转换为Document文件。
- 通过实现接口BeanDefinitionDocumentReader的DefaultBeanDefinitionDocumentReader对Document进行解析,并使用BeanDefinitionParserDelegate对Element进行解析。
1.3ClassPathResource
Spring的配置文件读取是通过ClassPathResource进行封装的。
Spring对其内部使用到的资源实现了自己的抽象结构:Resource接口封装底层资源。
当通过Resource相关类完成了对配置文件进行封装后,配置文件的读取功能就全权交给XmlBeanDefinitionReader来处理了。
2、源码
public XmlBeanFactory(Resource resource) throws BeansException {
//调用XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory)构造方法
this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
//parentBeanFactory为父类BeanFactory用于factory合并,可以为空
super(parentBeanFactory);
//资源加载的真正实现
this.reader.loadBeanDefinitions(resource);
}
2.1 核心逻辑部分loadBeanDefinitions
封装资源文件。当进入XmlBeanDefinitionReader后首先对参数Resource使用EncodedResource类进行封装。
/**
* Load bean definitions from the specified XML file.
* @param resource the resource descriptor for the XML file
* @return the number of bean definitions found
* @throws BeanDefinitionStoreException in case of loading or parsing errors
*/
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
//## 1、封装资源文件 ##//
return loadBeanDefinitions(new EncodedResource(resource));
}
获取输入流。从Resource中获取对应的InputStream并构造InputSource。
通过构造的InputSource实例和Resource实例继续调用函数doLoadBeanDefinitions。
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);
}
//## 通过属性来记录已经加载的资源 ##//
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
//## 2、获取输入流 ##//
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
//## 2.1 构造InputSource实例 ##//
//## InputSource这个类并不来自于Spring,它的全路径是 org.xml.sax.InputSource ##//
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//## 3、通过InputSource实例和Resource实例继续调用函数 ##//
//## 真正进入了逻辑核心部分 ##//
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();
}
}
}
2.1 核心处理部分doLoadBeanDefinitions
- 获取对XML文件的验证模式
- 加载XML文件,并得到相应的Document
根据返回的Document注册Bean信息
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//## 1、getValidationModeForResource 获取XML文件的验证模式 ##//
//## 2、加载XML文件,并得到对应Document ##//
Document doc = doLoadDocument(inputSource, resource);
//## 根据返回的Document注册Bean信息 ##//
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 {
//## 使用DefaultBeanDefinitionDocumentReader 实例化 BeanDefinitionDocumentReader ##//
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//## 记录统计前 BeanDefinition 的加载个数 ##//
int countBefore = getRegistry().getBeanDefinitionCount();
//## 加载及注册bean BeanDefinitionDocumentReader是一个接口,真正的类型其实已经是DefaultBeanDefinitionDocumentReader ##//
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
//## 记录本次加载 BeanDefinition 的个数 ##//
return getRegistry().getBeanDefinitionCount() - countBefore;
}
2.3核心逻辑的底部doRegisterBeanDefinitions
protected void doRegisterBeanDefinitions(Element root) {
// 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;
//## 专门处理解析BeanDefinitionParserDelegate类型的实例 ##//
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
//## 处理profile属性 ##//
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);
//## 解析并注册bean ##//
parseBeanDefinitions(root, this.delegate);
//## 解析后处理,留给子类实现 ##//
postProcessXml(root);
this.delegate = parent;
}
2.4 解析并注册BeanDefinition
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)) {
//## 对bean处理 默认解析 ##//
parseDefaultElement(ele, delegate);
}
else {
//## 对bean处理 自定义解析 ##//
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
2.4.1 默认标签的解析
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)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
bean标签的解析及注册
- 首先委托BeanDefinitionParserDelegate类的方法parseBeanDefinitionElement方法进行元素解析,返回BeanDefinitionHolder类型的实例bdHolder(包含我们配置文件的各种属性,如:class、name、id、alias之类的属性)。
- 当返回的bdHolder不为空的情况下若存在默认标签的子节点下再有自定义属性,还需要对自定义标签再次解析。
- 解析完成后,需要对解析后的bdHolder进行注册。
最后发出响应事件。
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//## 委托BeanDefinitionParserDelegate类的方法parseBeanDefinitionElement进行元素解析 ##//
//## BeanDefinitionHolder的实例bdHolder 已经包含我们配置文件中配置的各种属性了,例如:class、name、id、alias ##//
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//## 若存在默认标签的子节点下再有自定义属性,还需要对自定义属性进行解析 ##//
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
//## 解析完成后,需要对bdHolder进行注册 ##//
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));
}
}
2.4.1.1 创建用于属性承载的BeanDefinition
BeanDefinition是一个接口,在Spring中存在三种实现,RootBeanDefinition、ChildBeanDefinition以及GenericBeanDefinition。三种实现均继承AbstractBeanDefinition,其中BeanDefinition是配置文件
元素标签在容器中的内部标识形式。 2.4.1.2 注册解析的BeanDefinition
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
//## 使用beanName做唯一标识注册 ##//
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
//## 注册所以别名 ##//
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
通过beanName注册BeanDefinition
-
2.4.1.3 通知监听器解析及注册完成