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

Java利用反射和读取xml实现迷你容器

由于需要框架能实现多态,达到控制反转解耦。所以容器还是需要的,容器的存在可以简化对象获取工作,但是容器也不是万能的。合理使用即可,Spring对我来说太庞大了,用不着,为此给框架写一个迷你版容器。

容器配置还是继承以前用spring.net的容器配置,名称为ObjConfig.xml放在程序根目录供容器初始化

<?xml version="1.0" encoding="utf-8"?>
<objects xmlns='http://www.springframework.net' default-autowire="byType"><!--这个配置文件主要用来配置系统的业务服务类,不要删除、修改提交其他人添加的配置,新加配置提交时主要同时提交配置使用的动态库,--><!--否则会造成其他人更新后报错--><!--检验数据访问层底层。postgresql配LIS.DAL.Base.PostgreSqlBase--><object id="LisMianDbFactory" type="LIS.Dal.Base.PostgreSqlBase,LIS.Dal.Base"  singleton="false"></object></objects>

容器实现

package LIS.Core.Context;import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.lang.reflect.Type;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
import java.util.HashMap;
import java.util.*;//一个迷你版容器,供ORM等控制反转使用
public class ObjectContainer {///用来存类型private static List<Class> classList=new ArrayList<Class>();///存类的查找关系private static HashMap<String, Integer> classIndexMap = new HashMap<String, Integer>();/// <summary>/// 按类型返回强类型的对象,一般用接口获得实现类/// </summary>/// <typeparam name="T">对象类型</typeparam>/// <returns>返回的对象</returns>public static <T> T GetObject(){Type type = ObjectContainer.class.getClass().getGenericSuperclass();Class c=type.getClass();Class<?> parent=c.getSuperclass();String cName=c.getName();if(classIndexMap.containsKey(cName)){//创建对象Object o = GetObject(cName);return (T)o;}if(parent!=null){String parentName=parent.getName();if(classIndexMap.containsKey(parentName)){//创建对象Object o = GetObject(parentName);return (T)o;}}Class<?> interfaceArr[]=c.getInterfaces();if(interfaceArr!=null&&interfaceArr.length>0){for(int j=0;j<interfaceArr.length;j++){String interfaceName=interfaceArr[j].getName();if(classIndexMap.containsKey(interfaceName)){//创建对象Object o = GetObject(interfaceName);return (T)o;}}}return null;}/// <summary>/// 按名称返回强类型的对象/// </summary>/// <typeparam name="T">对象类型</typeparam>/// <param name="name">对象名称</param>/// <returns>返回的对象</returns>public static <T> T GetTypeObject(String name){Object o=GetObject(name);return (T)o;}/// <summary>/// 按名称返回对象/// </summary>/// <param name="name">对象名称</param>/// <returns>返回对象</returns>public static Object GetObject(String name){if(classIndexMap.containsKey(name)){try {int index=classIndexMap.get(name);Class c=classList.get(index);//创建对象Object o = c.newInstance();return o;}catch (Exception ex){ex.printStackTrace();}}return null;}/// <summary>/// 用类型全名和程序集全名获得类型/// </summary>/// <param name="typeName">类型全名</param>/// <param name="assemblyName">程序集名</param>/// <returns></returns>private static Class GetType(String typeName, String assemblyName){try {//得到根路径Class<?> clazz = ObjectContainer.class;ClassLoader classLoader = clazz.getClassLoader();URL resourceURL1 = classLoader.getResource("");String bashePath = resourceURL1.getFile();//组装成jar包路径String jarPath=bashePath+assemblyName+".jar";File file = new File(jarPath);if (!file.exists()) {throw new Exception("未能找到"+jarPath+"的文件");}//反射得到类型//自己生成jar包路径URL url = file.toURI().toURL();URL[] urls = new URL[]{url};//加载程序集URLClassLoader loader = new URLClassLoader(urls);//加载类Class c = loader.loadClass(typeName);if(c!=null){return  c;}else{throw new Exception("未能构建类型"+typeName);}}catch (Exception ex){ex.printStackTrace();}return  null;}/// <summary>/// 从根目录的ObjConfig初始化IOC容器,还是按Spring.Net的配置格式/// </summary>public static void InitIoc() {try {//得到根路径Class<?> clazz = ObjectContainer.class;ClassLoader classLoader = clazz.getClassLoader();URL resourceURL = classLoader.getResource("resources/ObjConfig.xml");String IocPath = resourceURL.getFile();//判断配置是否存在File file = new File(IocPath);if (!file.exists()) {System.out.println("resources/ObjConfig.xml文件不存在,请确认!");return;}//解析xmlDocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = factory.newDocumentBuilder();Document document = builder.parse(file);// 获得根节点Element rootElement = document.getDocumentElement();// 获得根节点下的所有子节点NodeList students = rootElement.getChildNodes();for (int i = 0; i < students.getLength(); i++) {// 由于节点多种类型,而一般我们需要处理的是元素节点Node childNode = students.item(i);// 元素节点就是非空的子节点,也就是还有孩子的子节点if (childNode.getNodeType() == Node.ELEMENT_NODE) {Element childElement = (Element) childNode;//不是对象配置元素就忽略if(childElement.getNodeName()!= "object"){continue;}//解析类型配置String type=childElement.getAttribute("type");//是否单例String singleton=childElement.getAttribute("singleton");//取对象idString id=childElement.getAttribute("id");//分割类全面和包名String [] arr=type.split(",");//反射得到类型Class c=GetType(arr[0],arr[1]);//添加到类型列表classList.add(c);//存储索引int index=classList.size()-1;Class<?> parent=c.getSuperclass();//有id就存id映射if(id!=null&&id!=""){if(classIndexMap.containsKey(id)){throw new Exception("已经包含了id为:"+id+"的类型");}classIndexMap.put(id,index);}//有父类就存父类映射if(parent!=null){String parentName=parent.getName();if(!classIndexMap.containsKey(parentName)){classIndexMap.put(parentName,index);}}//得到所有实现的接口Class<?> interfaceArr[]=c.getInterfaces();//循环存接口映射if(interfaceArr!=null&&interfaceArr.length>0){for(int j=0;j<interfaceArr.length;j++){String interfaceName=interfaceArr[j].getName();if(!classIndexMap.containsKey(interfaceName)) {classIndexMap.put(interfaceName, index);}}}}}}catch (Exception ex) {ex.printStackTrace();}}
}

使用容器
在这里插入图片描述
在这里插入图片描述

运行测试,成功取到PG数据库的数据
在这里插入图片描述

经过下午两小时的努力,LIS.Core的一个核心小功能实现了

相关文章:

Java利用反射和读取xml实现迷你容器

由于需要框架能实现多态&#xff0c;达到控制反转解耦。所以容器还是需要的&#xff0c;容器的存在可以简化对象获取工作&#xff0c;但是容器也不是万能的。合理使用即可&#xff0c;Spring对我来说太庞大了&#xff0c;用不着&#xff0c;为此给框架写一个迷你版容器。 容器…...

Android12之DRM基本接口实现(二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…...

普通二维码跳转微信小程序实战

简介 服务端springboot项目,前端基于uniapp的微信小程序,要求扫描二维码之后进入到小程序指定页面,下面记录一下实现过程以及过程中遇到的问题. 实现过程 下面是成功跳转的配置截图: 首先说下二维码规则,这个地方需要填写扫描二维码之后打开的地址,这个地址在我的项目里…...

spring boot 配置加载顺序

由官网的文档得知 https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config Default properties (specified by setting SpringApplication.setDefaultProperties).PropertySource annotations on your Configuration classe…...

基于stm32控制的4G模块在设备模式下通讯

这里的32控制其实和51的控制思路都是一样的&#xff0c;都是先利用一个网络助手将家里的无线网生成局域网&#xff0c;接着通过花生壳软件将局域网变成公共网&#xff0c;最后是利用串口助手&#xff0c;在4G模块的AT指令模式写入命令ATSOCKTCPC,公共网IP地址,公共网端口号&…...

预测宝可梦武力值、分类宝可梦

regression case 股票预测 无人车看到的各种sensor 影像镜头看到马路上的东西作为输入&#xff0c;输出就是方向盘角度等等的操纵策略 scalar 标量 这个是热力图&#xff0c;相当于你的XYZ但是Z用颜色表示了 closed-form solution 闭合解 learning rate事先定好的数值 在lin…...

Linux使用find命令查找文件

find命令 简介语法格式基本参数 参考实例根目录下文件名称的例子指定路径下特定类型的例子指定路径、文件类型特定文件名称的例子指定路径、文件类型特定文件大小的例子指定路径、文件类型 查找近期修改时间的例子指定路径、文件类型 查找空文件或目录的例子指定路径、文件类型…...

安卓使用android studio跨进程通信之AIDL

我写这篇文章不想从最基础的介绍开始,我直接上步骤吧. 1.创建服务端 1.1:创建服务端项目:我的as版本比较高,页面就是这样的 1.2:创建AIDL文件,右键项目,选中aidl aidl名字可以自定义也可以默认 basicTypes是自带的,可以删掉,也可以不删,然后把你自己所需的接口写上去 1.3:创建…...

RabbitMQ基础篇 笔记

RabbitMQ 余额支付 同步调用 一步一步的来&#xff0c;支付业务写完后&#xff0c;如果之后加需求&#xff0c;还需要增加代码&#xff0c;不符合开闭原则。 性能上也有问题&#xff0c;openfeign是同步调用&#xff0c;性能太差。 同步调用耦合太多。 同步的优势是可以立…...

实践小记—静态成员的使用注意(或许由此产生的不知名Bug)

序言 在实际生产过程中&#xff0c;为了便于调用&#xff0c;static修饰的成员会比较容易出现。 如果后期该变量并不会被修改&#xff0c;可以考虑使用。但如果后期需要被修改&#xff0c;使用该变量修饰符则需要慎重考虑。 尤其是在对硬件控制的实际生产中&#xff0c;更需…...

华为OD 身高体重排序(100分)【java】A卷+B卷

华为OD统一考试A卷B卷 新题库说明 你收到的链接上面会标注A卷还是B卷。目前大部分收到的都是B卷。 B卷对应20022部分考题以及新出的题目&#xff0c;A卷对应的是新出的题目。 我将持续更新最新题目 获取更多免费题目可前往夸克网盘下载&#xff0c;请点击以下链接进入&#xff…...

在Word中,图片显示不全

在今天交作业的时候&#xff0c;发现了一个非常SB的事情&#xff0c;把图片复制过去显示不完全&#xff1a; 使用文心一言查看搜索了一下&#xff0c;发现可能是以下几种原因&#xff1a; 图片所在行的行高设置不正确。可以重新设置行高&#xff0c;具体步骤包括打开图片显示…...

C++数据结构X篇_20_选择排序

文章目录 1. 选择排序原理2. 选择排序原理核心代码3. 选择排序时间消耗 1. 选择排序原理 选择排序&#xff1a;相对于冒泡排序&#xff0c;减少了交换次数&#xff0c;下图展示了选择排序的原理&#xff0c;具体仍需要结合代码分析。 2. 选择排序原理核心代码 //选择排序 v…...

华为OD技术面试-最短距离矩阵(动态规划、广度优先)

背景 记录2023-10-21 晚华为OD三面的手撕代码题&#xff0c;当时没做出来&#xff0c;给面试官说了我的想法&#xff0c;评价&#xff1a;解法复杂了&#xff0c;只是简单的动态规范 或 广度优先算法&#xff0c;事后找资料记录实现方式。 题目 腐烂的橘子 问题描述&#xff…...

【代码规范】switch 块级的作用域问题

代码规范的一些事儿 问题 今日 Git 提交代码时&#xff0c;出现报错&#xff1a; error Unexpected lexical declaration in case block no-case-declarations 解决过程 我马上就去百度&#xff0c;就找到了这篇文章&#xff1a;解决 Unexpected lexical declaration in ca…...

PHP 基础/练习

练习 成绩定级 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>成绩定级脚本</title> </…...

TCP协议与UDP协议

UDP协议 UDP协议端的格式 16位UDP长度,表示整个数据报(UDP首部UDP数据)的最大长度;如果校验和出错,就会直接丢弃; UDP的特点 UDP传输过程类似寄信 无连接 知道对端的IP和端口号就直接进行传输&#xff0c;不需要建立连接&#xff1b; 不可靠 没有任何安全机制&#xff0c…...

极智嘉(Geek+)柔性货箱到人拣选方案,助力Starlinks实现高效运营

近些年&#xff0c;电商业务席卷全球&#xff0c;一众企业蓬勃发展。比如沙特阿拉伯先进的物流与供应链解决方案供应商Starlinks的电子商务的销售额从6%增长到了23%。为满足日益增长的国际电商业务需求&#xff0c;以及订单交付时效性更高的要求&#xff0c;Starlinks与全球仓储…...

Hadoop3教程(三十一):(生产调优篇)异构存储

文章目录 &#xff08;157&#xff09;异构存储概述概述异构存储的shell操作 &#xff08;158&#xff09;异构存储案例实操参考文献 &#xff08;157&#xff09;异构存储概述 概述 异构存储&#xff0c;也叫做冷热数据分离。其中&#xff0c;经常使用的数据被叫做是热数据&…...

网络协议--UDP:用户数据报协议

11.1 引言 UDP是一个简单的面向数据报的运输层协议&#xff1a;进程的每个输出操作都正好产生一个UDP数据报&#xff0c;并组装成一份待发送的IP数据报。这与面向流字符的协议不同&#xff0c;如TCP&#xff0c;应用程序产生的全体数据与真正发送的单个IP数据报可能没有什么联…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

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

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

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档&#xff1a;manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号&#xff1a;4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建

【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...

Python环境安装与虚拟环境配置详解

本文档旨在为Python开发者提供一站式的环境安装与虚拟环境配置指南&#xff0c;适用于Windows、macOS和Linux系统。无论你是初学者还是有经验的开发者&#xff0c;都能在此找到适合自己的环境搭建方法和常见问题的解决方案。 快速开始 一分钟快速安装与虚拟环境配置 # macOS/…...