Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架

简单手写SpringIOC框架

    • 环境搭建
      • 基于XML方式
        • 项目结构
        • 项目代码
        • 运行结果
      • 基于注解方式
        • 项目结构
        • 项目代码
        • 运行结果
    • 简单手写SpringIOC框架
      • 核心原理
      • 基于XML方式
        • 原理
        • 项目结构
        • 项目代码
        • 运行结果
      • 基于注解方式
        • 原理
        • 项目结构
        • 项目代码
        • 运行结果

环境搭建

基于XML方式

项目结构

在这里插入图片描述

项目代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com</groupId><artifactId>spring</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.2.1.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>5.2.1.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.1.RELEASE</version></dependency></dependencies></project>

UserBean.java

package com.spring.bean;/*** @author honey* @date 2023-08-08 14:58:16*/
public class UserBean {
}

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userBean" class="com.spring.bean.UserBean"/></beans>

SpringTest01.java

package com.spring.test;import com.spring.bean.UserBean;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author honey* @date 2023-08-08 14:59:56*/
public class SpringTest01 {public static void main(String[] args) {// 读取spring.xmlClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");// 从IOC容器中读取对象UserBean userBean = applicationContext.getBean("userBean", UserBean.class);System.out.println(userBean);}
}

运行结果

在这里插入图片描述

基于注解方式

项目结构

在这里插入图片描述

项目代码

ScanBean.java

package com.spring.bean.scan;import org.springframework.stereotype.Component;/*** @author honey* @date 2023-08-08 16:37:26*/
@Component
public class ScanBean {
}

SpringConfig.java

package com.spring.config;import com.spring.bean.UserBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;/*** @author honey* @date 2023-08-08 16:30:21*/
@Configuration
@ComponentScan(value = {"com.spring.bean.scan"})
public class SpringConfig {@Bean(name = "user")public UserBean userBean() {return new UserBean();}
}

SpringTest02.java

package com.spring.test;import com.spring.bean.UserBean;
import com.spring.bean.scan.ScanBean;
import com.spring.config.SpringConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @author honey* @date 2023-08-08 16:31:25*/
public class SpringTest02 {public static void main(String[] args) {// 加载SpringConfigAnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);// 从IOC容器中读取对象UserBean userBean = applicationContext.getBean("user", UserBean.class);System.out.println(userBean);ScanBean scanBean = applicationContext.getBean("scanBean", ScanBean.class);System.out.println(scanBean);}
}

运行结果

在这里插入图片描述

简单手写SpringIOC框架

核心原理

底层使用map集合管理对象,key=beanId,value=实例对象

private final Map<String, Object> beanMap = new ConcurrentHashMap<>();

基于XML方式

原理

基于反射+工厂模式+DOM技术

  1. 使用DOM技术解析spring.xml文件;
  2. 获取bean的id和class属性;
  3. 根据类的完整路径使用反射技术初始化对象;
  4. 使用工厂模式管理初始化对象;

项目结构

在这里插入图片描述

项目代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com</groupId><artifactId>ext-spring-ioc</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.2.1.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>5.2.1.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.1.RELEASE</version></dependency><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency></dependencies></project>

UserBean.java

package com.spring.bean;/*** @author honey* @date 2023-08-08 16:56:32*/
public class UserBean {
}

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userBean" class="com.spring.bean.UserBean"/></beans>

SpringIocXml.java

package com.spring.ext;import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.core.io.ClassPathResource;import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** @author honey* @date 2023-08-08 16:57:17*/
public class SpringIocXml {private final Map<String, Object> beanMap = new ConcurrentHashMap<>();public SpringIocXml() throws IOException, DocumentException {init();}public <T> T getBean(String name) {return (T) beanMap.get(name);}/*** 初始化IOC容器*/private void init() throws IOException, DocumentException {// 解析spring.xml配置ClassPathResource classPathResource = new ClassPathResource("spring.xml");File xmlFile = classPathResource.getFile();SAXReader saxReader = new SAXReader();Document doc = saxReader.read(xmlFile);// 获取根节点Element rootElement = doc.getRootElement();// 获取bean节点信息List<Element> beans = rootElement.elements("bean");for (Element bean : beans) {try {String beanId = bean.attribute("id").getValue();String classPath = bean.attribute("class").getValue();// 使用反射机制初始化对象,并将对象存入Map集合Class<?> clazz = Class.forName(classPath);Object object = clazz.newInstance();beanMap.put(beanId, object);} catch (Exception e) {e.printStackTrace();}}}}

SpringTest01.java

package com.spring.test;import com.spring.bean.UserBean;
import com.spring.ext.SpringIocXml;
import org.dom4j.DocumentException;import java.io.IOException;/*** @author honey* @date 2023-08-08 17:04:35*/
public class SpringTest01 {public static void main(String[] args) throws DocumentException, IOException {SpringIocXml springIocXml = new SpringIocXml();UserBean userBean = springIocXml.getBean("userBean");System.out.println(userBean);}
}

运行结果

在这里插入图片描述

基于注解方式

原理

基于反射+工厂模式实现

  1. 判断配置类上是否有@Configuration注解;
  2. 获取配置类中的所有方法,判断方法上是否有@Bean注解,如果有则获取方法的返回值作为实例对象;
  3. 判断配置类上是否有@ComponentScan注解,如果有则扫描指定包下的所有类,并判断类上是否有@Component注解,如果有则通过反射技术初始化对象;
  4. 使用工厂模式管理初始化对象/实例对象;

项目结构

在这里插入图片描述

项目代码

pom.xml

<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.7</version>
</dependency>

ScanBean.java

package com.spring.bean.scan;import org.springframework.stereotype.Component;/*** @author honey* @date 2023-08-09 14:28:33*/
@Component
public class ScanBean {
}

SpringConfig.java

package com.spring.config;import com.spring.bean.UserBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;/*** @author honey* @date 2023-08-09 14:26:40*/
@Configuration
@ComponentScan(value = {"com.spring.bean.scan"})
public class SpringConfig {@Beanpublic UserBean userBean() {return new UserBean();}
}

SpringIocAnnotation.java

package com.spring.ext;import cn.hutool.core.lang.ClassScanner;
import cn.hutool.core.util.StrUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;/*** @author honey* @date 2023-08-09 14:12:21*/
public class SpringIocAnnotation {private final Object config;private final Map<String, Object> beanMap = new ConcurrentHashMap<>();public SpringIocAnnotation(Object config) {this.config = config;init();}/*** 初始化IOC容器*/public void init() {// 判断配置类上是否有@Configuration注解Configuration configuration = this.config.getClass().getDeclaredAnnotation(Configuration.class);if (configuration == null) {return;}// 处理@Bean注解Class<?> clazz = config.getClass();Method[] declaredMethods = clazz.getDeclaredMethods();for (Method method : declaredMethods) {// 判断方法上是否有@Bean注解Bean bean = method.getDeclaredAnnotation(Bean.class);if (bean != null) {try {// 获取beanIdString[] value = bean.value();String beanId = value.length > 0 ? value[0] : method.getName();// 获取方法的返回值Object object = method.invoke(config);beanMap.put(beanId, object);} catch (Exception e) {e.printStackTrace();}}}// 处理@Component注解ComponentScan componentScan = clazz.getDeclaredAnnotation(ComponentScan.class);if (componentScan != null) {for (String packageName : componentScan.value()) {try {// 扫描指定包下的所有类Set<Class<?>> classes = ClassScanner.scanPackage(packageName);for (Class<?> c : classes) {// 判断类上是否有@Component注解Annotation component = c.getDeclaredAnnotation(Component.class);if (component != null) {try {// 获取beanIdString beanId = StrUtil.lowerFirst(c.getSimpleName());// 通过反射技术初始化对象Object beanObject = c.newInstance();beanMap.put(beanId, beanObject);} catch (Exception e) {e.printStackTrace();}}}} catch (Exception e) {e.printStackTrace();}}}}public <T> T getBean(String name) {return (T) beanMap.get(name);}
}

SpringTest02.java

package com.spring.test;import com.spring.bean.UserBean;
import com.spring.bean.scan.ScanBean;
import com.spring.config.SpringConfig;
import com.spring.ext.SpringIocAnnotation;/*** @author honey* @date 2023-08-09 14:24:36*/
public class SpringTest02 {public static void main(String[] args) {SpringIocAnnotation springIocAnnotation = new SpringIocAnnotation(new SpringConfig());UserBean userBean = springIocAnnotation.getBean("userBean");System.out.println(userBean);ScanBean scanBean = springIocAnnotation.getBean("scanBean");System.out.println(scanBean);}
}

运行结果

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JSP实训项目设计报告—MVC简易购物商城

JSP实训项目设计报告—MVC简易购物商城 文章目录 JSP实训项目设计报告—MVC简易购物商城设计目的设计要求设计思路系统要求单点登录模块商品展示模块购物车展示模块 概要设计Model层View层Controller层 详细设计Model层View层登录界面系统主界面 Controller层 系统运行效果项目…

kafka是有序的吗?如何保证有序?

首先&#xff0c;Kafka无法保证消息的全局有序性&#xff0c;这是因为Kafka的设计中允许多个生产者并行地向同一个主题写入消息。而且&#xff0c;一个主题可能会被划分为多个分区&#xff0c;每个分区都可以在独立的生产者和消费者之间进行并行处理。因此&#xff0c;生产者将…

【MongoDB】数据库、集合、文档常用CRUD命令

目录 一、数据库操作 1、创建数据库操作 2、查看当前有哪些数据库 3、查看当前在使用哪个数据库 4、删除数据库 二、集合操作 1、查看有哪些集合 2、删除集合 3、创建集合 三、文档基本操作 1、插入数据 2、查询数据 3、删除数据 4、修改数据 四、文档分页查询 …

CSP复习每日一题(四)

树的重心 给定一颗树&#xff0c;树中包含 n n n 个结点&#xff08;编号 1 ∼ n 1∼n 1∼n&#xff09;和 n − 1 n−1 n−1条无向边。请你找到树的重心&#xff0c;并输出将重心删除后&#xff0c;剩余各个连通块中点数的最大值。 重心定义&#xff1a; 重心是指树中的一…

试图将更改推送到 GitHub,但是远程仓库已经包含了您本地没有的工作(可能是其他人提交的修改)

这通常是由于其他人或其他仓库推送到了相同的分支上&#xff0c;导致您的本地仓库和远程仓库之间存在冲突。 错误信息&#xff1a; To github.com:8upersaiyan/CKmuduo.git ! [rejected] main -> main (fetch first) error: failed to push some refs to github.com:8upers…

元宇宙时代来临,AI数字人的应用方式有哪些?

在数字化背景下&#xff0c;元宇宙的时代已经来临&#xff0c;当你看到网络新闻上各形各色的虚拟数字人时&#xff0c;你是不是也有些都心动呢&#xff1f;与真人相比&#xff0c;AI虚拟数字人还具有成本低廉并且不受时间、空间限制的特点&#xff0c;数字人的使用场景正在逐渐…

React集成tinymce插件

目录 一、Tinymce介绍 二、React集成Tinymce 1、安装tinymce/tinymce-react组件 2、React中引用 三、如何配置中文语言包 1、下载中文包 2、把语言文件放入tinymce 3、tinymce配置项中配置语言 一、Tinymce介绍 官网&#xff1a;The Most Advanced WYSIWYG Editor | T…

【脚踢数据结构】深入理解栈

(꒪ꇴ꒪ )&#xff0c;Hello我是祐言QAQ我的博客主页&#xff1a;C/C语言,Linux基础,ARM开发板&#xff0c;软件配置等领域博主&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff0c;让我们成为一个强大的攻城狮&#xff01;送给自己和读者的一句鸡汤&#x1f914;&…

数据清理在数据科学中的重要性

什么是数据清理&#xff1f; 推荐&#xff1a;使用 NSDT场景编辑器 助你快速搭建可编辑的3D应用场景 在数据科学中&#xff0c;数据清理是识别不正确数据并修复错误的过程&#xff0c;以便最终数据集可供使用。错误可能包括重复字段、格式不正确、字段不完整、数据不相关或不准…

web集群学习:源码安装nginx配置启动服务脚本、IP、端口、域名的虚拟主机

目录 1、源码安装nginx&#xff0c;并提供服务脚本。 2、配置基于ip地址的虚拟主机 3、配置基于端口的虚拟主机 4、配置基于域名的虚拟主机 1、源码安装nginx&#xff0c;并提供服务脚本。 1、源码安装会有一些软件依赖 &#xff08;1&#xff09;检查并安装 Nginx 基础依赖…

数据结构刷题训练——链表篇(二)

目录 前言 1.题目一&#xff1a;链表分割 1.1 思路 1.2 分析 1.3 题解 2. 题目二&#xff1a;相交链表 2.1 思路 2.2 分析 2.3 题解 3. 题目三&#xff1a;环形链表 3.1 思路 3.2 分析 3.3 题解 总结 前言 本期继续分享链表相关的OJ题目&#xff0c;在这个专栏博客…

【论文阅读】EULER:通过可扩展时间链接预测检测网络横向移动(NDSS-2022)

作者&#xff1a;乔治华盛顿大学-Isaiah J. King、H. Howie Huang 引用&#xff1a;King I J, Huang H H. Euler: Detecting Network Lateral Movement via Scalable Temporal Graph Link Prediction [C]. Proceedings 2022 Network and Distributed System Security Symposium…

UDP通信实验、广播与组播、本地套接字

文章目录 流程函数应用广播应用 组播&#xff08;多播&#xff09;本地套接字应用 流程 函数 返回值&#xff1a; 成功&#xff0c;返回成功发送的数据长度 失败&#xff0c;-1 返回值&#xff1a; 成功&#xff0c;返回成功接收数据长度 失败&#xff0c;-1 应用 广播 应用 …

MongoDB文档-进阶使用-MongoDB索引-createindex()与dropindex()-在MongoDB中使用正则表达式来查找

阿丹&#xff1a; 之前研究了MongoDB的基础增删改查。在学会基础的数据库增删改查肯定是不够的。这个时候就涉及到了数据库搜索的时候的效率。需要提高数据的搜索效率。 MongoDB索引 在所以数据库中如果没有数据索引的时候。如果需要查找到一些数据。都会去主动扫描所有可能存…

mybatis-plus的逻辑删除的坑

一旦在逻辑字段上加了TableLogic逻辑删除的配置&#xff0c;并且使用mybatis-plus自带的方法时&#xff08;如果自己用xml写SQL不会出现下面的情况&#xff09; 查询、修改时会自动排除逻辑删除的数据 当使用mybatis-plus自带的查询方法时&#xff0c;就不用每次查询的时候跟…

Blazor 简单组件(1):B_Icon开发

文章目录 前言ICON开发使用 前言 Blazor 简单组件(0)&#xff1a;简单介绍 ICON开发 <i class"Type" style"font-size:(Size)px;color:Color;"></i>code {/// <summary>/// icon类型/// </summary>[Parameter]public string Typ…

nginx 以及nginx优化

目录 nginx功能介绍 静态文件服务 反向代理 动态内容处理 SSL/TLS 加密支持 虚拟主机支持 URL 重写和重定向 缓存机制 日志记录 可扩展性和灵活性 nginx的主要应用场景 nginx常用命令 nginx另外一种安装方式 nginx常用的信号符&#xff1a; nginx配置文件详解 n…

Nginx复现

docker复现Nginx配置漏洞 2.1CRLF(carriage return/line feed)注入漏洞 这个漏洞产生的原因是请求重定向的错误配置&#xff0c;导致在url中输入回车换行符可以控制http响应头部 比如&#xff1a;location / { return 302 https://$host$uri; } 原本的目的是为了让http的…

【JavaEE基础学习打卡02】是时候了解JavaEE了

目录 前言一、为什么要学习JavaEE二、JavaEE规范介绍1.什么是规范&#xff1f;2.什么是JavaEE规范&#xff1f;3.JavaEE版本 三、JavaEE应用程序模型1.模型前置说明2.模型具体说明 总结 前言 &#x1f4dc; 本系列教程适用于JavaWeb初学者、爱好者&#xff0c;小白白。我们的天…

c#在设计时调试自定义 Windows 窗体控件

private string demoStringValue null; [Browsable(true)] public string DemoString {get{return this.demoStringValue;}set{demoStringValue value;} } 参考链接 在设计时调试自定义控件 - Windows Forms .NET Framework | Microsoft Learnhttps://learn.microsoft.com/z…