AnnotationConfigApplicationContext(1)之初始化Scanner和Reader
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的更多相关文章
- Spring源码解析 – AnnotationConfigApplicationContext容器创建过程
Spring在BeanFactory基础上提供了一些列具体容器的实现,其中AnnotationConfigApplicationContext是一个用来管理注解bean的容器,从AnnotationC ...
- Spring5深度源码分析(三)之AnnotationConfigApplicationContext启动原理分析
代码地址:https://github.com/showkawa/spring-annotation/tree/master/src/main/java/com/brian AnnotationCon ...
- 框架源码系列六:Spring源码学习之Spring IOC源码学习
Spring 源码学习过程: 一.搞明白IOC能做什么,是怎么做的 1. 搞明白IOC能做什么? IOC是用为用户创建.管理实例对象的.用户需要实例对象时只需要向IOC容器获取就行了,不用自己去创建 ...
- 基于注解的Spring容器源码分析
从spring3.0版本引入注解容器类之后,Spring注解的使用就变得异常的广泛起来,到如今流行的SpringBoot中,几乎是全部使用了注解.Spring的常用注解有很多,有@Bean,@Comp ...
- Spring源码分析之IOC的三种常见用法及源码实现(一)
1.ioc核心功能bean的配置与获取api 有以下四种 (来自精通spring4.x的p175) 常用的是前三种 第一种方式 <?xml version="1.0" enc ...
- Spring源码系列——容器的启动过程(一)
一. 前言 Spring家族特别庞大,对于开发人员而言,要想全面征服Spring家族,得花费不少的力气.俗话说,打蛇打七寸,那么Spring家族的"七寸"是什么呢?我心目中的答案一 ...
- Spring IOC-基于注解配置的容器
Spring中提供了基于注解来配置bean的容器,即AnnotationConfigApplicationContext 1. 开始 先看看在Spring家族中,AnnotationConfigApp ...
- iOS ZBarSDK的基本使用:扫描
1.首先使用Cocoapods导入库 ZBarSDK 2.敲代码: ViewController.h // // ViewController.h // erweima // // Created b ...
- Java编程的逻辑 (10) - 强大的循环
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...
随机推荐
- 数值计算:Legendre多项式
Legendre多项式的概念以及正交特性在此不多作描述,可以参考数学物理方程相关教材,本文主要讨论在数值计算中对于Legendre多项式以及其导数的计算方法. Legendre多项式的计算 递推公式 ...
- Java JDK的下载与安装!Java基础
在了解什么是Java.Java 语言的特点以及学习方法之后,本节将介绍如何搭建编写 Java 程序所需要的开发环境--JDK,只有搭建了环境才能敲代码! 学Java的都知道,JDK 是一种用于构建在 ...
- RPAaaS是什么?为何能够推进RPA人人可用?
RPAaaS是什么?为何能够推进RPA人人可用? 助力中小企业快速实现自动化,RPAaaS加速"RPA人人可用"时代到来 相对传统RPA拥有更多优势,PRAaaS为RPA行业带来更 ...
- Python ThreadPoolExecutor 线程池导致内存暴涨
背景 在有200W的任务需要取抓取的时候,目前采用的是线程池去抓取,最终导致内存暴涨. 原因 Threadpoolexcutor默认使用的是无界队列,如果消费任务的速度低于生产任务,那么会把生产任务无 ...
- javascript-原生-函数
本节呢讲解js的函数部分,js函数部分总共分为两大类:1.自定义函数.2.系统函数 说白了,系统函数就是js自己内置的函数,其他的都属于自定义函数. 1.自定义函数 函数是完成指定功能的程序段,可以反 ...
- python解释器和Pycharm编辑器安装使用完整详细教程
一.官网下载或软件管家公众号下载 二.安装Python解释器 1.选择自定义安装并添加到环境变量 2.检验Python是否安装成功 三.安装pycharm编辑器 1.点击安装,修改安装路径,建议安装C ...
- CICD 流水线就该这么玩系列之一
今天给大家分享的是 DevOps 世界中非常流行的一个 GitOps 工具 - Argo CD.如果你还不知道什么是 GitOps,欢迎留言告诉我,根据热度,我会再写一篇详细讲解 GitOps 的文章 ...
- poi实现生成下拉选联动
在我们实际的程序开发中,经常需要用到从excel导入数据中系统中,而为了防止用户在excel中乱输入文字,有些需要用到下拉选的地方,就需要从程序中动态生成模板.本例子简单的讲解一下,如何生成级联下拉选 ...
- 冲刺noip2021模拟16
T1 树上的数 考场上比较脑瘫没有想到直接dfs就行了这样是O(n+m)的,傻不拉几地多添了个log, 不过因为accoder的评测机太弱了,绝大多数人的正解都是60分,所以没有什么差别: 直接dfs ...
- 2021.8.6考试总结[NOIP模拟32]
T1 smooth 考场上水个了优先队列多带个$log$,前$80$分的点跑的飞快,后面直接萎了. 其实只需开$B$个队列,每次向对应队列中插入新的光滑数,就能保证队列中的数是单调的. 为了保证不重, ...