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

手撕spring框架(3)

手撕spring框架(3)

相关系列
手撕spring框架(1)
手撕spring框架(2)
手撕spring框架(4)

InitializingBean 接口详解

什么是 InitializingBean 接口?

InitializingBean 接口是 Spring 框架中的一个接口,用于在 Bean 初始化完成后执行特定的操作。当一个 Bean 实现了 InitializingBean 接口,Spring 容器在实例化 Bean 后会调用其 afterPropertiesSet() 方法,从而实现在 Bean 初始化阶段执行一些定制化的逻辑。

InitializingBean 接口的作用

InitializingBean 接口的主要作用是在 Bean 初始化完成后执行一些必要的操作,例如初始化一些资源、建立一些连接等。通过实现 InitializingBean 接口,开发人员可以在 Bean 初始化阶段 进行一些自定义的操作,从而更好地控制 Bean 的生命周期。

InitializingBean 接口的使用方法

要实现 InitializingBean 接口,只需要在 Bean 类中实现 afterPropertiesSet() 方法即可。在 afterPropertiesSet() 方法中编写需要在 Bean 初始化阶段执行的逻辑代码。下面是一个简单的示例:

package com.spring;public interface InitializingBean {void afterPropertiesSet();
}

调整DzendApplicationContext中的createBean方法

具体看最后文件

BeanPostProcessor类详解

什么是BeanPostProcessor?

在Spring框架中,BeanPostProcessor是一个接口,它允许在Spring容器实例化bean之后和调用bean的初始化方法之前对bean进行自定义处理。BeanPostProcessor接口定义了两个方法:postProcessBeforeInitialization和postProcessAfterInitialization。通过实现这两个方法,我们可以在bean初始化前后做一些额外的操作,比如修改bean的属性值、添加额外的逻辑等。

BeanPostProcessor的使用场景

BeanPostProcessor可以用于很多场景,比如:

  1. AOP(面向切面编程):通过BeanPostProcessor可以在bean初始化前后动态代理bean,实现AOP功能。
  2. 属性注入:可以在bean初始化前后修改bean的属性值,实现自定义的属性注入逻辑。
  3. Bean初始化:可以在bean初始化前后执行一些额外的逻辑,比如打印日志、记录性能指标等。

BeanPostProcessor的实现方式

要实现一个BeanPostProcessor,我们需要创建一个实现了BeanPostProcessor接口的类,并实现postProcessBeforeInitialization和postProcessAfterInitialization方法。下面是一个简单的示 例:

package com.spring;public interface BeanPostProcessor {default Object postProcessBeforeInitialization(Object bean, String beanName) {// 在bean初始化前执行的逻辑return bean;}default Object postProcessAfterInitialization(Object bean, String beanName) {// 在bean初始化后执行的逻辑return bean;}
}

调整DzendApplicationContext的代码

主要流程是添加一个BeanPostProcessorList,在扫描路径的时候,把符合条件的类添加到beanPostProcessorList队列中

添加一个beanPostProcessorList列表

private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();

scan方法中加入

if (clazz.isAnnotationPresent(Component.class)) {

代码下添加以下代码

if (BeanPostProcessor.class.isAssignableFrom(clazz)) {BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance();beanPostProcessorList.add(instance);}

在createBean方法中调整代码

for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {instance = beanPostProcessor.postProcessBeforeInitialization(instance,beanName);}
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {instance = beanPostProcessor.postProcessAfterInitialization(instance,beanName);}

最后附修改后的代码

DzendApplicationContext.java

package com.spring;import java.beans.Introspector;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class DzendApplicationContext {private Class<?> configClass;private Map<String,BeanDefinition> beanDefinitionMap= new HashMap<>();private Map<String, Object> singletonObjects=new HashMap<>();private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();public DzendApplicationContext(Class configClass)   {this.configClass=configClass;scan(configClass);}private void scan(Class configClass) {if(configClass.isAnnotationPresent(ComponentScan.class)){ComponentScan componentScan = (ComponentScan) configClass.getAnnotation(ComponentScan.class);String path = componentScan.value();path = path.replace(".","/");ClassLoader classLoader = DzendApplicationContext.class.getClassLoader();URL resource = classLoader.getResource(path);try {path = URLDecoder.decode(path, "UTF-8");} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}File file = null;try {file = new File(  URLDecoder.decode(resource.getFile(), "UTF-8"));} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}if(file.isDirectory()){for (File f : file.listFiles()) {String absolutePath = f.getAbsolutePath();absolutePath = absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));absolutePath=absolutePath.replace("\\",".");try {Class<?>  clazz = classLoader.loadClass(absolutePath);if (clazz.isAnnotationPresent(Component.class)) {if (BeanPostProcessor.class.isAssignableFrom(clazz)) {BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance();beanPostProcessorList.add(instance);}Component componentAnnotaion = clazz.getAnnotation(Component.class);String beanName= componentAnnotaion.value();if("".equals(beanName)){beanName = Introspector.decapitalize(clazz.getSimpleName());}BeanDefinition beanDefinition = new BeanDefinition();beanDefinition.setType(clazz);if (clazz.isAnnotationPresent(Scope.class)) {Scope scopeAnnotation = clazz.getAnnotation(Scope.class);String value = scopeAnnotation.value();beanDefinition.setScope(value);}else{beanDefinition.setScope("singleton");}beanDefinitionMap.put(beanName,beanDefinition);}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InvocationTargetException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (NoSuchMethodException e) {throw new RuntimeException(e);}}}}}public Object getBean(String beanName){if(!beanDefinitionMap.containsKey(beanName)){throw new NullPointerException();}BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);if(beanDefinition.getScope().equals("singleton")){Object singletonObject = singletonObjects.get(beanName);if(singletonObject == null){singletonObject = createBean(beanName,beanDefinition);singletonObjects.put(beanName,singletonObject);}return singletonObject;}else{//原型Object prototypeBean = createBean(beanName, beanDefinition);return prototypeBean;}}private Object createBean(String beanName, BeanDefinition beanDefinition) {Class clazz = beanDefinition.getType();Object instance = null;try {instance = clazz.getConstructor().newInstance();for (Field field : clazz.getDeclaredFields()) {if(field.isAnnotationPresent(Autowired.class)){field.setAccessible(true);field.set(instance,getBean(field.getName()));}}for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {instance = beanPostProcessor.postProcessBeforeInitialization(instance,beanName);}if(instance instanceof BeanNameAware){((BeanNameAware) instance).setBeanName(beanName);}if(instance instanceof InitializingBean){((InitializingBean) instance).afterPropertiesSet();}for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {instance = beanPostProcessor.postProcessAfterInitialization(instance,beanName);}} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (InvocationTargetException e) {throw new RuntimeException(e);} catch (NoSuchMethodException e) {throw new RuntimeException(e);}return instance;}
}

相关文章:

手撕spring框架(3)

手撕spring框架&#xff08;3&#xff09; 相关系列 手撕spring框架&#xff08;1&#xff09; 手撕spring框架&#xff08;2&#xff09; 手撕spring框架&#xff08;4&#xff09; InitializingBean 接口详解 什么是 InitializingBean 接口&#xff1f; InitializingBean 接…...

Swift手撸轮播效果

一、创建ScrollView objcMembers class LSLottieAnimView: UIView, UIScrollViewDelegate {private var scrollView: UIScrollView UIScrollView()func addScrollView() {scrollView.showsHorizontalScrollIndicator falsescrollView.isPagingEnabled true// 自定义framesc…...

数据分析——业务数据描述

业务数据描述 前言一、数据收集数据信息来源企业内部数据源市场调查数据源公共数据源和第三方数据源 二、公司内部数据客户资料数据销售明细数据营销活动数据 三、市场调查数据观察法提问法实验法 四、公共数据五、第三方数据六、数据预处理七、数据清洗丢弃部分数据补全缺失的…...

【哈希表】Leetcode 14. 最长公共前缀

题目讲解 14. 最长公共前缀 算法讲解 我们使用当前第一个字符串中的与后面的字符串作比较&#xff0c;如果第一个字符串中的字符没有出现在后面的字符串中&#xff0c;我们就直接返回&#xff1b;反之当容器中的所有字符串都遍历完成&#xff0c;说明所有的字符串都在该位置…...

(三)JVM实战——对象的内存布局与执行引擎详解

对象的内存布局 对象的实例化 对象的创建方式 - new的方式 - Class的newInstance():反射的方式 - Construct的newInstance() - clone:实现Cloneable接口,默认浅拷贝 - 使用反序列化&#xff1a;将二进制流转化为内存对象 创建对象的步骤 - 判断对象对应的类是否加载、链接、初…...

微信视频号如何变现呢,视频号涨粉最快方法

今天给大家带来的是视频号分成计划 视频号流量主这个项目&#xff0c;可以说这是目前的一个蓝海赛道&#xff0c;做的人也少&#xff0c;外面开的培训也很少&#xff0c;作为副业还是比较适合个人的&#xff0c;如果想批量操作这个项目&#xff0c;也比较适合工作室的。而且这…...

数智先锋 | 多场景数据治理案例,释放数据要素生产力

数据作为第五大生产要素&#xff0c;成为释放新质生产力的关键基础。 当前各个行业数字化建设如火如荼&#xff0c;全力挖掘数据价值以驱动行业高质量应用发展。数据治理成为数据要素价值发挥的重要基础和前提。 数据治理不单是技术问题&#xff0c;不是依赖工具就能解决的&a…...

UE5 audio capture 回声问题 ||在安卓上有爆鸣声

参考视频 0.基本步骤 【UE4_蓝图】录制麦克风声音/系统声音并输出保存WAV文件_ue4录音-CSDN博客 1.步骤 1.创建Sound Submix A 2. 右键新建Sound Submix B 3.把B的两个参数调为-96 4.audio capture的Base Submix&#xff0c;把前面提到的A赋值进去 5.开始录制输出和完成录制…...

第 10 场蓝桥杯小白入门赛题解

1.五一礼物【算法赛】 - 蓝桥云课 (lanqiao.cn) #include <iostream> using namespace std; int main() {cout<<"51"<<endl;return 0; }2.合成贤者之石【算法赛】 - 蓝桥云课 (lanqiao.cn) 假设黄水晶的个数是 x x x,那蓝水晶个数肯定是 x − 1 …...

抖音视频评论区用户采集 根据视频链接批量获取用户信息

要批量获取抖音视频评论区用户的信息&#xff0c;可以通过抖音开放平台的接口来实现。 首先&#xff0c;你需要在抖音开放平台注册开发者账号&#xff0c;并创建一个应用。然后&#xff0c;使用抖音开放平台提供的接口&#xff0c;可以根据视频链接获取视频的详细信息&#xf…...

C++ 多态(一)

一、多态定义 同一种操作作用于不同的对象时&#xff0c;可以产生不同的行为。在面向对象编程中&#xff0c;多态性是指通过继承和重写实现的&#xff0c;同一个方法在不同的子类中可以表现出不同的行为。多态性可以提高代码的灵活性和可扩展性&#xff0c;使得程序更易于维护…...

[Linux][网络][TCP][一][TCP基础][TCP报头]详细讲解

目录 1.TCP头部格式2.TCP协议的特点3.TCP如何封装与分用4.通过序列号和确认应答号提高可靠性1.32位序列号2.32位确认应答号3.保证可靠性4.为什么序列号和确认应答号是单独的字段 5.窗口大小1.TCP的发送和接收缓冲区2.窗口大小 6.连接管理机制 1.TCP头部格式 TCP全称为"传输…...

java-函数式编程-函数对象

定义 什么是合格的函数&#xff1f;无论多少次执行函数&#xff0c;只要输入一样&#xff0c;输出就不会改变 对象方法的简写 其实在类中&#xff0c;我们很多参数中都有一个this&#xff0c;被隐藏传入了 函数也可以作为对象传递&#xff0c;lambda就是很好的例子 函数式接口中…...

致远oa实时获取第三方自定义组件实现

背景 最近的一个需求不好处理&#xff0c;甲方没有准确的数据支撑&#xff0c;各种问题踢皮球&#xff0c;所以有时间实现一个实时获取数据的组件 需求 为了实现方便&#xff0c;封装了一个第三方数据实时展示的组件 只要修改配置&#xff0c;就可以实现字段的删除增加&…...

【Linux-点灯烧录-SD卡/USB烧写】

目录 1. 烧写方式2. 烧写之代码编译2.1 led.s->led.o2.2 led.o->led.elf2.3 led.elf->led.bin2.4 反汇编&#xff1a;led.elf->led.dis 3. 烧写之烧录到SD卡上&#xff1a;3.1 开启烧录软件权限&#xff1a;3.2 确定SD卡的格式&#xff1a;FAT323.3 烧录到SD卡上3.…...

PostgreSQL自带的命令行工具06- pg_isready

PostgreSQL自带的命令行工具06- pg_isready 基础信息 OS版本&#xff1a;Red Hat Enterprise Linux Server release 7.9 (Maipo) DB版本&#xff1a;16.2 pg软件目录&#xff1a;/home/pg16/soft pg数据目录&#xff1a;/home/pg16/data 端口&#xff1a;5777pg_isready 是 Po…...

【请投票】嘉立创EDA中LED发光二极管是否应有统一的引脚定义?

LED发光二极管的引脚定义应该是唯一的吗&#xff1f; 从下面原理图可以看到&#xff0c;器件型号仅尾缀不同,R代表RED红色发光二极管&#xff0c;W代表WHITE指白色发光二极管&#xff0c;是同一家制造商KENTO&#xff0c; 左侧红色发光二极管的1脚是阴极K&#xff0c;2脚是阳极…...

LT6911UXB HDMI2.0 至四端口 MIPI DSI/CSI,带音频 龙迅方案

1. 描述LT6911UXB 是一款高性能 HDMI2.0 至 MIPI DSI/CSI 转换器&#xff0c;适用于 VR、智能手机和显示应用。HDMI2.0 输入支持高达 6Gbps 的数据速率&#xff0c;可为4k60Hz视频提供足够的带宽。此外&#xff0c;数据解密还支持 HDCP2.2。对于 MIPI DSI / CSI 输出&#xff0…...

网络培训议题@2

目录 1. 如何通过IP和掩码确定网关&#xff1a;2. 网络路由的意义和配置方法&#xff1a;3. 网络Bond模式的区别和配置场景&#xff1a;4. 堆叠、VLAN、Trunk、聚合的意义&#xff1a;5. 虚拟机环境下VIP配置和常见问题&#xff1a;6. VXLAN拓展&#xff1a; 1. 如何通过IP和掩…...

linux文本三剑客之sed

目录 1、sed特点 1&#xff09;sed命令格式 2&#xff09;sed命令核心功能"增删改查" 2、sed命令执行过程 3、sed核心应用 1&#xff09;sed-查找p 2&#xff09;sed-删除d 3&#xff09;sed-增加cai 4) sed-替换s 1、sed特点 sed stream editor 流编辑器…...

【NotebookLM戏剧研究辅助实战指南】:20年戏剧学者亲授AI赋能文本细读的5大黄金工作流

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;NotebookLM戏剧研究辅助的底层逻辑与学科适配性 NotebookLM 以“语义锚点驱动”为核心机制&#xff0c;将用户上传的原始文本&#xff08;如莎士比亚手稿影印本OCR结果、梅兰芳口述史转录稿、《奥尼尔书…...

从原理图到PCB的桥梁:手把手教你用Cadence导出STM32项目的网表与BOM清单

从原理图到PCB的桥梁&#xff1a;手把手教你用Cadence导出STM32项目的网表与BOM清单 在电子设计自动化&#xff08;EDA&#xff09;流程中&#xff0c;从原理图设计到PCB布局的过渡阶段往往是最容易被忽视却又至关重要的环节。许多工程师在完成精美的原理图后&#xff0c;常常因…...

C51函数可重入性原理与实践指南

1. C51函数可重入性深度解析在嵌入式C51开发中&#xff0c;函数可重入性&#xff08;Reentrancy&#xff09;是一个直接影响系统稳定性的关键特性。简单来说&#xff0c;可重入函数是指能够被多个执行流&#xff08;如主程序和中断服务例程&#xff09;同时调用而不会引发数据冲…...

AI智能体的测试

测试AI智能体&#xff08;AI Agent&#xff09;与测试传统的确定性软件有本质的区别。传统软件测试关注的是“输入 A&#xff0c;是否必然输出 B”&#xff1b;而 AI Agent 具备自主规划、工具调用、长期记忆和非确定性生成的能力&#xff0c;这导致它的测试维度更广、复杂度更…...

CTF学习规划————1、如何入门CTF

CTF学习规划————1、如何入门CTF 无意中发现了一个巨牛巨牛的人工智能教程&#xff0c;忍不住分享一下给大家。教程不仅是零基础&#xff0c;通俗易懂&#xff0c;小白也能学&#xff0c;而且非常风趣幽默&#xff0c;还时不时有内涵段子&#xff0c;像看小说一样&#xff0…...

Onekey:三分钟学会免费获取Steam游戏清单的完整指南

Onekey&#xff1a;三分钟学会免费获取Steam游戏清单的完整指南 【免费下载链接】Onekey Onekey Steam Depot Manifest Downloader 项目地址: https://gitcode.com/gh_mirrors/one/Onekey Steam游戏清单获取从未如此简单&#xff01;你是否曾经需要获取Steam游戏的Depot…...

AI编码助手安全规则实战:为Cursor定制安全防线,防范硬编码与注入风险

1. 项目概述&#xff1a;当AI编码助手遇上安全红线最近在GitHub上看到一个挺有意思的项目&#xff0c;叫“Deadly244/cursor-security-rules”。光看名字&#xff0c;你可能会觉得这又是一个关于网络安全或代码审计的工具。但点进去仔细一看&#xff0c;发现它的定位非常精准且…...

2026年靠谱物联网供应商榜

作为深耕物联网领域五年的工程师&#xff0c;我见过太多“看起来很美好”的技术方案——设备接入率低、数据延迟高、多协议适配困难&#xff0c;尤其当项目涉及复杂环境时&#xff0c;这些问题会被无限放大。我们团队在实践中发现&#xff0c;许多物联网平台在核心算法层面缺乏…...

LLM应用开发资源导航:从Awesome List到实战项目构建

1. 项目概述&#xff1a;当“Awesome”遇见LLM应用如果你最近在GitHub上逛过&#xff0c;或者对大型语言模型&#xff08;LLM&#xff09;的应用开发感兴趣&#xff0c;那么“Shubhamsaboo/awesome-llm-apps”这个仓库大概率已经躺在你的浏览器书签或者GitHub星标列表里了。它不…...

终极Windows解析工具:WinFlexBison完整指南

终极Windows解析工具&#xff1a;WinFlexBison完整指南 【免费下载链接】winflexbison Main winflexbision repository 项目地址: https://gitcode.com/gh_mirrors/wi/winflexbison 你是否在Windows平台上开发编译器、解析器或需要处理复杂文本格式时&#xff0c;为缺少…...