AnnotationConfigApplicationContext(1)初始化Scanner和Reader

我们以AnnotationConfigApplicationContext为起点来探究Spring的启动过程

首先引入眼帘的就是AnnotationConfigApplicationContext的构造方法,而我们今天只来探讨this();

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
//this()方法这里就创建了一个Bean工厂和Reader和Scanner
this();
register(componentClasses);
refresh();
}

  

public AnnotationConfigApplicationContext() {
StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
// 生成并注册5个BeanDefinition
// 1.ConfigurationClassPostProcessor
// 2.AutowiredAnnotationBeanPostProcessor
// 3.CommonAnnotationBeanPostProcessor
// 4.EventListenerMethodProcessor
// 5.DefaultEventListenerFactory
this.reader = new AnnotatedBeanDefinitionReader(this);
createAnnotatedBeanDefReader.end();
// 注册默认的includeFilter
this.scanner = new ClassPathBeanDefinitionScanner(this);
}

  

AnnotationConfigApplicationContext首先会生成Reader和Scanner,但在这之前,BeanFactory其实已经实例化完成了

因为AnnotationConfigApplicationContext是GenericApplicationContext的子类,父类的构造器要优先于子类构造器执行,所以在执行AnnotationConfigApplicationContext类的无参构造时,会先执行GenericApplicationContext的无参构造:

public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}

  

一、AnnotatedBeanDefinitionReader

Spring在实例化AnnotatedBeanDefinitionReader做了很多,最主要的就是将内部的后置处理器注册到Spring中

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;
   //ConditionEvaluator对象封装了spring容器的信息
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
/**
* 将所有相关的后置处理器注册到这个registry中
*/
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

  将spring相关信息记录到conditionEvaluator对象后,spring开始注册相关后置处理器

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {
//将刚刚开始第一次new得bean工厂获得,
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
//加载组件,其中包括AnnotationAwareOrderComparator和ContextAnnotationAutowireCandidateResolver
//AnnotationAwareOrderComparator可以对实现PriorityOrdered、Ordered以及被@Order注解修饰的类进行统一的排序
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
//AutowireCandidateResolver 用来判断一个给定的 bean 是否可以注入,最主要的方法是 isAutowireCandidate
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
//BeanDefinitionHolder中有beanDefinition,beanName,alias
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source); //null
/**
* registerPostProcessor方法:
* 将beanName和BeanDefinition按Key—value键值对得方式放在BeanDefinitionMap中
* 将BeanName放在BeanDefinitionNames列表中,
* 将BeanName和BeanDefinition封装在BeanDefinitionHolder中,
* 将封装好得BeanDefinitionHolder放在BeanDefs列表中。
* 这里其实就是注册内部的后置处理器
*/
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//AutowiredAnnotationBeanPostProcessor
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
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)) {
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.
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));
}
//EventListenerMethodProcessor
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
//DefaultEventListenerFactory
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}

  

二、ClassPathBeanDefinitionScanner

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
if (useDefaultFilters) {
//添加includeFilters
//注册一个@Component注解对应的Filter
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}

  在开篇的时候我们提到了Scanner的用法,其中就提及到了includeFilters

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
ClassPathBeanDefinitionScanner classPathBeanDefinitionScanner = new ClassPathBeanDefinitionScanner(factory);
//得到该包下类的个数
// int scan = classPathBeanDefinitionScanner.scan("com.beans");
// System.out.println(scan);//6
//扫描没有加@Componment注解的类,并注册到容器中,未通过注解或其他方式定义Bean的类也不会添加到容器中
//classPathBeanDefinitionScanner.addExcludeFilter(new AnnotationTypeFilter(Component.class));
//扫描加了@Componment注解的类,并注册到容器中
classPathBeanDefinitionScanner.addIncludeFilter(new AnnotationTypeFilter(Component.class));
//获取bean
Object bean = factory.getBean(BeanTest.class);
System.out.println(bean);//com.beans.BeanTest@5ccddd20

  Spring会默认向includeFilters添加了@Componment注解

protected void registerDefaultFilters() {
  this.includeFilters.add(new AnnotationTypeFilter(Component.class));
  ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
  try {
    this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
    logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
  }catch (ClassNotFoundException ex) {
// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
  }
  try {
    this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
    logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
  }catch (ClassNotFoundException ex) {
    // JSR-330 API not available - simply skip.
  }
}

  到这里Spring就完成了AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner注解的实例化

AnnotationConfigApplicationContext(1)之初始化Scanner和Reader的更多相关文章

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

    Spring在BeanFactory基础上提供了一些列具体容器的实现,其中AnnotationConfigApplicationContext是一个用来管理注解bean的容器,从AnnotationC ...

  2. Spring5深度源码分析(三)之AnnotationConfigApplicationContext启动原理分析

    代码地址:https://github.com/showkawa/spring-annotation/tree/master/src/main/java/com/brian AnnotationCon ...

  3. 框架源码系列六:Spring源码学习之Spring IOC源码学习

    Spring 源码学习过程: 一.搞明白IOC能做什么,是怎么做的  1. 搞明白IOC能做什么? IOC是用为用户创建.管理实例对象的.用户需要实例对象时只需要向IOC容器获取就行了,不用自己去创建 ...

  4. 基于注解的Spring容器源码分析

    从spring3.0版本引入注解容器类之后,Spring注解的使用就变得异常的广泛起来,到如今流行的SpringBoot中,几乎是全部使用了注解.Spring的常用注解有很多,有@Bean,@Comp ...

  5. Spring源码分析之IOC的三种常见用法及源码实现(一)

    1.ioc核心功能bean的配置与获取api 有以下四种 (来自精通spring4.x的p175) 常用的是前三种 第一种方式 <?xml version="1.0" enc ...

  6. Spring源码系列——容器的启动过程(一)

    一. 前言 Spring家族特别庞大,对于开发人员而言,要想全面征服Spring家族,得花费不少的力气.俗话说,打蛇打七寸,那么Spring家族的"七寸"是什么呢?我心目中的答案一 ...

  7. Spring IOC-基于注解配置的容器

    Spring中提供了基于注解来配置bean的容器,即AnnotationConfigApplicationContext 1. 开始 先看看在Spring家族中,AnnotationConfigApp ...

  8. iOS ZBarSDK的基本使用:扫描

    1.首先使用Cocoapods导入库 ZBarSDK 2.敲代码: ViewController.h // // ViewController.h // erweima // // Created b ...

  9. Java编程的逻辑 (10) - 强大的循环

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

随机推荐

  1. 活动回顾|ShardingSphere X openGauss,将会产生怎样的化学反应?

    "ShardingSphere 作为 openGauss 生态的开源分布式数据库解决方案,将持续助力于 openGauss,满足千行百业广大客户分布式场景需求." 5月29日,由  ...

  2. 洛谷3613睡觉困难综合征(LCT维护链信息(前后缀)+贪心)

    这个题目还是很好啊QWQ很有纪念意义 首先,如果在序列上且是单次询问的话,就是一个非常裸的贪心了QWQ这也是NOI当时原题的问题和数据范围 我们考虑上树的话,应该怎么做? 我的想法是,对于每一位建一个 ...

  3. 升级更新 Windows10

    升级更新 Windows10:获取 Windows 更新助手 升级 Windows10,它是先下载 Windows10 系统镜像,然后才升级.在下载完 Windows10 后,升级前,有一步骤会询问: ...

  4. iOS路由最佳选择是什么

    背景 记得四年前iOS路由开始盛行,当时比较有名的是蘑菇街的,后来CTMediator写了几篇文章把蘑菇街批的体无完肤,导致我后来写新项目用了CTMediator,那一堆组件创建的叫一个酸爽啊!再后来 ...

  5. Golang通脉之指针

    指针的概念 指针是存储另一个变量的内存地址的变量. 变量是一种使用方便的占位符,用于引用计算机内存地址. 一个指针变量可以指向任何一个值的内存地址. 在上面的图中,变量b的值为156,存储在内存地址0 ...

  6. Beta Scrum Meeting汇总

    第0次Alpha Scrum Meeting 第1次Alpha Scrum Meeting 第2次Alpha Scrum Meeting 第3次Alpha Scrum Meeting 第4次Alpha ...

  7. [对对子队]会议记录4.17(Scrum Meeting8)

    今天已完成的工作 何瑞 ​ 工作内容:修复了一些bug,优化了UI ​ 相关issue:搭建关卡1 ​ 相关签入:4.17签入1 吴昭邦 ​ 工作内容:做了一些流水线系统的错误处理,添加了合成失败了之 ...

  8. seata整合nacos完成分布式的部署

    seata整合nacos完成分布式的部署 一.背景 二.部署机器 三.部署步骤 1.在seata上创建命名空间 2.下载对应版本的seata 3.单机启动 1.修改seata配置文件 1.修改注册中心 ...

  9. Kotlin/Native 用KMM写Flutter插件

    一.用KMM写Flutter插件 Google官方有一个写Flutter例子How to write a Flutter plugin,这里把Google plugin_codelab 例子改成用KM ...

  10. 【做题记录】 [JLOI2011]不等式组

    P5482 [JLOI2011]不等式组 超烦人的细节题!(本人调了两天 QAQ ) 这里介绍一种只用到一只树状数组的写法(离线). 树状数组的下标是:所有可能出现的数据进行离散化之后的值. 其含义为 ...