《系列二》-- 10、initialize-初始化bean
阅读之前要注意的东西:本文就是主打流水账式的源码阅读,主导的是一个参考,主要内容需要看官自己去源码中验证。全系列文章基于 spring 源码 5.x 版本。
写在开始前的话:
阅读spring 源码实在是一件庞大的工作,不说全部内容,单就最基本核心部分包含的东西就需要很长时间去消化了:
- beans
- core
- context
实际上我在博客里贴出来的还只是一部分内容,更多的内容,我放在了个人,fork自 spring 官方源码仓了; 而且对源码的学习,必须是要跟着实际代码层层递进的,不然只是干巴巴的文字味同嚼蜡。
这个仓设置的公共仓,可以直接拉取。
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 接口并定义自定义的装配行为。
详情可以参考下边的博客:
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的更多相关文章
- Spring框架系列(二)--装配和注入Bean
企业日常开发中,几乎都是Spring系的框架,无论是SSM.还是现在大火的SpringBoot+JPA/MyBatis,使用最大的目的就是简化开发 基本模块: 核心容器:Beans.Core.Cont ...
- Spring学习系列(二) 自动化装配Bean
一.Spring装配-自动化装配 @Component和@ComponentScan 通过spring注解(@Component)来表明该类会作为组件类,并告知Spring要为这类创建bean,不过组 ...
- Android高效率编码-第三方SDK详解系列(二)——Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能
Android高效率编码-第三方SDK详解系列(二)--Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能 我的本意是第二篇写Mob的shareSD ...
- 学习ASP.NET Core Blazor编程系列二十八——JWT登录(3)
学习ASP.NET Core Blazor编程系列文章之目录 学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应 ...
- [知识库分享系列] 二、.NET(ASP.NET)
最近时间又有了新的想法,当我用新的眼光在整理一些很老的知识库时,发现很多东西都已经过时,或者是很基础很零碎的知识点.如果分享出去大家不看倒好,更担心的是会误人子弟,但为了保证此系列的完整,还是选择分享 ...
- tensorflow笔记(五)之MNIST手写识别系列二
tensorflow笔记(五)之MNIST手写识别系列二 版权声明:本文为博主原创文章,转载请指明转载地址 http://www.cnblogs.com/fydeblog/p/7455233.html ...
- Spring IOC(二)容器初始化
本系列目录: Spring IOC(一)概览 Spring IOC(二)容器初始化 Spring IOC(三)依赖注入 Spring IOC(四)总结 目录 一.ApplicationContext接 ...
- 【转载】PyTorch系列 (二):pytorch数据读取
原文:https://likewind.top/2019/02/01/Pytorch-dataprocess/ Pytorch系列: PyTorch系列(一) - PyTorch使用总览 PyTorc ...
- windows下mongodb基础玩法系列二CURD附加一
windows下mongodb基础玩法系列 windows下mongodb基础玩法系列一介绍与安装 windows下mongodb基础玩法系列二CURD操作(创建.更新.读取和删除) windows下 ...
- C语言高速入门系列(二)
C语言高速入门系列(二) -----转载请注明出处coder-pig 本节引言: 在前面一节中我们对C语言进行了初步的了解,学会了使用IDE进行代码的编写,编译执行! 在这一节中我们会对C语言的基本的 ...
随机推荐
- 使用Java分析器优化代码性能,解决OOM问题
有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 背景 最近我一直在做性能优化,对一个单机应用做性能优化.主要是 ...
- [转帖]云数据库是杀猪盘么,去掉中间商赚差价,aws数据库性能提升 10 倍!价格便宜十倍。
https://tidb.net/blog/021059f1 于是乎dba中的冯大嘴喊出了云数据库就是杀猪盘.让每个公司自建数据库. 那么有没有一种数据库又便宜又好用呢.有 哪就是tidb数据库. 之 ...
- [转帖]TiFlash DeltaTree 存储引擎设计及实现分析 - Part 1
https://tidb.net/book/book-rush/features/tiflash-code/tiflash-deltatree TiFlash 是 TiDB 的分析引擎,是 TiDB ...
- [转帖]带你重走 TiDB TPS 提升 1000 倍的性能优化之旅
https://tidb.net/blog/29074d86#TiDB%20%E6%80%A7%E8%83%BD%E5%92%8C%E7%A8%B3%E5%AE%9A%E6%80%A7%E7%9A%8 ...
- 【转帖】读懂什么是RDMA
一.什么是RDMA1.RDMA主要体现 2.如何理解RDMA和TCP技术的区别?3.使用RDMA的好处包括: 二.什么是RoCE?1. RDMA协议包含:Infiniband(IB)2. 为什 ...
- [转帖]GC Ergonomics间接引发的锁等待超时问题排查分析
https://www.cnblogs.com/micrari/p/8831834.html 1. 问题背景 上周线上某模块出现锁等待超时,如下图所示:我虽然不是该模块负责人,但出于好奇,也一起帮忙排 ...
- zabbix 6.0 官方文档
Choose your platform ZABBIX VERSION 6.0 LTS 5.4 5.0 LTS 4.0 LTS OS DISTRIBUTION Red Hat Enterprise ...
- SQL注入payload学习整理
SQLserver 用的payload 0101%'and 1=(select @@version) and '%'=' GS的一个客户端参数 <add PropertyName="F ...
- echarts在左下角添加单位
配置单位 option = { xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], ...
- 爬虫逆向基础,认识 SM1-SM9、ZUC 国密算法
关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! [01x00] 简介 国密即国家密码局认定的国产加密算法,爬虫工程师在做 JS 逆向的时候,会遇 ...