Spring底层原理(三)
Spring底层原理(三)
Bean的生命周期
@SpringBootApplication
public class Application {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);context.close();}
}@Slf4j
@Component
public class LifeCycleBean {public LifeCycleBean(){log.info("构造");}@Autowiredpublic void autowire(@Value("${JAVA_HOME}") String home){log.info("依赖注入:{}",home);}@PostConstructpublic void init(){log.info("初始化");}@PreDestroypublic void destroy(){log.info("销毁");}
}
启动容器后会得到以下结果

Bean的生命周期为:构造方法 -> 依赖注入->初始化 ->销毁
与Bean生命周期相关的后置处理器
PostProcessor中文意思为后置处理器
InstantiationAwareBeanPostProcessor与DestructionAwareBeanPostProcessor都是BeanPostProcessor的子接口
@Slf4j
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {@Overridepublic void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {if (beanName.equals("lifeCycleBean")){log.info("<<<< 销毁前执行,如@PreDestory");}}@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {if (beanName.equals("lifeCycleBean")){log.debug("<<<< 实例化之前执行,这里返回的对象会替换掉原本的bean");}return null;}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {if (beanName.equals("lifeCycleBean")){log.debug("<<<< 实例化后执行,这里返回false会跳过依赖注入阶段");}return true;}@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {if (beanName.equals("lifeCycleBean")){log.debug("<<<< 依赖注入阶段执行,如@Autowired、@Value、@Resource");}return pvs;}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("lifeCycleBean")){log.debug("<<<< 初始化之前执行,这里返回的对象会替换掉原本的bean,如@PostConstruct、@ConfigurationProperties");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("lifeCycleBean")){log.debug("<<<< 初始化之后执行,这里返回的对象会替换掉原本的bean,如代理增强");}return bean;}
}

Bean后置处理器与模板方法模式
public class MethodTemplateTest {public static void main(String[] args) {MyBeanFactory factory = new MyBeanFactory();factory.addProcessor(bean -> System.out.println("解析@Autowired"));factory.addProcessor(bean -> System.out.println("解析@Resources"));factory.getBean();}static class MyBeanFactory {private List<BeanPostProcessor> processors = new ArrayList<>();public void addProcessor(BeanPostProcessor postProcessor) {processors.add(postProcessor);}public Object getBean() {Object bean = new Object();System.out.println("构造:" + bean);System.out.println("依赖注入:" + bean);for (BeanPostProcessor processor : processors) {processor.inject(bean);}System.out.println("初始化:" + bean);return bean;}}interface BeanPostProcessor {void inject(Object bean);//对依赖注入阶段进行拓展}
}
- 将代码中不确定的部分抽象成接口,供后续拓展
常见的bean后置处理器
public class A4Application {public static void main(String[] args) {//GenericApplicationContext是一个干净的容器,没有添加BeanFactory后置处理器和Bean后置处理器GenericApplicationContext context = new GenericApplicationContext();//注册beancontext.registerBean("bean1",Bean1.class);context.registerBean("bean2",Bean2.class);context.registerBean("bean3",Bean3.class);//初始化容器context.refresh();//执行beanFactory后置处理器,添加bean后置处理器,初始化所有单例bean//销毁容器context.close();}
}
添加AutowiredAnnotationBeanPostProcessor
context.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
ContextAnnotationAutowireCandidateResolver:用于支持解析@ValueAutowiredAnnotationBeanPostProcessor:该处理器用于解析@Autowired@Value

添加CommonAnnotationBeanPostProcessor
context.registerBean(CommonAnnotationBeanPostProcessor.class);
CommonAnnotationBeanPostProcessor:用于解析@Resurce@PostConstruct@PreDestroy
ConfigurationPropertiesBindingPostProcessor.register(context);
ConfigurationPropertiesBindingPostProcessor:用于解析@ConfigurationProperties
Autowired后处理器执行分析
AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
processor.setBeanFactory(beanFactory);//需要从容器中查找依赖
Bean1 bean1 = new Bean1();
System.out.println(bean1);//Bean1{bean2=null, bean3=null, home='null'}
//参数1:需要注入的值,null则从容器中获取 参数2:被注入的目标
processor.postProcessProperties(null,bean1,"bean1");

通过反射访问InjectionMetadata中的信息
Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
findAutowiringMetadata.setAccessible(true);
InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadata.invoke(processor, "bean1", Bean1.class, null);//获取bean1上加了@Value @Autowired的成员变量 方法参数信息

如何查找依赖?
//根据field获取field对应的type,然后容factory中查找
Field bean3 = Bean1.class.getDeclaredField("bean3");
DependencyDescriptor dd1 = new DependencyDescriptor(bean3, false);
Object o = beanFactory.doResolveDependency(dd1, null, null, null);
//根据方法参数查找依赖
Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
//创建依赖描述器,按照方法参数查找依赖,需要一个MethodParameter对象,参数2为参数的索引
DependencyDescriptor dd2 = new DependencyDescriptor(new MethodParameter(setBean2, 0), true);
Object o2 = beanFactory.doResolveDependency(dd2, null, null, null);//匹配@Value
Method setHome = Bean1.class.getDeclaredMethod("setHome", String.class);
DependencyDescriptor dd3 = new DependencyDescriptor(new MethodParameter(setHome, 0), true);
Object o3 = beanFactory.doResolveDependency(dd3, null, null, null);
相关文章:
Spring底层原理(三)
Spring底层原理(三) Bean的生命周期 SpringBootApplication public class Application {public static void main(String[] args) {ConfigurableApplicationContext context SpringApplication.run(Application.class, args);context.close();} }Slf4j Component public cla…...
ElementPlus表格中的背景透明
ElementPlus表格中的背景透明 最近写大屏,用到elementplus中的el-table,为了让显示效果好看一点,需要把表格的白色背景调整为透明,与整个背景融为一体。可以参考的资料非常少,大部分都是ElmentUI的方法,在…...
【会议征稿通知】2024第四届神经网络、信息与通信工程国际学术会议(NNICE 2024)
2024第四届神经网络、信息与通信工程国际学术会议(NNICE 2024) 2024 4th International Conference on Neural Networks, Information and Communication Engineering 2024第四神经网络、信息与通信工程国际学术会议(NNICE 2024࿰…...
PyCharm改变代码背景图片的使用教程
一个好的集成环境是学习和使用一门编程语言的重中之重,这次我给大家分享如何改变PyCharm软件的代码背景图片。 说明:本教程使用的是汉化版PyCharm软件。 打开PyCharm软件。 点击软件最上方导航栏的文件,然后找到设置。 打开设置然后点击外观…...
BadNets: Identifying Vulnerabilities in the Machine Learning Model Supply Chain
BadNets: Identifying Vulnerabilities in the Machine Learning Model Supply Chain----《BadNets:识别机器学习模型供应链中的漏洞》 背景: 许多用户将训练过程外包给云计算,或者依赖于经过训练的模型,然后根据特定的任务对模型进行微调。这…...
Kubernetes速成课程:掌握容器编排的精髓
微服务演进方向 • 面向分布式设计(Distribution):容器、微服务、API 驱动的开发; • 面向配置设计(Configuration):⼀个镜像,多个环境配置; • 面向韧性设计(Resistancy):故障容忍和自愈; • 面向弹性设计(Elasticity):弹性扩展和对环境变化(负载)做出响应; •…...
【数据库】分组数据 GROUP BY、HAVING
分组数据 创建分组过滤分组SQL 子句顺序 创建分组 s q l sql sql 中,使用 GROUP BY 子句对数据进行分组。分组通常与聚合函数一起使用,以对每个组内的数据执行聚合操作; e . g . e.g. e.g. 按照客户分组,计算每个客户的订单总金额…...
“唯品会VIP商品API:一键获取奢侈品详情,尊享品质生活!“
要获取唯品会VIP商品的详细信息,您可以通过唯品会的API接口进行调用。 唯品会提供了多种商品选择,包括服装、美容护肤、鞋子、箱包、家居、母婴等等。在这些商品中,VIP奢侈品专区是唯品会的重要特色之一。 要获取VIP商品的详细信息…...
uniapp解决iOS切换语言——原生导航栏buttons文字不生效
uniapp 切换语言原生导航栏buttons文字不生效? 文章目录 uniapp 切换语言原生导航栏buttons文字不生效?效果图page.json配置解决方式 效果图 场景:在 tabbar 页面中,配置 原生导航栏 buttons ,切换语言时,不…...
idea 基础设置
1、设置 IDEA 主题 2、自动导包和优化多余的包 3、同一个包下的类,超过指定个数的时候,导包合并为* 4、显示行号 , 方法和方法间的分隔符: 5、忽略大小写,进行提示 6、多个类不隐藏,多行显示 7、设置默认的…...
Rockchip Uboot CmdLine 作用 来源 常用参数
Rockchip Uboot CmdLine cmdline 是 U-Boot 向 kernel 传递参数的一个重要手段,诸如传递启动存储,设备状态等。cmdline 参数有多个来源,由 U-Boot 进行拼接、过滤重复数据之后再传给 kernel。U-Boot 阶段的 cmdline 被保存在 bootargs 环境变…...
MySQL表导出
# 导出表和数据 mysqldump --skip-extended-insert -hHost -uUser -pPassword -PPost database table > table.sql# 如: mysqldump --skip-extended-insert -h172.1.0.1 -uroot -pabc123 -P3306 data_support city_code > city_code.sql# 导入表和数据 mysql …...
HTML页面获取URL传递的参数值
如: // 查询url上链接的参数与参数值 function getQueryString(name) {var url window.location.search; // 获取URLvar pattern new RegExp("[\?\&]" name "([^\&])", "i"); // 正则匹配URLvar matcher pattern.exec(…...
mac安装jenkins
1、安装jenkins之前确认是否安装了homebrew 2、开始安装jenkins 安装完如下图则安装完成 3、改一下ip和端口 4、启动jenkins brew services restart jenkins 使用自己修改后的ip:port http://0.0.0.0:8088 根据提示信息,拿到管理员密码,并解锁 5、安装…...
asp.net网球馆计费管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio
一、源码特点 asp.net网球馆计费管理系统是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010,数据库为sqlserver2008,使用c#语 言开发 aspnet网球馆计费管理系统1 二、…...
动手学深度学习——第五次学
权重衰减是最广泛使用的正则化的技术之一 今天学的很头疼,好多都是公式 12权重衰退(解决过拟合) 13丢弃法(解决过拟合) 14数值稳定(梯度爆炸和梯度消失问题) 15竞赛题讲解 层和块 多层感知机…...
python实验16_网络爬虫
实验16:网络爬虫 1.实验目标及要求 (1)掌握简单爬虫方法。 2. 实验主要内容 爬取中国票房网 ① 爬取中国票房网(www.cbooo.cn)2019年票房排行榜前20名的电影相关数据 代码部分: import time from selenium.webdriver impor…...
家长扫码查成绩
亲爱的老师,你是否曾为了如何让家长更方便地查询学生的成绩而烦恼?现在,我们为你介绍一款简单易用的成绩查询系统,让家长只需轻轻一扫,即可查看孩子的成绩。 一、什么是成绩查询系统? 成绩查询系统是一款专…...
【转】多台服务器共享session问题
多台服务器共享 session 问题 现在的大型网站中,如何实现多台服务器中的 session 数据共享呢? 当使用多台服务器架设成集群之后,我们通过负载均衡的方式,同一个用户(或者 ip)访问时被分配到不同的服务器上…...
页面置换算法的模拟实现及命中率对比
页面置换算法是用于管理计算机内存中页面(或页面框)的一种策略。常见的页面置换算法包括FIFO(先进先出)、LRU(最近最少使用)、LFU(最少使用)等。以下是一个简单的页面置换算法模拟实…...
TRAE SOLO模式实战:如何用AI上下文工程师5分钟搞定JWT登录接口开发
TRAE SOLO模式实战:5分钟构建JWT登录接口的AI开发革命 清晨的阳光透过百叶窗洒在键盘上,咖啡杯里升起最后一缕热气。作为一名全栈开发者,你刚收到产品经理的紧急需求:"今天下班前上线用户登录功能,支持邮箱密码验…...
万象视界灵坛部署案例:阿里云ECS GPU实例一键拉起Omni-Vision Sanctuary服务
万象视界灵坛部署案例:阿里云ECS GPU实例一键拉起Omni-Vision Sanctuary服务 1. 项目概述 万象视界灵坛(Omni-Vision Sanctuary)是一款基于OpenAI CLIP技术的高级多模态智能感知平台。这个创新性的解决方案将复杂的视觉识别任务转化为直观、…...
雯雯的后宫-造相Z-Image-瑜伽女孩惊艳效果展示:新月式体式+柔光原木场景生成实录
雯雯的后宫-造相Z-Image-瑜伽女孩惊艳效果展示:新月式体式柔光原木场景生成实录 安全声明:本文仅展示AI图像生成技术效果,所有内容均基于技术演示目的,不涉及任何不当内容。 1. 效果惊艳开场:当瑜伽遇见AI艺术 今天要…...
SecGPT-14B模型微调:提升OpenClaw安全任务执行准确率
SecGPT-14B模型微调:提升OpenClaw安全任务执行准确率 1. 为什么需要微调SecGPT-14B 去年我在使用OpenClaw自动化执行安全扫描任务时,经常遇到一个头疼的问题:当Agent尝试分析漏洞报告时,基础模型总是把"SSRF漏洞"和&q…...
Pixel Couplet Gen快速上手:Rust+WASM加速正则解析器性能实测报告
Pixel Couplet Gen快速上手:RustWASM加速正则解析器性能实测报告 1. 项目概览 Pixel Couplet Gen是一款融合传统春节文化与现代像素艺术风格的AI春联生成器。通过ModelScope大模型驱动,这款工具将中国传统的春联创作带入了数字时代,特别采用…...
OpenClaw自动化测试:Kimi-VL-A3B-Thinking多模态交互验证框架
OpenClaw自动化测试:Kimi-VL-A3B-Thinking多模态交互验证框架 1. 为什么需要AI驱动的自动化测试 去年接手一个客户端项目时,我遇到了一个典型痛点——每次发版前的手动回归测试需要3个人天。更麻烦的是,UI微调导致的视觉差异很难通过传统断…...
Python数据分析实战:用Seaborn绘制炫酷相关性热力图(附完整代码)
Python数据分析实战:用Seaborn绘制炫酷相关性热力图 数据分析工作中,相关性分析是理解变量间关系的核心技能。而热力图作为直观展示相关性的工具,已经成为数据科学家和商业分析师的标准配置。本文将带你从零开始,掌握用Seaborn绘…...
为什么28S与18S rRNA比值可用于评估RNA质量?
在分子生物学实验中,获得高质量RNA样本是基因表达分析、转录组测序等研究成功的关键前提。在众多RNA质量评估方法中,28S与18S核糖体RNA的比值长期被广泛用作实验室中的“黄金标准”。这一标准为何如此受重视?其背后有着明确的原理与判断依据。…...
OpenClaw低代码开发:Qwen2.5-VL-7B自动化流程设计器入门
OpenClaw低代码开发:Qwen2.5-VL-7B自动化流程设计器入门 1. 为什么需要可视化流程设计器? 上周我尝试用OpenClaw自动处理一批产品截图和说明文档时,遇到了一个典型问题:需要先让Qwen2.5-VL-7B识别图片中的关键元素,再…...
装机:WIN10家庭版升级专业版
https://ubuntu.com/download/desktop/thank-you?version24.04.4&architectureamd64<strue 装机:WIN10家庭版升级专业版Win10、Win11不重装系统情况下怎么使用一条命令实现家庭版升级为专业版或企业版?https://mp.weixin.qq.com/s/bIcRu6A_cl…...
