XML 配置文件的读取时Spring中重要的功能,因为Spring的大部分功能都是以配置作为切入点的,那么我们可以从XMLBeanDefinitionReader中梳理一下资源文件读取、解析即注册的大致脉络。
BeanDefinition 的加载、解析、注册过程
/**
* 用XMLBeanDefinitionReader 加载配置文件
*/
@Test
public void useXMLBeanDefinitionReaderLoadXML() {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions("spring/applicationContext-test.xml");
UserServiceImpl userService = factory.createBean(UserServiceImpl.class);
userService.getUserInfo();
}
Bean的获取与创建:
源码分析:
protected T doGetBean(
final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
//提取对用的beanName
final String beanName = transformedBeanName(name);
Object bean;
//检查缓存中或实例工厂中是否有对应的实例
//为什么首先会使用这段代码呢?
//因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖
//Spring 创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光
// 也就是将ObjectFactory 加入到缓存中,一旦下个bean创建时候需要依赖上个bean则直接使用ObjectFactory
//直接尝试从缓存中获取或者singletonFactories中的ObjectFactory中获取
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 检查循环依赖
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
try {
//将存储XML配置文件 的GerbericBeanDefinition 转换为 RootBeanDefinition,如果是指定BeanName 是子Bean的话同时会 合并父类的相关属性
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
//若存在依赖则需要递归实例化依赖的bean
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
}
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean);
}
}
// singleton 模式的创建
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory
1.转换对应的beanName,传入的参数name可以是beanName 或者是别名,也可能是FactiryBean。
2.尝试从缓存中加载单例ApplicationContext 获取Bean的过程: