手撕spring框架(3)

手撕spring框架(3)

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

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;}
}

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

服务器远程连接jupyter notebook

目录 服务器远程连接jupyter notebook1、在服务器端安装notebook2、在服务器端的设置Step 1:Step 2:Step 3: 3. 在服务器端运行jupyter4、在windows 上连接远程服务器 参考资料 服务器远程连接jupyter notebook 1、在服务器端安装notebook conda install jupyter notebook 2…

一个C++小程序调试过程记录

Top 20 C Projects With Source Code [2024 Update]https://www.interviewbit.com/blog/cpp-projects/ 这个网页有一些简单的C程序的源码&#xff0c;闲来无事&#xff0c;把第一个程序&#xff08;Bookshop Management System Using C&#xff09;的源码下载了下来。 源文件…

面试:Spring(IOC、AOP、事务失效、循环引用、SpringMVC、SpringBoot的自动配置原理、Spring框架常见注解)

目录 一、Spring的单例Bean是否是线程安全的&#xff1f; 二、什么是AOP 1、介绍 &#xff08;1&#xff09;记录操作日志 &#xff08;2&#xff09;实现Spring中的事务 三、spring中事务失效的场景有哪些&#xff1f; 1、异常捕获处理 2、抛出检查异常 3、非public方…

jupyter notebook导出pdf文件显示不了中文

找到文件index.tex.j2&#xff0c;我的在 C:\Users\Administrator\miniconda3\envs\opencv2\share\jupyter\nbconvert\templates\latex 我安装miniconda3并配置opencv2所需要的环境, 配置前 最后&#xff1a;用文本编辑器打开&#xff0c;修改图中article为ctexart&#xf…

计算机网络 —— 网络层

IP 1. 基本介绍2. IP地址定义3. IP地址分类4. 子网掩码5. 全局地址与私有地址 1. 基本介绍 TCP/IP 协议的心脏是网络层&#xff0c;主要“实现节点之间的通信”&#xff0c;即“点对点(end-to-end)通信”。 网络层包含IP(Internet Protocol)及DNS&#xff08;Domain Name Sys…

设计模式之空对象模式

空对象模式&#xff08;Null Object Pattern&#xff09;也称为零对象模式&#xff0c;是一种设计模式&#xff0c;用于代表空值的对象&#xff0c;而不是返回null。它的目的是让空对象能够像任何其他非空对象一样被使用&#xff0c;从而避免在代码中进行空值检查&#xff0c;提…

Meditron:基于 Llama 完全开源的医学大语言模型

健康危机就在眼前&#xff0c;当医疗资源有限时&#xff0c;每一秒钟都至关重要&#xff01;Meditron 就像一位忠实的医疗助手&#xff0c;提供基于证据的护理建议和情境意识的推荐&#xff0c;帮助医疗工作者在诊断和治疗过程中做出更准确的决策。 在资源有限的医疗环境中&am…

06_电子设计教程基础篇(学习视频推荐)

文章目录 前言一、基础视频1、电路原理3、模电4、高频电子线路5、电力电子技术6、数学物理方法7、电磁场与电磁波8、信号系统9、自动控制原理10、通信原理11、单片机原理 二、科普视频1、工科男孙老师2、达尔闻3、爱上半导体4、华秋商城5、JT硬件乐趣6、洋桃电子 三、教学视频1…

Text-to-SQL小白入门(12)Awesome-Text2SQL开源项目star破1000

项目介绍 项目地址 23年9月份刚开源这个项目&#xff0c;大半年过去了&#xff0c;star数终于破1000啦&#xff0c;决定在知乎更新一下内容&#xff0c;看看内容变化&#xff0c;知乎有上当时项目介绍的链接&#xff1a;追光者&#xff1a;Text-to-SQL小白入门&#xff08;六&…

用LM Studio搭建微软的PHI3小型语言模型

什么是 Microsoft Phi-3 小语言模型&#xff1f; 微软Phi-3 模型是目前功能最强大、最具成本效益的小型语言模型 &#xff08;SLM&#xff09;&#xff0c;在各种语言、推理、编码和数学基准测试中优于相同大小和更高大小的模型。此版本扩展了客户高质量模型的选择范围&#x…

【计算机网络】网络层总结

目录 知识梗概 IP地址 子网划分 IP包头格式 路由 网络层协议 ARP病毒/ARP欺骗 知识梗概 IP地址 IP相关介绍&#xff1a;机器之间需要交流&#xff0c;必须要一个地址才能找到对应的主机&#xff0c;IP地址是主机的一种表示&#xff0c;保证主机之间的正常通信&#xff…

【Mac】Mac安装软件常见问题解决办法

前言 刚开始用Mac系统的小伙伴或者在更新系统版本后运行App的朋友会经常碰到弹窗提示「xxx已损坏&#xff0c;无法打开&#xff0c;您应该将它移到废纸篓」、「打不开xxx&#xff0c;因为Apple无法检查其是否包含恶意软件」、「打不开xxx&#xff0c;因为它来自身份不明的开发…

计算机408备考-数据结构重要知识点-数据结构的定义

【计算机408备考-数据结构重要知识点-数据结构的定义-哔哩哔哩】 https://b23.tv/x7shjNf 数据是信息的载体。数据元素是数据的基本单位。一个数据元素可由若干数据项组成&#xff0c;数据项是构成数据元素的不可分割的最小单位。数据对象是具有相同性质的数据元素的集合&…

cAdvisor-Docker容器性能分析工具

cAdvisor-Docker容器性能分析工具 软件简介 cAdvisor 是谷歌公司用来分析运行中的Docker容器的资源占用以及性能特性的工具。 cAdvisor 是一个运行中的守护进程用来收集、聚合、处理和导出运行容器相关的信息&#xff0c;每个容器保持独立的参数、历史资源使用情况和完整的资…

【数据结构与算法】力扣 239. 滑动窗口最大值

题干描述 给你一个整数数组 nums&#xff0c;有一个大小为 k **的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1&#xff1a; 输入&#xff1a; nums [1,3,-1,-3,5,3…

树莓派点亮LED灯

简介 使用GPIO Zero library 的 Python库实现点亮LED灯。接线 树莓派引脚参考图如下&#xff1a; LED正极 接GPIO17 LED负极 接GND 权限 将你的用户加到gpio组中&#xff0c; 否则无法控制GPIO sudo usermod -a -G gpio 代码 from gpiozero import LED from time impor…

使用Python的Tkinter库创建你的第一个桌面应用程序

文章目录 准备工作创建窗口和按钮代码解释运行你的应用程序结论 在本教程中&#xff0c;我们将介绍如何使用Python的Tkinter库创建一个简单的桌面应用程序。我们将会创建一个包含一个按钮的窗口&#xff0c;点击按钮时会在窗口上显示一条消息。 准备工作 首先&#xff0c;确保…

Delta lake with Java--利用spark sql操作数据2

上一篇文章尝试了建库&#xff0c;建表&#xff0c;插入数据&#xff0c;还差删除和更新&#xff0c;所以在这篇文章补充一下&#xff0c;代码很简单&#xff0c;具体如下&#xff1a; import org.apache.spark.sql.SaveMode; import org.apache.spark.sql.SparkSession;publi…

Unity ParticleSystem 入门

概述 在项目的制作过程成&#xff0c;一定少不了粒子系统的使用吧&#xff0c;如果你想在项目粒子效果&#xff0c;那这部分的内容一定不要错过喔&#xff01;我添加了理解和注释更好理解一点&#xff01; Common Attribute(粒子通用属性) Duration&#xff1a;粒子持续的时间…

Java基于微信小程序+uniapp的校园失物招领小程序(V3.0)

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…