5、Spring之Bean生命周期~创建Bean(1)

5、Spring之Bean生命周期~创建Bean

  • 创建Bean
    • resolveBeanClass()方法
      • doResolveBeanClass()方法
    • resolveBeforeInstantiation()方法

创建Bean

  Spring Bean的生命周期首先会经过扫描,然后回经过合并,合并之后就会通过getBean()方法去获取bean,getBean()方法大致逻辑,先根据判断是单例bean还是原型bean,原型bean直接创建,单例bean会判断单例池中有没有,没有的话调用createBean()方法。而createBean方法也没有真正的执行实例化操作,而是执行啦实例化前操作,废话不多说,直接上代码:

//---------------------------------------------------------------------
// Implementation of relevant AbstractBeanFactory template methods
//---------------------------------------------------------------------/*** Central method of this class: creates a bean instance,* populates the bean instance, applies post-processors, etc.** @see #doCreateBean*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {if (logger.isTraceEnabled()) {logger.trace("Creating instance of bean '" + beanName + "'");}RootBeanDefinition mbdToUse = mbd;// Make sure bean class is actually resolved at this point, and// clone the bean definition in case of a dynamically resolved Class// which cannot be stored in the shared merged bean definition.// 马上就要实例化Bean了,确保beanClass被加载了Class<?> resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}// Prepare method overrides.try {mbdToUse.prepareMethodOverrides();} catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);}try {// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.// 实例化前Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}} catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}try {Object beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isTraceEnabled()) {logger.trace("Finished creating instance of bean '" + beanName + "'");}return beanInstance;} catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {// A previously detected exception with proper bean creation context already,// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.throw ex;} catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);}
}

通过上述代码,我们就可以看到createBean()方法并不是直接去创建Bean对象,而是要经过一系列的准备工作,我们开始逐行分析:

  1. 首先会调用resolveBeanClass()方法,确保Bean对象的class已经被加载;
  2. prepareMethodOverrides()方法的作用是判断MethodOverrides属性是否存在,存在的话进行方法覆盖,由于配置文件方式使用较少,此方法不展示细说,感兴趣的小伙伴可以自行查阅相关资料;
  3. 再往下就到啦比较重要的实例化前,调用resolveBeforeInstantiation()方法,执行初始化前操作;
  4. 如果实例化前这一步有返回值,会直接返回,不走后续的实例化、依赖注入、初始化前,直接跳到初始化这一步,执行AOP操作;
  5. 调用doCreateBean()方法执行;由于doCreateBean()方法逻辑比较多,请移步至《Spring之Bean生命周期~创建Bean(2)》

resolveBeanClass()方法

resolveBeanClass()方法详解

/*** Resolve the bean class for the specified bean definition,* resolving a bean class name into a Class reference (if necessary)* and storing the resolved Class in the bean definition for further use.** @param mbd          the merged bean definition to determine the class for* @param beanName     the name of the bean (for error handling purposes)* @param typesToMatch the types to match in case of internal type matching purposes*                     (also signals that the returned {@code Class} will never be exposed to application code)* @return the resolved bean class (or {@code null} if none)* @throws CannotLoadBeanClassException if we failed to load the class*/
@Nullable
protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)throws CannotLoadBeanClassException {try {// 如果beanClass被加载了if (mbd.hasBeanClass()) {return mbd.getBeanClass();}// 如果beanClass没有被加载if (System.getSecurityManager() != null) {return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)() -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());} else {return doResolveBeanClass(mbd, typesToMatch);}} catch (PrivilegedActionException pae) {ClassNotFoundException ex = (ClassNotFoundException) pae.getException();throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);} catch (ClassNotFoundException ex) {throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);} catch (LinkageError err) {throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);}
}

通过上述代码我们可以看到:

  1. 如果beanClass被加载过,直接返回;
  2. 如果还没有被加载,调用doResolveBeanClass()方法加载beanClass,并且拿到类加载器;
  3. 返回createBean()方法;

doResolveBeanClass()方法

doResolveBeanClass()方法详解

@Nullable
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)throws ClassNotFoundException {ClassLoader beanClassLoader = getBeanClassLoader();ClassLoader dynamicLoader = beanClassLoader;boolean freshResolve = false;if (!ObjectUtils.isEmpty(typesToMatch)) {// When just doing type checks (i.e. not creating an actual instance yet),// use the specified temporary class loader (e.g. in a weaving scenario).ClassLoader tempClassLoader = getTempClassLoader();if (tempClassLoader != null) {dynamicLoader = tempClassLoader;freshResolve = true;if (tempClassLoader instanceof DecoratingClassLoader) {DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;for (Class<?> typeToMatch : typesToMatch) {dcl.excludeClass(typeToMatch.getName());}}}}String className = mbd.getBeanClassName();if (className != null) {// 解析Spring表达式,有可能直接返回了一个Class对象Object evaluated = evaluateBeanDefinitionString(className, mbd);if (!className.equals(evaluated)) {// A dynamically resolved expression, supported as of 4.2...if (evaluated instanceof Class) {return (Class<?>) evaluated;} else if (evaluated instanceof String) {className = (String) evaluated;freshResolve = true;} else {throw new IllegalStateException("Invalid class name expression result: " + evaluated);}}if (freshResolve) {// When resolving against a temporary class loader, exit early in order// to avoid storing the resolved Class in the bean definition.if (dynamicLoader != null) {try {return dynamicLoader.loadClass(className);} catch (ClassNotFoundException ex) {if (logger.isTraceEnabled()) {logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);}}}return ClassUtils.forName(className, dynamicLoader);}}// Resolve regularly, caching the result in the BeanDefinition...return mbd.resolveBeanClass(beanClassLoader);
}

通过上诉代码,我们可以看到:

  1. 优先返回当前线程中的ClassLoader;
  2. 线程中类加载器为null的情况下,返回ClassUtils类的类加载器;
  3. 如果ClassUtils类的类加载器为空,那么则表示是Bootstrap类加载器加载的ClassUtils类,那么则返回系统类加载器;
  4. 返回resolveBeanClass()方法;

resolveBeforeInstantiation()方法

resolveBeforeInstantiation()方法详解

/*** Apply before-instantiation post-processors, resolving whether there is a* before-instantiation shortcut for the specified bean.** @param beanName the name of the bean* @param mbd      the bean definition for the bean* @return the shortcut-determined bean instance, or {@code null} if none*/
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {Object bean = null;if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {// Make sure bean class is actually resolved at this point.// synthetic表示合成,如果某些Bean式合成的,那么则不会经过BeanPostProcessor的处理if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {Class<?> targetType = determineTargetType(beanName, mbd);if (targetType != null) {bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);if (bean != null) {bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);}}}mbd.beforeInstantiationResolved = (bean != null);}return bean;
}

  通过上述方法,我们可以看到,首先会判断Bean对象是否实现了InstantiationAwareBeanPostProcessor接口,如果实现了InstantiationAwareBeanPostProcessor接口,会调用它的postProcessBeforeInstantiation方法,返回postProcessBeforeInstantiation方法的执行结果;
  返回createBean()方法;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/25483.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

特种设备起重机指挥题库附答案

1、【多选题】力的三要素是指:( )。(ACD) A、力的大小 B、力的单位 C、力的方向 D、力的作用点 2、【多选题】司索作业规范正确的要求是( )(ABC) A、吊点正确 B、吊索挂设合理 C、绑扎牢靠 D、吊索长短一致 3、【多选题】圆柱形物体兜吊时&#xff0c;一定要放空圈&#…

【python】python GUI编程--tkinter模块初探

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

归并排序(Merge_sort)

归并排序&#xff1a; 归并的意思是将两个数组合成为一个&#xff0c;而归并排序就是&#xff1a;将一个数组分为许多个&#xff0c;让多个数组按大小归并&#xff0c;直到归并为一个&#xff1b; 基本思想为&#xff1a; 将一个数组拆分为许多个两两结合的数组&#xff0c;…

树的4种遍历

目录 树的四种遍历方式的总结 1. 前序遍历&#xff08;Pre-order Traversal&#xff09; 2. 中序遍历&#xff08;In-order Traversal&#xff09; 3. 后序遍历&#xff08;Post-order Traversal&#xff09; 4. 层序遍历&#xff08;Level-order Traversal 或 广度优先遍…

引入别人的安卓项目报错

buildscript { repositories { google() jcenter() } dependencies { classpath com.android.tools.build:gradle:4.1.0 // 使用最新版本的插件 } } allprojects { repositories { google() jcenter() } } 在…

Feign是如何发送http请求的底层源码

Feign 的底层源码涉及多个组件和库来实际发送 HTTP 请求。Feign 的主要目标是提供一个声明式的 Web Service 客户端接口&#xff0c;而底层实现则依赖于其他库&#xff08;如 OkHttp、Apache HttpClient 等&#xff09;来发送实际的 HTTP 请求。 1、接口代理 当你通过 Feign …

Keil软件仿真的使用

一、软件的初始化设置 初始设置可以按照下图&#xff0c;这里我使用的是STM32F103C8T6&#xff0c;所以单片机型号为STM32F103C8&#xff0c;这个设置在Debug目录下。然后进行时钟的设置&#xff0c;我们板上晶振为8M&#xff0c;这里将时钟改为8. 或许有人想问如果是别的型号单…

Effective Java 1 用静态工厂方法代替构造器

知识点上本书需要会Java语法和lang、util、io库&#xff0c;涉及concurrent和function包。 内容上主要和设计模式相关&#xff0c;代码风格力求清晰简洁&#xff0c;代码尽量复用&#xff0c;组件尽量少依赖&#xff0c;错误尽早发现。 第1个经验法则&#xff1a;用静态工厂方…

Chroium 源码目录结构分析(1):源码目录体积一栏

获取源码 首先&#xff0c;我们拉一份最新的源代码&#xff08;笔者是2024.6.6日拉取的&#xff09;&#xff1a; fetch --nohistory chromium 源码预处理 如果运行build&#xff0c;会生成许多生成的代码&#xff0c;因此我们不运行build。 然后&#xff0c;把干扰后续分析…

sqlilabs靶场安装

05-sqllabs靶场安装 1 安装 1 把靶场sqli-labs-master.zip上传到 /opt/lampp/htdocs 目录下 2 解压缩 unzip sqli-labs-master.zip3 数据库配置 找到配置文件,修改数据库配置信息 用户名密码&#xff0c;修改为你lampp下mysql的用户名密码&#xff0c;root/123456host:la…

语法的时态1——一般现在时(1)

定义&#xff1a;一般现在时用来表示经常发生的动作&#xff0c;以及客观事实。 一般现在时的构成以及标志词 1.一般现在时的结构 &#xff08;1&#xff09;主系表结构 构成&#xff1a;主语be(am,is,ear)其他。属于状态句。 I…

贪吃蛇双人模式设计(2)

敲上瘾-CSDN博客控制台程序设置_c语言控制程序窗口大小-CSDN博客贪吃蛇小游戏_贪吃蛇小游戏csdn-CSDN博客​​​​​​​ 一、功能实现&#xff1a; 玩家1使用↓ → ← ↑按键来操作蛇的方向&#xff0c;使用右Shift键加速&#xff0c;右Ctrl键减速玩家2使用W A S D按键来操…

matlab演示地月碰撞

代码 function EarthMoonCollisionSimulation()% 初始化参数earth_radius 6371; % 地球半径&#xff0c;单位&#xff1a;公里moon_radius 1737; % 月球半径&#xff0c;单位&#xff1a;公里distance 384400; % 地月距离&#xff0c;单位&#xff1a;公里collision_tim…

Astar路径规划算法复现-python实现

# -*- coding: utf-8 -*- """ Created on Fri May 24 09:04:23 2024"""import os import sys import math import heapq import matplotlib.pyplot as plt import time 传统A*算法 class Astar:AStar set the cost heuristics as the priorityA…

Kafka集成flume

1.flume作为生产者集成Kafka kafka作为flume的sink&#xff0c;扮演消费者角色 1.1 flume配置文件 vim $kafka/jobs/flume-kafka.conf # agent a1.sources r1 a1.sinks k1 a1.channels c1 c2# Describe/configure the source a1.sources.r1.type TAILDIR #记录最后监控文件…

基于python-CNN深度学习的水瓶是否装满水识别-含数据集+pyqt界面

代码下载地址&#xff1a; https://download.csdn.net/download/qq_34904125/89374853 本代码是基于python pytorch环境安装的。 下载本代码后&#xff0c;有个requirement.txt文本&#xff0c;里面介绍了如何安装环境&#xff0c;环境需要自行配置。 或可直接参考下面博文…

绘唐2.5一键追爆款2.5免费版

免费分享给您 小说推文工具是一种用于在社交媒体上宣传和推广小说的工具。它可以帮助作者将小说的内容和相关信息以推文的形式快速发布在各种社交媒体平台上&#xff0c;吸引读者的注意力并增加小说的曝光度。 以下是一些小说推文工具可能具备的功能&#xff1a; 1. 编辑和排…

【linux】进程控制——进程创建,进程退出,进程等待

个人主页&#xff1a;东洛的克莱斯韦克-CSDN博客 祝福语&#xff1a;愿你拥抱自由的风 相关文章 【Linux】进程地址空间-CSDN博客 【linux】详解linux基本指令-CSDN博客 目录 进程控制概述 创建子进程 fork函数 父子进程执行流 原理刨析 常见用法 出错原因 进程退出 概…

MyBatis-Plus学习总结

一.快速入门 (一)简介 MyBatis-Plus (opens new window)&#xff08;简称 MP&#xff09;是一个 MyBatis (opens new window) 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 (二)快速入门 1.准备数据库脚本 2.准备bo…

六、Docker Swarm、Docker Stack和Portainer的使用

六、Docker swarm和Docker stack的使用 系列文章目录1.Docker swarm1.简介2.docker swarm常用命令3.docker node常用命令4.docker service常用命令5.实战案例6.参考文章 2.Docker stack1.简介3.Docker stack常用命令4.实战案例5.常见问题及调错方式1.查看报错信息并尝试解决&am…