当前位置: 首页 > news >正文

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中文意思为后置处理器

InstantiationAwareBeanPostProcessorDestructionAwareBeanPostProcessor都是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:用于支持解析@Value
  • AutowiredAnnotationBeanPostProcessor:该处理器用于解析@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表格中的背景透明 最近写大屏&#xff0c;用到elementplus中的el-table&#xff0c;为了让显示效果好看一点&#xff0c;需要把表格的白色背景调整为透明&#xff0c;与整个背景融为一体。可以参考的资料非常少&#xff0c;大部分都是ElmentUI的方法&#xff0c;在…...

【会议征稿通知】2024第四届神经网络、信息与通信工程国际学术会议(NNICE 2024)

2024第四届神经网络、信息与通信工程国际学术会议&#xff08;NNICE 2024&#xff09; 2024 4th International Conference on Neural Networks, Information and Communication Engineering 2024第四神经网络、信息与通信工程国际学术会议&#xff08;NNICE 2024&#xff0…...

PyCharm改变代码背景图片的使用教程

一个好的集成环境是学习和使用一门编程语言的重中之重&#xff0c;这次我给大家分享如何改变PyCharm软件的代码背景图片。 说明&#xff1a;本教程使用的是汉化版PyCharm软件。 打开PyCharm软件。 点击软件最上方导航栏的文件&#xff0c;然后找到设置。 打开设置然后点击外观…...

BadNets: Identifying Vulnerabilities in the Machine Learning Model Supply Chain

BadNets: Identifying Vulnerabilities in the Machine Learning Model Supply Chain----《BadNets:识别机器学习模型供应链中的漏洞》 背景&#xff1a; 许多用户将训练过程外包给云计算&#xff0c;或者依赖于经过训练的模型&#xff0c;然后根据特定的任务对模型进行微调。这…...

Kubernetes速成课程:掌握容器编排的精髓

微服务演进方向 • 面向分布式设计(Distribution):容器、微服务、API 驱动的开发; • 面向配置设计(Configuration):⼀个镜像&#xff0c;多个环境配置; • 面向韧性设计(Resistancy):故障容忍和自愈; • 面向弹性设计(Elasticity):弹性扩展和对环境变化(负载)做出响应; •…...

【数据库】分组数据 GROUP BY、HAVING

分组数据 创建分组过滤分组SQL 子句顺序 创建分组 s q l sql sql 中&#xff0c;使用 GROUP BY 子句对数据进行分组。分组通常与聚合函数一起使用&#xff0c;以对每个组内的数据执行聚合操作&#xff1b; e . g . e.g. e.g. 按照客户分组&#xff0c;计算每个客户的订单总金额…...

“唯品会VIP商品API:一键获取奢侈品详情,尊享品质生活!“

要获取唯品会VIP商品的详细信息&#xff0c;您可以通过唯品会的API接口进行调用。 唯品会提供了多种商品选择&#xff0c;包括服装、美容护肤、鞋子、箱包、家居、母婴等等。在这些商品中&#xff0c;VIP奢侈品专区是唯品会的重要特色之一。 要获取VIP商品的详细信息&#xf…...

uniapp解决iOS切换语言——原生导航栏buttons文字不生效

uniapp 切换语言原生导航栏buttons文字不生效&#xff1f; 文章目录 uniapp 切换语言原生导航栏buttons文字不生效&#xff1f;效果图page.json配置解决方式 效果图 场景&#xff1a;在 tabbar 页面中&#xff0c;配置 原生导航栏 buttons &#xff0c;切换语言时&#xff0c;不…...

idea 基础设置

1、设置 IDEA 主题 2、自动导包和优化多余的包 3、同一个包下的类&#xff0c;超过指定个数的时候&#xff0c;导包合并为* 4、显示行号 &#xff0c; 方法和方法间的分隔符&#xff1a; 5、忽略大小写&#xff0c;进行提示 6、多个类不隐藏&#xff0c;多行显示 7、设置默认的…...

Rockchip Uboot CmdLine 作用 来源 常用参数

Rockchip Uboot CmdLine cmdline 是 U-Boot 向 kernel 传递参数的一个重要手段&#xff0c;诸如传递启动存储&#xff0c;设备状态等。cmdline 参数有多个来源&#xff0c;由 U-Boot 进行拼接、过滤重复数据之后再传给 kernel。U-Boot 阶段的 cmdline 被保存在 bootargs 环境变…...

MySQL表导出

# 导出表和数据 mysqldump --skip-extended-insert -hHost -uUser -pPassword -PPost database table > table.sql# 如&#xff1a; mysqldump --skip-extended-insert -h172.1.0.1 -uroot -pabc123 -P3306 data_support city_code > city_code.sql# 导入表和数据 mysql …...

HTML页面获取URL传递的参数值

如&#xff1a; // 查询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 根据提示信息&#xff0c;拿到管理员密码&#xff0c;并解锁 5、安装…...

asp.net网球馆计费管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net网球馆计费管理系统是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语 言开发 aspnet网球馆计费管理系统1 二、…...

动手学深度学习——第五次学

权重衰减是最广泛使用的正则化的技术之一 今天学的很头疼&#xff0c;好多都是公式 12权重衰退&#xff08;解决过拟合&#xff09; 13丢弃法&#xff08;解决过拟合&#xff09; 14数值稳定&#xff08;梯度爆炸和梯度消失问题&#xff09; 15竞赛题讲解 层和块 多层感知机…...

python实验16_网络爬虫

实验16&#xff1a;网络爬虫 1.实验目标及要求 &#xff08;1&#xff09;掌握简单爬虫方法。 2. 实验主要内容 爬取中国票房网 ① 爬取中国票房网&#xff08;www.cbooo.cn)2019年票房排行榜前20名的电影相关数据 代码部分: import time from selenium.webdriver impor…...

家长扫码查成绩

亲爱的老师&#xff0c;你是否曾为了如何让家长更方便地查询学生的成绩而烦恼&#xff1f;现在&#xff0c;我们为你介绍一款简单易用的成绩查询系统&#xff0c;让家长只需轻轻一扫&#xff0c;即可查看孩子的成绩。 一、什么是成绩查询系统&#xff1f; 成绩查询系统是一款专…...

【转】多台服务器共享session问题

多台服务器共享 session 问题 现在的大型网站中&#xff0c;如何实现多台服务器中的 session 数据共享呢&#xff1f; 当使用多台服务器架设成集群之后&#xff0c;我们通过负载均衡的方式&#xff0c;同一个用户&#xff08;或者 ip&#xff09;访问时被分配到不同的服务器上…...

页面置换算法的模拟实现及命中率对比

页面置换算法是用于管理计算机内存中页面&#xff08;或页面框&#xff09;的一种策略。常见的页面置换算法包括FIFO&#xff08;先进先出&#xff09;、LRU&#xff08;最近最少使用&#xff09;、LFU&#xff08;最少使用&#xff09;等。以下是一个简单的页面置换算法模拟实…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

Linux 中如何提取压缩文件 ?

Linux 是一种流行的开源操作系统&#xff0c;它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间&#xff0c;使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的&#xff0c;要在 …...