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
:用于支持解析@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表格中的背景透明 最近写大屏,用到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(最少使用)等。以下是一个简单的页面置换算法模拟实…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...

1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...

Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...