1. 前言

xml配置的方式过于繁琐,现在一般更多通过注解或JavaConfig的方式来使用Spring,也就是会用到AnnotationConfigApplicationContext类。在这个类的启动过程中,有一个至关重要的类——AnnotatedBeanDefinitionReader,在它的构造函数里,往DefaultListableBeanFactory中注入了Spring内置的6个非常非常非常重要的BeanDefinition。

2. AnnotatedBeanDefinitionReader

在AnnotationConfigApplicationContext的构造函数里,会创建两个很重要的对象,AnnotatedBeanDefinitionReader顾名思义就是基于注解的BeanDefinition读取器,ClassPathBeanDefinitionScanner是基于ClassPath路径下的BeanDefinition扫描器。

public AnnotationConfigApplicationContext() {/*** 基于注解的BeanClass读取器,读取完是为了注册到容器中* 1.将BeanClass 解析成 AnnotatedGenericBeanDefinition* 2.注册BeanDefinition 到 BeanFactory*/this.reader = new AnnotatedBeanDefinitionReader(this);/*** BeanDefinition扫描器* 扫描包路径,得到BeanDefinition Set集合*/this.scanner = new ClassPathBeanDefinitionScanner(this);
}

重点关注AnnotatedBeanDefinitionReader类,它的两大职责:

  • 将基于注解的BeanClass转换为AnnotatedGenericBeanDefinition。
  • 将BeanDefinition注册到DefaultListableBeanFactory里。

它的构造函数很重要:

/*** 读取到BeanDefinition是为了完成注册,所以需要registry* @param registry BeanDefinition注册器* @param environment 环境对象*/
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");Assert.notNull(environment, "Environment must not be null");this.registry = registry;this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);// ***关键 注册Spring内置的 BeanPostProcessor 和 BeanFactoryPostProcessorAnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

因为Reader读取完BeanDefinition的目的是为了完成注册,所以需要一个注册器BeanDefinitionRegistry。这个注册器其实就是AnnotationConfigApplicationContext里的DefaultListableBeanFactory,说白了就是要把读取到的BeanDefinition注册到BeanFactory。
构造函数里的最后一行代码非常重要,它会向BeanFactory注册Spring内置的非常重要的后置处理器。

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {registerAnnotationConfigProcessors(registry, null);
}

它是一个空壳方法,最终调用重载方法:

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {// 获取DefaultListableBeanFactoryDefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);if (beanFactory != null) {if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {// 排序器 支持@Order @PrioritybeanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);}if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {// 依赖注入的候选Bean解析器beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());}}// 注册的BeanDefinition集合Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {/*** @see ConfigurationClassPostProcessor* 这个类 实现了BeanFactoryPostProcessor 接口* 在refresh方法中的 invokeBeanFactoryPostProcessors 时执行,完成BeanDefinition的注册过程* 这个后置处理器会扫描 @ComponentScan 路径下的Bean*/RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));}if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {/*** @see AutowiredAnnotationBeanPostProcessor* 完成依赖注入的后置处理器*/RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {/*** @see CommonAnnotationBeanPostProcessor* 支持Bean的@PostConstruct和@PreDestroy注解的后置处理器*/RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));}// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.// 针对JPA的支持,可先忽略if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition();try {def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,AnnotationConfigUtils.class.getClassLoader()));} catch (ClassNotFoundException ex) {throw new IllegalStateException("Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);}def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));}if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {/*** @see EventListenerMethodProcessor* 支持@EventListener的后置处理器*/RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));}if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {/*** @see DefaultEventListenerFactory* 将@EventListener方法注册为单个ApplicationListener示例*/RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));}return beanDefs;
}

2.1 ConfigurationClassPostProcessor

这个类实现了BeanFactoryPostProcessor接口,用来对BeanFactory进行扩展用的,在AnnotationConfigApplicationContext的refresh()方法中,会调用invokeBeanFactoryPostProcessors()方法调用所有的BeanFactoryPostProcessor扩展,其中就包含这里的ConfigurationClassPostProcessor。
它会完成对@ComponentScan路径下Bean的扫描和注册过程,也就是说,我们自定义的Bean将由这个类完成扫描并注册到BeanFactory中。

2.2 AutowiredAnnotationBeanPostProcessor

Spring的IOC容器,我们只需要声明Bean,Spring会自动帮我们进行依赖注入,这个活就是AutowiredAnnotationBeanPostProcessor干的。它实现了BeanPostProcessor接口,代表要针对Bean进行扩展,依赖注入也属于是针对Bean的一个扩展。

2.3 CommonAnnotationBeanPostProcessor

这个类实现了BeanPostProcessor接口,代表也是针对Bean的扩展点。它还继承了InitDestroyAnnotationBeanPostProcessor类,主要是针对@PostConstruct@PreDestroy@Resource注解的支持。

2.4 PersistenceAnnotationBeanPostProcessor

针对JPA的支持,没太了解,不是很重要,忽略。

2.5 EventListenerMethodProcessor

这个类实现了BeanFactoryPostProcessor接口,代表是针对BeanFactory的扩展点。它主要用来支持@EventListener注解,将EventListener方法注册为单个ApplicationListener实例。

2.6 DefaultEventListenerFactory

这个类没有实现任何PostProcessor,它不算是一个扩展点,主要是配合EventListenerMethodProcessor一起使用,它是一个工厂,用来将EventListener方法生成单个ApplicationListener实例。

AnnotatedBeanDefinitionReader相关推荐

  1. Spring 容器的启动过程

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 本文来源:http://r6f.cn/b47K 一. 前言 ...

  2. 难以想象SpringBoot中的条件注解底层居然是这样实现的

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源 | https://urlify.cn/bm2qqi Spr ...

  3. 面试:SpringBoot中的条件注解底层是如何实现的?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源 | https://urlify.cn/bm2qqi Spr ...

  4. Spring Context 你真的懂了吗?

    今天介绍一下大家常见的一个单词 context 应该怎么去理解,正确的理解它有助于我们学习 spring 以及计算机系统中的其他知识. 1. context 是什么 我们经常在编程中见到 contex ...

  5. spring boot 加载过程分析(三)

    接着上一篇,现在主要来看一下prepareContext方法的内容,先看代码: prepareContext执行过程 private void prepareContext(ConfigurableA ...

  6. 追踪解析Spring ioc启动源码(2)

    接上篇 3 reader 注册配置类 该 part 的起点: public AnnotationConfigApplicationContext(Class<?>... annotated ...

  7. 浅入 spring ioc 单例容器

    我们要干嘛? 1, 分析IOC 是怎么扫描路径 2, 对象是怎么被加载进容器的 3, 对象是怎么从容器里获取 4, 执行方法 案例代码, 网上一大顿分析xml的, 太low了, 我们直接从注解模式, ...

  8. 我该如何学习spring源码以及解析bean定义的注册

    如何学习spring源码 前言 本文属于spring源码解析的系列文章之一,文章主要是介绍如何学习spring的源码,希望能够最大限度的帮助到有需要的人.文章总体难度不大,但比较繁重,学习时一定要耐住 ...

  9. 剑指Spring源码(一)

    Spring,相信每个Java开发都用过,而且是每天都在用,那强大又神秘的IoC,AOP,让我们的开发变得越来越简单,只需要一个注解搞定一切,但是它内部到底是什么样子的呢?跟着我,一起探究Spring ...

最新文章

  1. 孪生素数 java代码_科学网—孪生素数猜想——利用 Java + 正则表达式 输出孪生素数对 - 马廷灿的博文...
  2. arg是什么函数_java后端开发三年!你还不了解Spring 依赖注入,凭什么给你涨薪...
  3. 怎么装python的keras库_matlab调用keras深度学习模型(环境搭建)
  4. 什么样的域名更利于优化?
  5. 20321关系数据库理论基础
  6. 乱查征信,贷款不想要了吗?
  7. 微服务实践沙龙-上海站
  8. 8086 INC, DEC
  9. activiti5第一弹-----基本的activiti示例
  10. 重构 - 美股行情系统APP推送改造
  11. JavaScript按概率随机生成事件
  12. 訪问可能没有定义的data (通过static类型flash.net:FileReference引用)
  13. 谷歌浏览器安装json-handle插件
  14. NXP ZigBee JN5169开发流程总结
  15. 操作系统的作用及类别
  16. 电子海图浮标信息的计算和输入
  17. Fresher练打字
  18. python一个强大的编程软件零基础也可以学习
  19. 计算机玩游戏怎么会突然有边框,电脑打游戏怎么设置全屏
  20. Python爬虫快速了解网页中javascript语言

热门文章

  1. 读英语计算机书籍读后感,英文书读后感范文(精选4篇)
  2. 论文学习——黄河源区气象水文序列突变点诊断
  3. 抽奖滚动效果 python_Python使用Tkinter实现滚动抽奖器效果
  4. [转]IText导出word之页眉页脚页码
  5. 计算机cad相关证书,cad证书含金量 工资一般是多少
  6. 二叉树的遍历及解题思路
  7. threejs 展示gltf模型加了环境光,全黑
  8. “程序包com.sun.image.codec.jpeg不存在“ 正解
  9. 睡不好为何昏昏沉沉?大脑:是我在发送警告
  10. 边列表(edgelist)和邻接矩阵(adjacency)相互转化(how to convert edge list to adjacency, or adjacency to edge list)