阅读之前要注意的东西:本文就是主打流水账式的源码阅读,主导的是一个参考,主要内容需要看官自己去源码中验证。全系列文章基于 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. [转帖]火狐URL默认打开为HTTPS,切换成http形式

    火狐在当前及未来版本默认URL采用HTTPS进行链接,但个人习惯,某些网站不是https,改http在响应超时状态也会切成https,将默认为http. edge,chrome 依然还是http为主要 ...

  2. [转帖]FIO磁盘性能测试工具

    https://www.cnblogs.com/lyhabc/p/16708771.html 简介 一般我们测试硬盘或者存储的性能的时候,会用Linux系统自带的dd命令,因为是自带命令,简单易使用, ...

  3. [转帖]创建lvm

    https://www.jianshu.com/p/bf6b92d73b9b 一.环境介绍 服务器中有sda,sdb,sdc,sdd,sde,sdf六块硬盘,其中sda作为系统盘已经安装了系统,需要将 ...

  4. [转帖]Redis中的Lua脚本

    最近琢磨分布式锁时接触到的知识点,简单记一下. 文章目录 1. Redis中的Lua 2. 利用Lua操作Redis 3. Lua脚本的原子性 4. 关于 EVALSHA 5. 常用`SCRIPT` ...

  5. [转帖]技术派-汇编语言指令集(intel X86系列)

    针对汇编语言指令集(intel X86系列8086/80186/80286/80386/80486) AAA - Ascii Adjust for Addition        AAD - Asci ...

  6. Harbor 简要安装说明

    Harbor 简要安装说明 下载最新的离线安装文件 链接:https://pan.baidu.com/s/1ZEjgnI3YmhsdVOm7h7SWcQ 提取码:GSNB 复制这段内容后打开百度网盘手 ...

  7. Vue.use和install之间的关系

    创建一个plugins.js文件 跟main.js同级下,创建一个plugins.js文件 export default { // install是vue给我们提供的.它会自动去执行install. ...

  8. 【JS 逆向百例】某易支付密码 MD5+AES 加密分析

    关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后 ...

  9. OpenIM (Open-Source Instant Messaging) Mac Deployment Guide

    This guide provides step-by-step instructions for deploying OpenIM on a Mac, including both source c ...

  10. Leetcode 42题 接雨水(Trapping Rain Water) Java语言求解

    题目链接 https://leetcode-cn.com/problems/trapping-rain-water/ 题目内容 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱 ...