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>
我们简单描述一下上面代码的意图:
- 创建一个Resource资源对象,spring对所有资源进行了抽象
- 创建了一个默认的DefaultListableBeanFactory工厂对象,作为ioc的容器。
- 创建一个BeanDefinitionReader,并将工厂传入进去并通过其loadBeanDefinitions方法传入resource驱动解析xml最终生成BeanDefinition对象信息。
- 通过beanFactory获取bean的对象
上面的代码主要包含两个流程:
- 容器初始化。 负责定位资源并解析bean的定义,最终将BeanDefinition对象存储到BeanDefinitionRegister对象中(DefaultListableBeanFactory实现了BeanDefinitionRegister接口)
- bean初始化。 当getBean时,会创建具体的bean对象,根据BeanDefinition的scop值,如果是singleton则会缓存创建后的bean对象供下次直接使用。
容器初始化过程
当我们执行reader.loadBeanDefinitions(resource);这句代码时,会开始解析并装配bean的定义信息到BeanDefinitionRegister中。流程如下:
- 首先进入XmlBeanDefinitionReader.loadBeanDefinitions方法进行BeanDefinition加载。
- 调用其内部方法doLoadBeanDefinitions做加载,主要做两件事:
- 通过resource创建出xml Document对象供后续解析使用;
- 通过registerBeanDefinitions从给定的Document对象中注册BeanDefinition
- registerBeanDefinitions创建BeanDefinitionDocumentReader对象,由其负责从Document中读取BeanDefinition信息并注册到register对象中(BeanDefinitionRegister)
- BeanDefinitionDocumentReader.doRegisterBeanDefinitions创建BeanDefinitionParserDelegate对象,委托其负责解析bean信息。在解析beanDefinition信息前后提供了回调方法(preProcessXml,postProcessXml)供用户定制化处理。
- 以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实例过程如下:
- 通过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
}
}
- 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);
}