初探Spring源码之Spring Bean的生命周期
写在前面的话:
学无止境,写博客纯粹是一种乐趣而已,把自己理解的东西分享出去,不意味全是对的,欢迎指正!
Spring 容器初始化过程做了什么?
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
实例了一个 AnnotationConfigApplicationContext对象,Spring中出来注解Bean定义的类有两个:
AnnotationConfigApplicationContext和AnnotationConfigWebApplicationContex AnnotationConfigWebApplicationContext是AnnotationConfigApplicationContext的web版本,两者的用法以及对注解的处理方式几乎没有什么差别,通过分析这个类我们知道注册一个bean到spring容器有两种办法一、直接将注解Bean注册到容器中:(参考)public void register(Class<?>... annotatedClasses)但是直接把一个注解的bean注册到容器当中也分为两种方法:
1、在初始化容器时注册并且解析
2、也可以在容器创建之后手动调用注册方法向容器注册,然后通过手动刷新容器,使得容器对注册的注解Bean进行处理。
思考:为什么@profile要使用这类的第2种方法?
因为需要通过applicationContext.getEnvironment()这样的方式设置环境或者获取环境变量
二、通过扫描指定的包及其子包下的所有类扫描其实同上,也是两种方法,初始化的时候扫描,和初始化之后再扫描
public AnnotationConfigApplicationContext() {//
/**
* 父类的构造方法
* 创建一个读取注解的Bean定义读取器
* 什么是bean定义?BeanDefinition
*/
this.reader = new AnnotatedBeanDefinitionReader(this); //
//可以用来扫描包或者类,继而转换成bd
//但是实际上我们扫描包工作不是scanner这个对象来完成的
//是spring自己new的一个ClassPathBeanDefinitionScanner
//这里的scanner仅仅是为了程序员能够在外部调用AnnotationConfigApplicationContext对象的scan方法
this.scanner = new ClassPathBeanDefinitionScanner(this); //
}
注意: * 初始化一个bean的读取和扫描器 * 何谓读取器和扫描器参考上面的属性注释
* 默认构造函数,如果直接调用这个默认构造方法,需要在稍后通过调用其register()
* 去注册配置类(javaconfig),并调用refresh()方法刷新容器,
* 触发容器对注解Bean的载入、解析和注册过程
实例化AnnotationConfigApplicationContext会先实例化父类GenericApplicationContext,然后初始化一个Bean工厂,DefaultListableBeanFactory
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}1处,实例化一个BeanDefinition读取器 AnnotatedBeanDefinitionReader
/**
* 这里的BeanDefinitionRegistry registry是通过在AnnotationConfigApplicationContext
* 的构造方法中传进来的this
* 由此说明AnnotationConfigApplicationContext是一个BeanDefinitionRegistry类型的类
* 何以证明我们可以看到AnnotationConfigApplicationContext的类关系:
* GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry
* 看到他实现了BeanDefinitionRegistry证明上面的说法,那么BeanDefinitionRegistry的作用是什么呢?
* BeanDefinitionRegistry 顾名思义就是BeanDefinition的注册器
* 那么何为BeanDefinition呢?参考BeanDefinition的源码的注释
* @param registry
*/
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
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;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, null);
以上空壳方法,调用以下方法
1 public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
2 BeanDefinitionRegistry registry, @Nullable Object source) {
3 //主要是为了获得工厂对象,实例化AnnotationConfigApplicationContext的时候会调用父类
4 //GenericApplicationContext的构造器去实例化DefaultListableBeanFactory
5 //这里的registry其实际是GenericApplicationContext的子类实例,向上转型取得工厂的属性
6 //从而得到 beanFactory对象
7 DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
获得工厂的具体逻辑
private static DefaultListableBeanFactory unwrapDefaultListableBeanFactory(BeanDefinitionRegistry registry) {
if (registry instanceof DefaultListableBeanFactory) {
return (DefaultListableBeanFactory) registry;
}
else if (registry instanceof GenericApplicationContext) {
//这里在AnnotationConfigApplicationContext初始化的时候this()
//方法中调用了父类GenericApplicationContext的时候new了一个DefaultListableBeanFactory对象
//下面代码返回这个对象
return ((GenericApplicationContext) registry).getDefaultListableBeanFactory();
}
else {
return null;
}
}
这段代码主要是为解析是否含有需要排序的注解
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
//AnnotationAwareOrderComparator主要能解析@Order注解和@Priority
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
//ContextAnnotationAutowireCandidateResolver提供处理延迟加载的功能
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
org.springframework.context.annotation.internalConfigurationAnnotationProcessor这个是BeanDefinition
的一个beanName, 具体的类是ConfigurationClassPostProcessor,它在BeanDefinition中表现的是一个后置处理器(重要),是Spring的核心类之一。
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
//BeanDefinitio的注册,这里很重要,需要理解注册每个bean的类型
//org.springframework.context.annotation.internalConfigurationAnnotationProcessor
//这个是spring生命周期非常重要的一个类
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//需要注意的是ConfigurationClassPostProcessor的类型是BeanDefinitionRegistryPostProcessor
//而 BeanDefinitionRegistryPostProcessor 最终实现BeanFactoryPostProcessor这个接口
//因此需要对这两种类型的进行区分处理
//将一个类变成BeanDefinition
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
//这里是将BD注册到BeanFactory的BeanDefinitionMap容器中,并返回一个
//BeanDefinitionHolder对象
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
实际上上面的代码和以下的代码主要往DefaultListableBeanFactory中的beanDefinitionMap 中放入以下所列举的6个后置处理器。其中ConfigurationClassPostProcessor是核心
0.org.springframework.context.annotation.ConfigurationClassPostProcessor(重要)
1.org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
2.org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
3.org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
4.org.springframework.context.event.EventListenerMethodProcessor
5.org.springframework.context.event.DefaultEventListenerFactory
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//AutowiredAnnotationBeanPostProcessor 实现了 MergedBeanDefinitionPostProcessor
//MergedBeanDefinitionPostProcessor 最终实现了 BeanPostProcessor
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_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));
}
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));
}
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));
}
疑问1:普通的对象是怎么变成BeanDefinition的呢?
//将一个类变成BeanDefinition
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
疑问2:对象变成Beandefinition之后又是怎么注册到bean工厂的呢?
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//将bd注册到工厂的BeanDefinitionMap中
registry.registerBeanDefinition(beanName, definition);
//BeanDefinitionHolder 只是封装参数使用
return new BeanDefinitionHolder(definition, beanName);
}
registry.registerBeanDefinition(beanName, definition);这句代码将Beandefinition注册到BeanFactory中
注意这里的registry注册器一直都是AnnotationConfigApplicationContext对象,该类中没有registerBeanDefinition() ,因此会调用父类GenericApplicationContext的registerBeanDefinition()方法注册Beandefinition。
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
调用org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition()的方法执行以下逻辑
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
不管GenericBeanDefinition,还是RootBeanDefinition都继承了AbstractBeanDefinition,因此会执行以下逻辑
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
//BeanDefinition的所有实现类都继承了AbstractBeanDefinition,因此会执行以下的检验逻辑
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
执行一些逻辑判断,打印一些log,这些不重要
//根据beanName从容器中取出BD,判断是否已经注册了的各种校验
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
//是否允许覆盖原有的bean 默认是不覆盖
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + existingDefinition + "] bound.");
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isWarnEnabled()) {
logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isInfoEnabled()) {
logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
//加入到beanDefinitionMap当中,正常第一次不会走到这里
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
//这里加锁的意义是防止正在创建的Bean被修改。
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;
}
}
}
初次注册BeanDefinition的会执行
else {
// Still in startup registration phase
//初次注册会执行这段逻辑,90%的注册会走到这里
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
至此,实例化一个AnnotationBeanDefinitionReader会注册6个后置处理器,为什么注册这些后置处理器,有什么作用,会在后续的Spring源码解析中进行讲解。另外核心的类ConfigurationClassPostProcessor的作用是什么?
2处,实例化一个BeanDefinition 扫描器ClassPathBeanDefinitionScanner
BeanDefinition扫描器这里不做多介绍,因为这里的扫描器主要是为了给程序员自己定义一个类的扫描器,用来扫描我们自定义的加了注解类。
疑问3:Spring是怎么扫描被注解标识的类呢?
如加了@Component @Controller @Service @Repository 等等,其实用的也是ClasspathBeanDefinitionScanner,只不过Spring内部它自己实例化了一个,并不是用的这里这个而已,后续会进行解析和讲解。
初探Spring源码之Spring Bean的生命周期的更多相关文章
- Spring 源码分析之 bean 依赖注入原理(注入属性)
最近在研究Spring bean 生命周期相关知识点以及源码,所以打算写一篇 Spring bean生命周期相关的文章,但是整理过程中发现涉及的点太多而且又很复杂,很难在一篇文章中把Spri ...
- Spring源码分析之Bean的创建过程详解
前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...
- Spring源码-IOC部分-Bean实例化过程【5】
实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...
- Spring学习-- IOC 容器中 bean 的生命周期
Spring IOC 容器可以管理 bean 的生命周期 , Spring 允许在 bean 声明周期的特定点执行定制的任务. Spring IOC 容器对 bean 的生命周期进行管理的过程: 通过 ...
- 你还不知道Vue的生命周期吗?带你从Vue源码了解Vue2.x的生命周期(初始化阶段)
作者:小土豆biubiubiu 博客园:https://www.cnblogs.com/HouJiao/ 掘金:https://juejin.im/user/58c61b4361ff4b005d9e8 ...
- 【Spring源码分析】Bean加载流程概览
代码入口 之前写文章都会啰啰嗦嗦一大堆再开始,进入[Spring源码分析]这个板块就直接切入正题了. 很多朋友可能想看Spring源码,但是不知道应当如何入手去看,这个可以理解:Java开发者通常从事 ...
- 【Spring源码解读】bean标签中的属性
说明 今天在阅读Spring源码的时候,发现在加载xml中的bean时,解析了很多标签,其中有常用的如:scope.autowire.lazy-init.init-method.destroy-met ...
- Spring 源码分析之 bean 实例化原理
本次主要想写spring bean的实例化相关的内容.创建spring bean 实例是spring bean 生命周期的第一阶段.bean 的生命周期主要有如下几个步骤: 创建bean的实例 给实例 ...
- 【Spring源码分析】Bean加载流程概览(转)
转载自:https://www.cnblogs.com/xrq730/p/6285358.html 代码入口 之前写文章都会啰啰嗦嗦一大堆再开始,进入[Spring源码分析]这个板块就直接切入正题了. ...
随机推荐
- jQuery引入公共库问题
话说脚本最好放到底部,这样页面既可以逐步呈现,也可以提高下载,但是某些公共模块且有js效果,顺序优先公共库的话,效果是出不来的,所以以后就把公共库最好放在头部,(就是这个而已:http://apps. ...
- CiSCO 交换机配置 SSH 登陆
CiSCO 交换机配置 SSH 登陆 题目:在三层交换机上仅运行 SSH 服务,且用户名和密码的方式登录交换机. (一)了解主机名与域名 1."主机名" 为该设备的名称 2 ...
- Arch下error: signature from "NAME<EMAIL ADD>"
pacman的unknown trust问题错误消息类似于:error: signature from "NAME<EMAIL ADD>" is unknown tru ...
- Archlinux 下系统如何设置让 Wine 调用 ibus输入法
前言: 如果你是fcitx输入法用户,那么这篇文章大可不必看.fcitx是一个非常强大的框架,著名搜狗输入法就是基于fcitx输入法架构开发的.据我所知.您遇到这个问题可以通过卸载ibus输入法进行修 ...
- java学习基础部分
JVM虚拟机的位置: 垃圾回收在java程序运行过程中自动进行,程序员无法精准控制和干预. Java程序还会出现内存泄漏和内存溢出. Jre = jvm+java se标准类库 Jdk = jre + ...
- spider_keeper
一 简介 spider_keeper 是一款开源的spider管理工具,可以方便的进行爬虫的启动,暂停,定时,同时可以查看分布式情况下所有爬虫日志,查看爬虫执行情况等功能. 二 安装 部署 安装环境 ...
- python学习,day3:函数式编程,带return
return的主要作用就是,在调用的时候,能知道函数的运行情况,相当于打个标签 # coding=utf-8 # Author: RyAn Bi def test1(): print('in the ...
- java设计模式学习笔记
简介 设计模式可以分为五类 接口型 模式:适配器模式,外观模式,合成模式,桥接模式 职责型 模式:单例模式,观察者模式,调停者模式,代理模式,职责链模式,享元模式 构造型 模式:构建者模式,工厂方法模 ...
- 导出excel设置样式(Aspose.Cells)
Aspose.Cells.Style style = xlBook.Styles[xlBook.Styles.Add()];style1.Pattern = Aspose.Cells.Backgrou ...
- Java 的多态
1 多态的概念 多态(?) 可以理解为多种状态/多种形态 同一事物,由于条件不同,产生的结果不同 程序中的多态 同一引用类型,使用不同的实例而执行结果不同的. 同:同一个类型,一般指父类. ...