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:/ ...
随机推荐
- IL合集
由于之前写的表达式树合集,未编写任何注释且是以图片的形式展现给大家,在这里向各位看官道歉了,接下来为大家奉上新鲜出炉的香喷喷的IL合集,后面会持续更新,各位看官点关注不迷路,之前答应的手写IOC以及多 ...
- 【NOIP1998】 三连击 题解
文章转载前需和原作者联系,否则追究法律责任 题目链接:https://www.luogu.com.cn/problem/P1008 首先我们来分析一下题目.要求是枚举三个数,比例为1:2:3,且各个数 ...
- Eureka使用总结
关于Eureka: 提供基于 REST的服务,在集群中主要用于服务管理.使用该框架,可以将业务组件注册到Eureka容器中,这些组件可进行集群部署,Eureka主要维护这些服务的列表并自动检查他们的状 ...
- 2021年1月-第02阶段-前端基础-HTML+CSS进阶-VS Code 软件
软件安装 VSCode软件 能够安装 VS Code 能够熟练使用 VS Code 软件 能够安装 VS Code 最常用的插件 1. VS Code简介 1.1 VS Code 简介 Visual ...
- 项目优化之v-if
前言: 在vue项目中,由于功能比较多,需要各种条件控制某个功能.某个标签.表格中的某一行是否显示等,需要使用大量的v-if来判断条件. 例如: <div v-if="isShow(a ...
- .NET 事件总线,简化项目、类库、线程、服务等之间的通信,代码更少,质量更好。
Jaina .NET 事件总线,简化项目.类库.线程.服务等之间的通信,代码更少,质量更好. 安装 Package Manager Install-Package Jaina .NET CLI do ...
- [敏捷软工团队博客]Beta阶段事后分析
设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件要解决的问题是:现在的软工课程的作业分布在博客园.GitHub上,没有一个集成多种功能的一体化 ...
- AIApe问答机器人Scrum Meeting 4.29
Scrum Meeting 4 日期:2021年4月29日 会议主要内容概述:汇报两日工作,讨论任务优先级. 一.进度情况 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作中遇到的困难 李明 ...
- 2020BUAA软工个人项目作业
2020BUAA软工个人项目作业 17373010 杜博玮 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人项目作业 我在这个课程的目标是 学 ...
- spring cloud config的使用
在传统的应用中,我们的配置文件都是放在项目中,这个影响不大.但是在一个微服务架构的系统中,我们的微服务可能存在几十上百个,并且每个小的微服务可能又部署在多台机器上,那么这个时候如果我们的配置文件在都放 ...