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

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

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

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>

容器实现

java 复制代码
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;
            }
            //解析xml
            DocumentBuilderFactory 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");
                    //取对象id
                    String 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的一个核心小功能实现了

相关推荐
_oP_i29 分钟前
Pinpoint 是一个开源的分布式追踪系统
java·分布式·开源
mmsx32 分钟前
android sqlite 数据库简单封装示例(java)
android·java·数据库
bryant_meng35 分钟前
【python】OpenCV—Image Moments
开发语言·python·opencv·moments·图片矩
武子康1 小时前
大数据-258 离线数仓 - Griffin架构 配置安装 Livy 架构设计 解压配置 Hadoop Hive
java·大数据·数据仓库·hive·hadoop·架构
KevinRay_1 小时前
Python超能力:高级技巧让你的代码飞起来
网络·人工智能·python·lambda表达式·列表推导式·python高级技巧
Captain823Jack2 小时前
nlp新词发现——浅析 TF·IDF
人工智能·python·深度学习·神经网络·算法·自然语言处理
资源补给站2 小时前
大恒相机开发(2)—Python软触发调用采集图像
开发语言·python·数码相机
豪宇刘2 小时前
MyBatis的面试题以及详细解答二
java·servlet·tomcat
秋恬意2 小时前
Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别
java·数据库·mybatis
Captain823Jack2 小时前
w04_nlp大模型训练·中文分词
人工智能·python·深度学习·神经网络·算法·自然语言处理·中文分词