阅读之前要注意的东西:本文就是主打流水账式的源码阅读,主导的是一个参考,主要内容需要看官自己去源码中验证。全系列文章基于 spring 源码 5.x 版本。

写在开始前的话:

阅读spring 源码实在是一件庞大的工作,不说全部内容,单就最基本核心部分包含的东西就需要很长时间去消化了:

  • beans
  • core
  • context

实际上我在博客里贴出来的还只是一部分内容,更多的内容,我放在了个人,fork自 spring 官方源码仓了; 而且对源码的学习,必须是要跟着实际代码层层递进的,不然只是干巴巴的文字味同嚼蜡。

https://gitee.com/bokerr/spring-framework-5.0.x-study

这个仓设置的公共仓,可以直接拉取。

Spring源码阅读系列--全局目录.md

initializeBean 方法源码如下

    /**
* Initialize the given bean instance, applying factory callbacks
* as well as init methods and bean post processors.
* <p>Called from {@link #createBean} for traditionally defined beans,
* and from {@link #initializeBean} for existing bean instances.
*
* @param beanName the bean name in the factory (for debugging purposes)
* @param bean the new bean instance we may need to initialize
* @param mbd the bean definition that the bean was created with
* (can also be {@code null}, if given an existing bean instance)
* @return the initialized bean instance (potentially wrapped)
* @see BeanNameAware
* @see BeanClassLoaderAware
* @see BeanFactoryAware
* @see #applyBeanPostProcessorsBeforeInitialization
* @see #invokeInitMethods
* @see #applyBeanPostProcessorsAfterInitialization
*/
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
} else {
// 特殊 bean 处理 Aware BeanClassLoaderAware BeanFactoryAware
invokeAwareMethods(beanName, bean);
} Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// init-method 执行前 后处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
} try {
// 处理用户自定义初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// init-method 执行后 后处理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
} return wrappedBean;
}

这里的操作其实相当简单

"后置处理器" 是老朋友了

二、重要操作

2.1 应用 Aware

实际上它是个接口,我们可以把它叫做自动装配。

若我们想要实现某个自动装配操作,那么就可以实现 Aware 接口并定义自定义的装配行为。

详情可以参考下边的博客:

《系列二》-- 11、Aware是什么

2.2 applyBeanPostProcessorsBeforeInitialization:

执行-bean初始化前-后置处理器: 简单的说,就是要在初始化方法(init-method) 执行前,才能进行的一些操作。

[遗憾的是,目前spring.beans 包下,除了测试包之外,spring框架中,并没有这方面的实际应用。

也就是说你可以忽略它,这个后置处理器,目前还不会对 bean 做出任何的改动。]

    @Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {// 初始化 init-method 前
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

2.3 invokeInitMethods:

如果元数据中定义了init-method:结合包装器 bw,以及 BeanDefinition 中记录的元数据;

应用反射的原理,执行该 init-method.

    /**
* Give a bean a chance to react now all its properties are set,
* and a chance to know about its owning bean factory (this object).
* This means checking whether the bean implements InitializingBean or defines
* a custom init method, and invoking the necessary callback(s) if it does.
*
* @param beanName the bean name in the factory (for debugging purposes)
* @param bean the new bean instance we may need to initialize
* @param mbd the merged bean definition that the bean was created with
* (can also be {@code null}, if given an existing bean instance)
* @throws Throwable if thrown by init methods or by the invocation process
* @see #invokeCustomInitMethod
*/
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
// 首先判断是否实现了 InitializingBean 接口,如果实现了,直接调用接口方法: afterPropertiesSet 即可完成初始化操作
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
} catch (PrivilegedActionException pae) {
throw pae.getException();
}
} else {
// 直接回调完成操作,适用于较高版本的 spring
((InitializingBean) bean).afterPropertiesSet();
}
} // 低版本中,通过在xml中配置 init-method 方式实现初始化方法
// 此种情形下,需要通过 反射调用bean上定义的 init-method 方法.(发射存在性能损耗,不如上述的直接回调。)
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName)
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
// 利用反射执行 init-method
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}

2.4 applyBeanPostProcessorsAfterInitialization

执行-bean初始化后-后置处理器: 简单的说,就是要在初始化方法(init-method) 执行后,才能进行的一些操作。

[遗憾的是,目前spring.beans 包下,除了测试包之外,spring框架中,并没有这方面的实际应用。

也就是说你可以忽略它,这个后置处理器,目前还不会对 bean 做出任何的改动。]

    @Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// afterInitialization: 初始化之后 - 后置处理
Object current = processor.postProcessAfterInitialization(result, beanName); // 初始化 init-method 之后
if (current == null) {
return result;
}
result = current;
}
return result;
}

《系列二》-- 10、initialize-初始化bean的更多相关文章

  1. Spring框架系列(二)--装配和注入Bean

    企业日常开发中,几乎都是Spring系的框架,无论是SSM.还是现在大火的SpringBoot+JPA/MyBatis,使用最大的目的就是简化开发 基本模块: 核心容器:Beans.Core.Cont ...

  2. Spring学习系列(二) 自动化装配Bean

    一.Spring装配-自动化装配 @Component和@ComponentScan 通过spring注解(@Component)来表明该类会作为组件类,并告知Spring要为这类创建bean,不过组 ...

  3. Android高效率编码-第三方SDK详解系列(二)——Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能

    Android高效率编码-第三方SDK详解系列(二)--Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能 我的本意是第二篇写Mob的shareSD ...

  4. 学习ASP.NET Core Blazor编程系列二十八——JWT登录(3)

    学习ASP.NET Core Blazor编程系列文章之目录 学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应 ...

  5. [知识库分享系列] 二、.NET(ASP.NET)

    最近时间又有了新的想法,当我用新的眼光在整理一些很老的知识库时,发现很多东西都已经过时,或者是很基础很零碎的知识点.如果分享出去大家不看倒好,更担心的是会误人子弟,但为了保证此系列的完整,还是选择分享 ...

  6. tensorflow笔记(五)之MNIST手写识别系列二

    tensorflow笔记(五)之MNIST手写识别系列二 版权声明:本文为博主原创文章,转载请指明转载地址 http://www.cnblogs.com/fydeblog/p/7455233.html ...

  7. Spring IOC(二)容器初始化

    本系列目录: Spring IOC(一)概览 Spring IOC(二)容器初始化 Spring IOC(三)依赖注入 Spring IOC(四)总结 目录 一.ApplicationContext接 ...

  8. 【转载】PyTorch系列 (二):pytorch数据读取

    原文:https://likewind.top/2019/02/01/Pytorch-dataprocess/ Pytorch系列: PyTorch系列(一) - PyTorch使用总览 PyTorc ...

  9. windows下mongodb基础玩法系列二CURD附加一

    windows下mongodb基础玩法系列 windows下mongodb基础玩法系列一介绍与安装 windows下mongodb基础玩法系列二CURD操作(创建.更新.读取和删除) windows下 ...

  10. C语言高速入门系列(二)

    C语言高速入门系列(二) -----转载请注明出处coder-pig 本节引言: 在前面一节中我们对C语言进行了初步的了解,学会了使用IDE进行代码的编写,编译执行! 在这一节中我们会对C语言的基本的 ...

随机推荐

  1. [转帖][MySQL 8.2.0] 从参数变化解读 MySQL 8.2.0 发版说明

    https://www.mryunwei.com/482476.html 日前,MySQL 8.2.0 创新版本已正式上线,并提供安装包下载,但 docker 镜像尚未更新. 在 MySQL 8.1. ...

  2. [转帖]Dapper,大规模分布式系统的跟踪系统

    http://bigbully.github.io/Dapper-translation/ 作者:Benjamin H. Sigelman, Luiz Andr´e Barroso, Mike Bur ...

  3. [转帖]50年来Intel CPU变化有多大?频率从0.75MHz提升到5.2GHz

    https://m.baidu.com/bh/m/detail/ar_9297450181050583423?data_from=lemon 今天(11月15日)是Intel推出4004处理器50周年 ...

  4. CentOS创建vsftp进行读写操作的简单方法

    1. 安装vsftpd yum install epel-release yum install vsftpd 2. 进入系统设置简单进行处理 注意 user_list 是不允许访问的列表. [roo ...

  5. 初识C语言:掌握未来的编程利器

    ​ 欢迎大家来到贝蒂大讲堂 ​ 养成好习惯,先赞后看哦~ ​ 所属专栏:C语言学习 ​ 贝蒂的主页:Betty's blog 1. C语言是什么 在我们生活中,我们和父母.朋友.老师交流时候使用的就是 ...

  6. clickhouse 优化实践,万级别QPS数据毫秒写入和亿级别数据秒级返回 | 京东云技术团队

    1.背景 魔笛活动平台目前在采集每个活动的用户行为数据并进行查询,解决线上问题定位慢,响应不及时的问题,提升客诉的解决效率.目前每天采集的数据量5000万+,一个月的数据总量15亿+,总数据量40亿+ ...

  7. 【K哥爬虫普法】不要沾边!涉案 7k 合判 6 年!

    我国目前并未出台专门针对网络爬虫技术的法律规范,但在司法实践中,相关判决已屡见不鲜,K 哥特设了"K哥爬虫普法"专栏,本栏目通过对真实案例的分析,旨在提高广大爬虫工程师的法律意识, ...

  8. 【JS 逆向百例】猿人学系列 web 比赛第五题:js 混淆 - 乱码增强,详细剖析

    逆向目标 猿人学 - 反混淆刷题平台 Web 第五题:js 混淆,乱码增强 目标:抓取全部 5 页直播间热度,计算前 5 名直播间热度的加和 主页:https://match.yuanrenxue.c ...

  9. Python 潮流周刊#22:Python 3.12.0 发布了!!

    你好,我是猫哥.这里每周分享优质的 Python.AI 及通用技术内容,大部分为英文.标题取自其中一则分享,不代表全部内容都是该主题,特此声明. 本周刊由 Python猫 出品,精心筛选国内外的 25 ...

  10. 小白学k8s(10)-k8s中ConfigMap理解

    理解ConfigMap 什么是ConfigMap ConfigMap的创建 使用key-value 字符串创建 从env文件创建 从目录创建 通过Yaml/Json创建 ConfigMap使用 用作环 ...