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:/ ...
随机推荐
- HCNP Routing&Switching之路由引入导致的问题及解决方案
前文我们了解了路由引入相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15359902.html:今天我们来讨论下由于路由引入所导致的问题以及怎么避免此 ...
- IIS部署WCF详细教程
前言: 前段时间接手了公司一个十几年前的老项目,该项目对外提供的服务使用的是WCF进行通信的.因为需要其他项目需要频繁的使用该WCF服务,所以我决定把这个WCF部署到IIS中避免每次调试运行查看效果. ...
- 订单峰值激增 230%,Serverless 如何为世纪联华降本超 40%?|双11 云原生实践
作者 | 朱鹏 导读:2020 年 双11,世纪联华基于阿里云函数计算 (FC) 弹性扩容,应用于大促会场 SSR.线上商品秒杀.优惠券定点发放.行业导购.数据中台计算等多个场景,业务峰值 QPS 较 ...
- 洛谷3203 弹飞绵羊(LCT)
据说这个题当年的正解是分块qwq 根据题目所说,对于题目中的弹力系数,就相当于一条边,那么对于"跳出去"这个限制,我们可以选择建造一个新点\(n+1\)表示结束,那么每次,求一个点 ...
- keras框架下的深度学习(一)手写体识别
这个系列文章主要记录使用keras框架来搭建深度学习模型的学习过程,其中有一些自己的想法和体会,主要学习的书籍是:Deep Learning with Python,使用的IDE是pycharm. 在 ...
- 【数据结构与算法Python版学习笔记】树——利用二叉堆实现优先级队列
概念 队列有一个重要的变体,叫作优先级队列. 和队列一样,优先级队列从头部移除元素,不过元素的逻辑顺序是由优先级决定的. 优先级最高的元素在最前,优先级最低的元素在最后. 实现优先级队列的经典方法是使 ...
- js基础学习之"=="与"==="的区别
var a = 1; var b = 1; var c = "1"; 1. "==" 可理解为相等运算符.相等运算符比较时,会自己进行类型转换,等于什么类型就会 ...
- 乘风破浪,遇见上一代操作系统Windows 10 - 抢鲜尝试安装新微软商店(Microsoft Store)
背景 在微软官方文章的<十一项关于微软商店新知>中提到: 新的微软商店现在可在Windows 11上找到,我们很高兴地分享,它将在未来几个月内提供给Windows 10客户!我们将很快分享 ...
- CDP客户数据管理平台体系化搭建
一.Cdp系统简介 1.基本概念 客户数据平台(Customer-Data-Platform),简称CDP:通过采集多方客户数据(主体与线索)等,从而进行精准的客户分析和人群细分,进而实现高效的客户维 ...
- Django 前端BootCSS 实现分页
通过使用bootstrap框架,并配合Django自带的Paginator分页组件即可实现简单的分页效果. 1.创建MyWeb项目 python manage.py startapp MyWeb 2. ...