spring容器初始化与bean获取的过程

412 阅读3分钟

spring容器初始化

首先我们使用一段原始的xml配置一个bean,并且自己创建资源及beanfactory等对象来获取bean。

Resource resource = new ClassPathResource("applicationContext.xml");

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

BeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);

reader.loadBeanDefinitions(resource);

Person p = (Person) beanFactory.getBean("person");

System.out.println(p);
<bean id="person" class="com.example.leetcode.spring.bean.Person">
    <property name="name" value="tom"></property>
</bean>

我们简单描述一下上面代码的意图:

  1. 创建一个Resource资源对象,spring对所有资源进行了抽象
  2. 创建了一个默认的DefaultListableBeanFactory工厂对象,作为ioc的容器。
  3. 创建一个BeanDefinitionReader,并将工厂传入进去并通过其loadBeanDefinitions方法传入resource驱动解析xml最终生成BeanDefinition对象信息。
  4. 通过beanFactory获取bean的对象

上面的代码主要包含两个流程:

  1. 容器初始化。 负责定位资源并解析bean的定义,最终将BeanDefinition对象存储到BeanDefinitionRegister对象中(DefaultListableBeanFactory实现了BeanDefinitionRegister接口)
  2. bean初始化。 当getBean时,会创建具体的bean对象,根据BeanDefinition的scop值,如果是singleton则会缓存创建后的bean对象供下次直接使用。

容器初始化过程

当我们执行reader.loadBeanDefinitions(resource);这句代码时,会开始解析并装配bean的定义信息到BeanDefinitionRegister中。流程如下:

  1. 首先进入XmlBeanDefinitionReader.loadBeanDefinitions方法进行BeanDefinition加载。
  2. 调用其内部方法doLoadBeanDefinitions做加载,主要做两件事:
    • 通过resource创建出xml Document对象供后续解析使用;
    • 通过registerBeanDefinitions从给定的Document对象中注册BeanDefinition
  3. registerBeanDefinitions创建BeanDefinitionDocumentReader对象,由其负责从Document中读取BeanDefinition信息并注册到register对象中(BeanDefinitionRegister)
  4. BeanDefinitionDocumentReader.doRegisterBeanDefinitions创建BeanDefinitionParserDelegate对象,委托其负责解析bean信息。在解析beanDefinition信息前后提供了回调方法(preProcessXml,postProcessXml)供用户定制化处理。
  5. 以xml bean节点为例BeanDefinitionDocumentReader.processBeanDefinition处理流程如下:
    • 通过BeanDefinitionParserDelegate对象解析并创建出BeanDefinition对象并包装成BeanDefinitionHolder
    • 通过BeanDefinitionReaderUtils.registerBeanDefinition将其注册到工厂中
    • 通过getReaderContext().fireComponentRegistered发送注册ReaderEventListener事件

小结: spring容器初始化的过程比较清晰易懂, 由主要的几个组件完成。分别是:Resource统一的资源抽象, DefaultListableBeanFactory(由于实现了BeanDefinitionRegister所以也有当成一个注册表),BeanDefinitionReader负责从不同形式的bean定义文件中读取BeanDefinition, BeanDefinitionDocumentReader通过委托解析并将BeanDefinition存储到BeanDefinitionRegister, BeanDefinitionParserDelegate负责具体的解析工作.

bean实例化获取过程

经过spring容器初始化后, DefaultListableBeanFactory已经拥有了BeanDefinition信息, 所以创建bean实例只需要在DefaultListableBeanFactory中即可完成。 这里查看DefaultListableBeanFactory继承关系会发现主要分为两类功能: 1, 作为BeanDefinition的注册表; 2. 作为BeanFactory创建Bean实例已经获取

具体的Bean实例过程如下:

  1. 通过AbstractBeanFactory.doGetBean获取bean对象。 这个方法的关键处理如下:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
	if (如果是单例对象) {
	    if(DefaultSingletonBeanRegistry中已经有生成好的单例对象){
	        return 对象
	    }
	}
    
    if (如果singleton作用域) {
        createBean
    }
    if(如果是property作用域){
        createBean
    }
}
  1. AbstractAutowireCapableBeanFactory负责创建bean对象并属性注入(大部分工作基本上这个类都做了)
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
    Object obj = BeanPostProcessor处理
    if(obj不为空) {
        return obj;
    }		
    通过doCreateBean创建bean
}

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {
    // 创建bean并返回一个被Wrapper的对象
    instanceWrapper = createBeanInstance(beanName, mbd, args); 
    
    // 通过MergedBeanDefinitionPostProcessor更新bean对象
    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    
    // 将生成好的singleton bean对象缓存
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    
    // 注入bean的属性值
    populateBean(beanName, mbd, instanceWrapper);
    
    // 初始化bean(调用init方法等)
    exposedObject = initializeBean(beanName, exposedObject, mbd);
    
    // bean注册到销毁记录
    registerDisposableBeanIfNecessary(beanName, bean, mbd);
}

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    ... 
    // 实例化bean
    return instantiateBean(beanName, mbd);
}

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    // 通过不同的策略来实例化bean
    beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
    // 对bean进行包装,便于后续注入属性值等
	BeanWrapper bw = new BeanWrapperImpl(beanInstance);
	initBeanWrapper(bw);
	return bw;
}

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // 将属性值注入(如setXxx())
    applyPropertyValues(beanName, mbd, bw, pvs);
}