现在都是在springboot 中 集成 spirng,那我们就从springboot 开始。

一:springboot 启动main 函数

 public static void main(String[] args) throws Exception {
SpringApplication.run(AuditCenterWebApp.class, args);
}

  

  二:跟踪下来,会进入到springAppliaction  的 run(String... args) 方法。

 public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting(); Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
      // 组织环境
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
      // 打印我们设置的banner
Banner printedBanner = this.printBanner(environment);
/**创建applicationContext 默认webApplicationType 是 SERVLET,
所以返回的是org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext对象*/
context = this.createApplicationContext();
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
// 准备上下文
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 刷新上下文
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
} listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
} try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}

  三:准备上下文 this.prepareContext

点击进入,跟踪 this.load(context, sources.toArray(new Object[0])); 方法

    private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
this.postProcessApplicationContext(context);
this.applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {
this.logStartupInfo(context.getParent() == null);
this.logStartupProfileInfo(context);
} context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
} Set<Object> sources = this.getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
this.load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}

  

  四:我们看一下 BeanDefinitionLoader 是如何创建的

protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
} BeanDefinitionLoader loader = this.createBeanDefinitionLoader(this.getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
} if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
} if (this.environment != null) {
loader.setEnvironment(this.environment);
} loader.load();
}

  (1)getBeanDefinitionRegistry,返回的是 BeanDefinitionRegistry 接口。 将 beanDefinitionRegistry 作为参数 创建 BeanDefinitionLoader

BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
Assert.notNull(registry, "Registry must not be null");
Assert.notEmpty(sources, "Sources must not be empty");
    // 此处的source 就是第一步中 SpringApplication.run(AuditCenterWebApp.class,args) 中的 AuditCenterWebApp.class
this.sources = sources;
    // new 一个注解的读取器
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
this.xmlReader = new XmlBeanDefinitionReader(registry);
if (this.isGroovyPresent()) {
this.groovyReader = new GroovyBeanDefinitionReader(registry);
}
// new Bean定义的扫描器
this.scanner = new ClassPathBeanDefinitionScanner(registry);
this.scanner.addExcludeFilter(new BeanDefinitionLoader.ClassExcludeFilter(sources));
}

  

  (2)我们看下AnnotatedBeanDefinitionReader 的创建,AnnotatedBeanDefinitionReader 里注册了 proccess。跟踪代码到 AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

在这个方法里 springboot 注册 了spring 的几个注解 processor, spring的注解分为几类,每一类注解都有相应注解处理器

// configuration 注解,是个引导注解,所以的他的优先级是很高的,@Configuration 就是由他来处理
org.springframework.context.annotation.internalConfigurationAnnotationProcessor -> org.springframework.context.annotation.ConfigurationClassPostProcessor
// 自动装配的处理器,可以自动装配带注解的字段,他支持(@Value, @Autowired, @Inject, @Lookup),默认他的require=true
org.springframework.context.annotation.internalAutowiredAnnotationProcessor -> org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
// 用来检查java 的bean 的属性值 @Required
org.springframework.context.annotation.internalRequiredAnnotationProcessor -> org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
// 这个注解支持许多java注解和jsr-250 注解。@PostConstruct,@PreDestroy,@Resource等
org.springframework.context.annotation.internalCommonAnnotationProcessor -> org.springframework.context.annotation.CommonAnnotationBeanPostProcessor org.springframework.context.event.internalEventListenerProcessor -> org.springframework.context.event.EventListenerMethodProcessor
org.springframework.context.event.internalEventListenerFactory -> org.springframework.context.event.DefaultEventListenerFactory

  五:好了回到第四步,调用了 BeanDefinitionLoader 的load()方法。再次跟进load()

public int load() {
int count = 0;
// 此处source 是 AuditCenterWebApp
Object[] var2 = this.sources;
int var3 = var2.length; for(int var4 = 0; var4 < var3; ++var4) {
Object source = var2[var4];
// 将 AuditCenterWebApp 作为入参传入
count += this.load(source);
} return count;
}

  六:这里判断启动类上是否有启动的注解

 private int load(Class<?> source) {
if (this.isGroovyPresent() && BeanDefinitionLoader.GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
BeanDefinitionLoader.GroovyBeanDefinitionSource loader = (BeanDefinitionLoader.GroovyBeanDefinitionSource)BeanUtils.instantiateClass(source, BeanDefinitionLoader.GroovyBeanDefinitionSource.class);
this.load(loader);
}
// 是否是组件,会根据启动类中是否有启动的注解 或者 根据类的信息本身(类名,构造方法等)
if (this.isComponent(source)) {
this.annotatedReader.register(new Class[]{source});
return 1;
} else {
return 0;
}
}

  一直往下跟踪,跟踪到 org.springframework.context.annotation.AnnotatedBeanDefinitionReader#doRegisterBean 方法

这个方法叫doRegisterBean  ,根据类型和方法名 可以知道:这个方法是注册 注解处理器的bean定义信息的

 <T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
    // 创建bean的定义信息对象(类名,类的元数据对象)
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
abd.setInstanceSupplier(instanceSupplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
// singleton
abd.setScope(scopeMetadata.getScopeName());
// auditCenterWebApp
String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
int var10;
int var11;
// qualifiers == null 上一层写死
if (qualifiers != null) {
Class[] var9 = qualifiers;
var10 = qualifiers.length; for(var11 = 0; var11 < var10; ++var11) {
Class<? extends Annotation> qualifier = var9[var11];
if (Primary.class == qualifier) {
abd.setPrimary(true);
} else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
} else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
} BeanDefinitionCustomizer[] var13 = definitionCustomizers;
var10 = definitionCustomizers.length; for(var11 = 0; var11 < var10; ++var11) {
BeanDefinitionCustomizer customizer = var13[var11];
customizer.customize(abd);
}
// 将beanDefinition 和 beanName 包装成BeanDefinitionHolder, adb就是bean定义信息对象
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}

跟踪 BeanDefinitionReaderUtils.registerBeanDefinition 方法。

GenericApplicationContext 类中 定义的beanFactory是 DefaultListableBeanFactory,所以最后调的是 DefaultListableBeanFactory 的 registerBeanDefinition

  public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
// 调用的是 GenericApplicationContext 的registerBeanDefinition 方法。
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
String[] var4 = aliases;
int var5 = aliases.length; for(int var6 = 0; var6 < var5; ++var6) {
String alias = var4[var6];
registry.registerAlias(beanName, alias);
}
} }

这里是开始注册bean 定义信息(注解处理器,启动类 等 基础bean信息),将bean信息注册到

List<String> beanDefinitionNames                                         // bean 定义信息的注册名称 列表,有序
Map<String, BeanDefinition> beanDefinitionMap                  // bean 定义信息 的映射,无序
Set<String> manualSingletonNames                                     //手动注册的单例名称列表

 public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var9) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var9);
}
}
//Map<String, BeanDefinition> beanDefinitionMap ,key=bean名称,bean 对象的定义
// bean 定义对象的映射,beanName 是对象的全限定名称
BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
// 如果定义了重复的bean 名称,是否允许覆盖,默认true
if (!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");
} if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else if (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
} this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
// 注册工作是否已经启动
if (this.hasBeanCreationStarted()) {
synchronized(this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
} else {
// 正常的话,会走到这里。设置bean 的名称和定义
this.beanDefinitionMap.put(beanName, beanDefinition);
// bean定义的名称列表
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
} this.frozenBeanDefinitionNames = null;
} if (oldBeanDefinition != null || this.containsSingleton(beanName)) {
this.resetBeanDefinition(beanName);
} }

ok,总结下  this.prepareContext  主要做的事情

环境预处理

创建系统上下文

打印banner

预加载,注册 基础bean定义 (注解处理器,启动类,bean名称处理器 等)

设置上下文监听

 

springboot ---> spring ioc 注册流程 源码解析 this.prepareContext 部分的更多相关文章

  1. 【Spring】Spring IOC原理及源码解析之scope=request、session

    一.容器 1. 容器 抛出一个议点:BeanFactory是IOC容器,而ApplicationContex则是Spring容器. 什么是容器?Collection和Container这两个单词都有存 ...

  2. Spring Boot @Enable*注解源码解析及自定义@Enable*

      Spring Boot 一个重要的特点就是自动配置,约定大于配置,几乎所有组件使用其本身约定好的默认配置就可以使用,大大减轻配置的麻烦.其实现自动配置一个方式就是使用@Enable*注解,见其名知 ...

  3. Spring Boot系列(三):Spring Boot整合Mybatis源码解析

    一.Mybatis回顾 1.MyBatis介绍 Mybatis是一个半ORM框架,它使用简单的 XML 或注解用于配置和原始映射,将接口和Java的POJOs(普通的Java 对象)映射成数据库中的记 ...

  4. 【SSH进阶之路】Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)

    我们前面的三篇博文,简单易懂的介绍了为什么要使用IOC[实例讲解](二).和Spring的IOC原理[通俗解释](三)以及依赖注入的两种常用实现类型(四),这些都是刚开始学习Spring IoC容器时 ...

  5. 手把手教你调试SpringBoot启动 IoC容器初始化源码,spring如何解决循环依赖

    授人以鱼不如授人以渔,首先声明这篇文章并没有过多的总结和结论,主要内容是教大家如何一步一步自己手动debug调试源码,然后总结spring如何解决的循环依赖,最后,操作很简单,有手就行. 本次调试 是 ...

  6. Spring中AOP相关源码解析

    前言 在Spring中AOP是我们使用的非常频繁的一个特性.通过AOP我们可以补足一些面向对象编程中不足或难以实现的部分. AOP 前置理论 首先在学习源码之前我们需要了解关于AOP的相关概念如切点切 ...

  7. Android 玩转IOC,Retfotit源码解析,教你徒手实现自定义的Retrofit框架

    CSDN:码小白 原文地址: http://blog.csdn.net/sk719887916/article/details/51957819 前言 Retrofit用法和介绍的文章实在是多的数不清 ...

  8. Laravel开发:Laravel核心——Ioc服务容器源码解析(服务器解析)

    make解析 服务容器对对象的自动解析是服务容器的核心功能,make 函数.build 函数是实例化对象重要的核心,先大致看一下代码: public function make($abstract) ...

  9. Laravel开发:Laravel核心——Ioc服务容器源码解析(服务器绑定)

    服务容器的绑定 bind 绑定 bind 绑定是服务容器最常用的绑定方式,在 上一篇文章中我们讨论过,bind 的绑定有三种: 绑定自身 绑定闭包 绑定接口 今天,我们这篇文章主要从源码上讲解 Ioc ...

随机推荐

  1. 【1】Zookeeper概述

    一.前言 在"网络是不可靠的"这一前提下,分布式系统开发需要解决如下四个问题: 客户端如何访问众多服务?  解决方案:服务聚合,使用API网关 服务于服务之间如何通信?  解决方案 ...

  2. 【死磕 Java 集合】— ConcurrentSkipListMap源码分析

    转自:http://cmsblogs.com/?p=4773 [隐藏目录] 前情提要 简介 存储结构 源码分析 主要内部类 构造方法 添加元素 添加元素举例 删除元素 删除元素举例 查找元素 查找元素 ...

  3. odoo标识符

    class Book(models.Model): _name = "library.book" _description = "Book" _order = ...

  4. resultMap自定义映射---8.3.1. 解决列名(表中的字段名称)和实体类中的属性名不一致

    1.1.1.1.      步骤一:将驼峰匹配注释掉 --------------测试完成后仍然 回来开启  其他地方可能用到 一旦注释掉驼峰匹配,那么再通过queryUserById查询的结果中,用 ...

  5. netty-2.客户端与服务端互发消息

    (原) 第二篇,客户端与服务端互发消息 与第一篇的例子类似,这里服务端需要三个类,客户端也需要三个类. 服务端关键代码如下:MyServer与上一个例子中的TestServer 差多,这里只列举不同的 ...

  6. 阿里云端安装mysql

    首先查看系统版本,是64位的centos7 file /sbin/init 安装指南如下 https://www.cnblogs.com/thinkingandworkinghard/p/671125 ...

  7. JS 对浏览器相关的操作

    // 获取浏览器 宽高 var width = window.innerWidth || document.documentElement.clientWidth || document.body.c ...

  8. u-boot-2018.09 DTS上 I2C节点的解析 (转)

    这篇理下uboot上I2C总线挂载设备的整个流程. 其他总线(如SPI等)应是类同的思路. uboot 中,以max8997挂载到s3c24xx i2c总线为例, dts里面的写法如下 aliases ...

  9. Jenkins配置邮件信息

    1.进入Manage Jenkins----系统配置 2.设置Jenkins地址和管理员邮箱(不设置管理员邮箱无法发送邮件) 3.配置系统管理员的邮件属性 4.点击[高级]配置系统管理员的邮件属性 5 ...

  10. 数据管理必看!Kendo UI for jQuery过滤器状态保持

    Kendo UI for jQuery最新试用版下载 Kendo UI目前最新提供Kendo UI for jQuery.Kendo UI for Angular.Kendo UI Support f ...