Spring源码解析 – AnnotationConfigApplicationContext容器创建过程

本文详细介绍了Spring中的AnnotationConfigApplicationContext容器的创建过程,从构造函数开始,逐步分析了如何初始化bean读取器和扫描器、注册bean配置类以及容器的刷新过程。在注册bean配置类时,解析了bean定义信息、处理了bean作用域,并通过BeanDefinitionHolder将bean定义信息注册到容器中。最后,文章还深入解析了refresh()方法,包括预处理、获取和预处理Bean工厂、注册BeanPostProcessor等步骤,展示了Spring容器初始化的完整流程。
摘要由CSDN通过智能技术生成

Spring在BeanFactory基础上提供了一些列具体容器的实现,其中AnnotationConfigApplicationContext是一个用来管理注解bean的容器,从AnnotationConfigApplicationContext的实现结构图中可以看出:

AnnotationConfigApplicationContext继承GenericApplicationContext这个通用应用上下文,GenericApplicationContext内部定义了一个DefaultListableBeanFactory实例,GenericApplicationContext实现了BeanDefinitionRegistry接口,所以可以通过AnnotationConfigApplicationContext实例注册bean defintion,然后调用refresh()方法来初始化上下文。
AnnotationConfigApplicationContext继承AbstractApplicationContext,AbstractApplicationContext提供了ApplicationContext的抽象实现。
下面通过一个示例分析AnnotationConfigApplicationContext的初始化过程:

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ExtensionConfig.class);
构造函数:

复制代码
1 //1. 初始化bean读取器和扫描器;
2 //调用父类GenericApplicationContext无参构造函数,初始化一个BeanFactory: DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory()
3 this();
4 //2.注册bean配置类
5 register(annotatedClasses);
6 //3.刷新上下文
7 refresh();
8 }
复制代码

  1. this() 初始化bean读取器和扫描器

1 public AnnotationConfigApplicationContext() {
2 //在IOC容器中初始化一个 注解bean读取器AnnotatedBeanDefinitionReader
3 this.reader = new AnnotatedBeanDefinitionReader(this);
4 //在IOC容器中初始化一个 按类路径扫描注解bean的 扫描器
5 this.scanner = new ClassPathBeanDefinitionScanner(this);
GenericApplicationContext部分代码:

复制代码
1 public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
2 private final DefaultListableBeanFactory beanFactory;
3
4 //初始化一个BeanFactory
5 public GenericApplicationContext() {
6 this.beanFactory = new DefaultListableBeanFactory();
7 }
8
9 …
10 }
复制代码
2. register(annotatedClasses)

注册bean配置类, AnnotationConfigApplicationContext容器通过AnnotatedBeanDefinitionReader的register方法实现注解bean的读取,具体源码如下:

AnnotationConfigApplicationContext.java中register方法

复制代码
1 //按指定bean配置类读取bean
2 public void register(Class<?>… annotatedClasses) {
3 for (Class<?> annotatedClass : annotatedClasses) {
4 registerBean(annotatedClass);
5 }
6 }
7
8 public void registerBean(Class<?> annotatedClass) {
9 doRegisterBean(annotatedClass, null, null, null);
10 }
11
12 //核心实现逻辑
13 void doRegisterBean(Class annotatedClass, @Nullable Supplier instanceSupplier, @Nullable String name,
14 @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer… definitionCustomizers) {
15 //将Bean配置类信息转成容器中AnnotatedGenericBeanDefinition数据结构, AnnotatedGenericBeanDefinition继承自BeanDefinition作用是定义一个bean的数据结构,下面的getMetadata可以获取到该bean上的注解信息
16 AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
17 //@Conditional装配条件判断是否需要跳过注册
18 if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
19 return;
20 }
21 //@param instanceSupplier a callback for creating an instance of the bean
22 //设置回调
23 abd.setInstanceSupplier(instanceSupplier);
24 //解析bean作用域(单例或者原型),如果有@Scope注解,则解析@Scope,没有则默认为singleton
25 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
26   //作用域写回BeanDefinition数据结构, abd中缺损的情况下为空,将默认值singleton重新赋值到abd
27 abd.setScope(scopeMetadata.getScopeName());
28   //生成bean配置类beanName
29 String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
30 //通用注解解析到abd结构中,主要是处理Lazy, primary DependsOn, Role ,Description这五个注解
31 AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
32   //@param qualifiers specific qualifier annotations to consider, if any, in addition to qualifiers at the bean class level
33   // @Qualifier特殊限定符处理,
34 if (qualifiers != null) {
35 for (Class<? extends Annotation> qualifier : qualifiers) {
36 if (Primary.class == qualifier) {
37 // 如果配置@Primary注解,则设置当前Bean为自动装配autowire时首选bean
38 abd.setPrimary(true);
39 }
40   else if (Lazy.class == qualifier) {
41   //设置当前bean为延迟加载
42 abd.setLazyInit(true);
43 }
44 else {
45       //其他注解,则添加到abd结构中
46 abd.addQualifier(new AutowireCandidateQualifier(qualifier));
47 }
48 }
49 }
50   //自定义bean注册,通常用在applicationContext创建后,手动向容器中一lambda表达式的方式注册bean,
51   //比如:applicationContext.registerBean(UserService.class, () -> new UserService());
52 for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
53     //自定义bean添加到BeanDefinition
54 customizer.customize(abd);
55 }
56 //根据beanName和bean定义信息封装一个beanhold,heanhold其实就是一个 beanname和BeanDefinition的映射
57 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
58   //创建代理对象
59 definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
60   // BeanDefinitionReaderUtils.registerBeanDefinition 内部通过DefaultListableBeanFactory.registerBeanDefinition(String beanName, BeanDefinition beanDefinition)按名称将bean定义信息注册到容器中,
61   // 实际上DefaultListableBeanFactory内部维护一个Map<String, BeanDefinition>类型变量beanDefinitionMap,用于保存注bean定义信息(beanname 和 beandefine映射)
62 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
63 }
复制代码
register方法重点完成了bean配置类本身的解析和注册,处理过程可以分为以下几个步骤:

根据bean配置类,使用BeanDefinition解析Bean的定义信息,主要是一些注解信息
Bean作用域的处理,默认缺少@Scope注解,解析成单例
借助AnnotationConfigUtils工具类解析通用注解
将bean定义信息已beanname,beandifine键值对的形式注册到ioc容器中
3. refresh()刷新上下文

refresh方法在AbstractApplicationContext容器中实现,refresh()方法的作用加载或者刷新当前的配置信息,如果已经存在spring容器,则先销毁之前的容器,重新创建spring容器,载入bean定义,完成容器初始化工作,所以可以看出AnnotationConfigApplicationContext容器是通过调用其父类AbstractApplicationContext的refresh()函数启动整个IoC容器完成对Bean定义的载入。

AbstractApplicationContext.java中refresh方法的实现代码如下:

复制代码
1 public void refresh() throws BeansException, IllegalStateException {
2 synchronized (this.startupShutdownMonitor) {
3 //1.刷新前的预处理
4 prepareRefresh();
5
6 //2.获取刷新后的内部Bean工厂
7 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
8
9 //3.BeanFactory的预准备工作
10 prepareBeanFactory(beanFactory);
11
12 try {
13 // BeanFactory准备工作完成后,可以做一些后置处理工作,
14      // 4.空方法,用于在容器的子类中扩展
15 postProcessBeanFactory(beanFactory);
16
17 // 5. 执行BeanFactoryPostProcessor的方法,BeanFactory的后置处理器,在BeanFactory标准初始化之后执行的
18 invokeBeanFactoryPostProcessors(beanFactory);
19
20 // 6. 注册BeanPostProcessor(

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值