DefaultListableBeanFactory是bean加载的核心部分,是Spring注册和加载bean的默认实现。
DefaultListableBeanFactory的层次结构。
AliasRegistry接口:定义对alias的增删改查
SimpleAliasRegistry类:对AliasRegistry接口进行了实现,用map来存alias
SingletonBeanRegistry接口:定义了单例的注册和获取
BeanFactory接口:定义了获取bean以及获取bean的各种属性
DefaultSingletonBeanRegistry类:对SingletonBeanRegistry接口进行了实现
HierarchicalBeanFactory接口:增加了对parentBean的支持。
BeanDefinitionRegistry:定义了对BeanDefinition的增删改查
FactoryBeanRegistrySupport:增加了对FactoryBeand的处理。
ConfigurableBeanFactory接口:提供了配置Factory的各种方法
ListableBeanFactory接口:根据各种条件获取bean的配置清单
AbstractBeanFactory类:综合了ListableBeanFactory和ConfigurableBeanFactory的功能
AutowireCapableBeanFactory接口:定义了bean的创建,自动注入,初始化以及应用bean后的处理
AbstractAutowireCapableBeanFactory类:对AutowireCapableBeanFactory接口进行实现,综合了AbstractBeanFactory和AutowireCapableBeanFactory的功能
ConfigurableListableBeanFactory接口:BeanFactory的配置清单
DefaultListableBeanFactory类:综合了全部功能
XmlBeanFactory继承DefaultListableBeanFactory,主要增加了通过xml文档来去读BeanDefinition,而注册和获取都是通过DefaulListableBeanFactory来实现的。
XmlBeanFactory源码增加了XmlBeanDefinitionReader来读取Resource之后通过this.reader.loadBeanDefinitions来读取解析xml文档并注册。
因为XmlBeanFactory接受的参数是Resuorce类型的,所以要用new ClassPathResource来将目标文件转换为Resuorce类型。
接下来我进入loadBeanDefinitions方法,发现传入的Resource先被封装为了EncodedResource类,然后在另一个重载方法中获取对应的InputStrom并构造InputSource,然后将InputSource调用doLoadBeanDefinitions方法来进行解析。
在doLoadBeanDefinitions里将Resource转换为了Document,然后根据Document注册Bean信息。
进入doLoadDocument方法里,我们能看到里面调用了getValidationModeForResource方法,这个方法是来验证xml是否符合dtd或者xsd中定义的格式的。
到这里我们可以做一个小测试:
applicationContext.xml
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="hello" class="springtest.MyTestBean"/>
beans>
MyTestBean.java
public class MyTestBean {
private String teststr = "hello world";
public String getTeststr() {
return teststr;
}
public void setTeststr(String teststr) {
this.teststr = teststr;
}
}
BeanFactoryTest.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class BeanFactoryTest {
public static void main(String[] args) throws IOException {
XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
System.out.println("BeanFactory中Bean的数量:"+xmlBeanFactory.getBeanDefinitionCount());
String[] bdNames = xmlBeanFactory.getBeanDefinitionNames();
for(String str: bdNames)
System.out.println("bean的名字:"+str);
MyTestBean bean = (MyTestBean)xmlBeanFactory.getBean("hello");
System.out.println(bean.getTeststr());
}
}
如此简单的代码,在spring中其实是非常复杂的,上面分析的只是粗略的看了比较顶层的源码,接下来会继续分析更深层的代码。
上层代码的逻辑大概是:将文件转换为resource类型传入XmlBeanFactory中,XmlBeanFactory使用XmlBeanDefinitionReader中的loadBeanDefinitions来分析解析和注册bean,在loadBeanDefinitions中调用doLoadBeanDefinitions方法来验证资源文件并转换为Document类型,然后根据Document来进行Bean的解析和注册。
建议大家搭建环境,自己进去看看,不然很难弄清楚的。