运行环境:jdk8,springboot-2.2.2
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
</parent>
创建Spring IOC容器对象
问题:
- 容器在哪里创建?
- 容器的运行时类型是什么?
// 启动类
@SpringBootApplication
public class BootApplication {
public static void main(String[] args) {
SpringApplication.run(BootApplication.class);
}
}
// 执行run方法时,创建Spring IOC容器。这里只是创建了容器对象,容器还未执行refresh方法
context = createApplicationContext();
SpringBoot
默认使用的容器类型是AnnotationConfigServletWebServerApplicationContext
Spring IOC容器结构分析
接下类分析下AnnotationConfigServletWebServerApplicationContext
下图的继承关系比较“吓人”,但是重点只有几个
-
GenericApplicationContext
这个类是
AnnotationConfigServletWebServerApplicationContext
的父类,GenericApplicationContext
持有成员变量private final DefaultListableBeanFactory beanFactory;
此成员变量的初始化是在调用
GenericApplicationContext
的无参构造器时执行的public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory(); }
-
DefaultListableBeanFactory
这个类是创建和管理bean实例的bean工厂
持有成员变量
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
保存最初的BeanDefinition
对象
其父类AbstractBeanFactory
持有成员变量
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
保存最终的BeanDefinition
对象,之后会调用其中的BeanDefinition
对象作为模板创建bean实例
其父类DefaultSingletonBeanRegistry
持有成员变量
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
保存创建完成的单实例bean
它还持有其他成员变量保存其他种类的bean实例
有了上述的继承关系AnnotationConfigServletWebServerApplicationContext
的对象将非常强大,这个对象将可以创建BeanDefinition
和bean实例,管理所有的BeanDefinition
和bean实例
补充
DefaultListableBeanFactory
的 beanDefinitionMap
和AbstractBeanFactory
的mergedBeanDefinitions
都保存了BeanDefinition
对象,那么创建bean实例时用谁做模板?
在AbStractApplicationContext
执行finishBeanFactoryInitialization(beanFactory)
方法创建剩余的所有非懒加载的单实例bean时
调用AbstractBeanFactory
的getMergedBeanDefinition
方法获取BeanDefinition
对象
会先调用抽象方法getBeanDefinition
(由DefaultListableBeanFactory
实现)
此方法会从DefaultListableBeanFactory
的beanDefinitionMap
中找BeanDefinition
找不到,抛异常;找到,对其加工,将其put到mergedBeanDefinitions
再从mergedBeanDefinitions
中获取并返回RootBeanDefinition
将其作为模板创建bean实例