精华内容
下载资源
问答
  • 笔者之前沉迷游戏无法自拔,但是现在之前...从来没有系统的总结归纳过学过的知识,于是决定自己写框架试试,也可以查漏补缺,不懂得地方就多看看别的怎么处理的。所以开贴记录下自己的学习成果,框架还不完善只是作为

    笔者之前沉迷游戏无法自拔,但是现在之前玩的游戏也不太爱玩了,发现下班到睡觉之前有2-3个小时空闲,仿佛发现了一笔宝贵的财富不能浪费。
    笔者从事手游工作也有两年的时间了,主要做的是逻辑和SDK方面的工作,有时候也查查平台相关的闪退卡死问题。从来没有系统的总结归纳过学过的知识,于是决定自己写个框架试试,也可以查漏补缺,不懂得地方就多看看别的怎么处理的。所以开贴记录下自己的学习成果,框架还不完善只是作为记录(可能并不能投入使用),老司机可以随意指点,我会虚心接受的。

    一、UI插件的选择

    笔者第一个项目用的插件是NGUI,因为当时没得选,市场上就有这一款插件供使用。自从Unity推出了自己的UGUI,大部分新的项目也相继使用开来。我猜想主要原因是UGUI是Unity原生的,所以效率性能应该会好很多,兼容性也会提高。笔者两款UI插件都有用过,但是从去年开始就关注Unity的第三款UI插件FairyGUI,发现此款插件有很多方便开发者的功能,加之笔者自己的实验项目那就研究个没尝试过得好了,所以就选择了FairyGUI。
    FairyGUI地址:http://www.fairygui.com/
    第一件事就是上官网下demo,看官网的视频、帖子,加官方群询问一些不了解的地方。笔者这里建议在问问题之前最好把自己能查到的能看到的东西都看完,这样也是出于对作者的尊重,也不会让自己遭人嫌弃。

    二、语言的选择

    说个好玩的事情,笔者想写自己的项目不是一天两天了,之前也放弃过一次,那时候觉得一个项目必须做好热更新,有bug就要及时修复,还能更新出一些新玩法。但是笔者服务器的造诣尚浅,那时候没有找到如果做到lua协议热更新,如果协议不能热更新那么能更新的新功能的太少,在寻找探索的过程中也就放弃了。
    当然笔者现在还是不太会服务器罗马不是一天建成的所以此次先用c#写项目,但是我会减少对c#的依赖,等哪天搞定的服务器,就将框架移植到lua中

    三、UI插件的使用

    FGUI在Unity方面的使用主要关注的是“包”也就是Package。你如果想显示一个UI界面,首先需要找到UI界面所引用的包,将这些包加载进来(UIPackage.AddPackage),你才能看到UI的界面(UIPackage.CreateObject)。
    所以UI框架的第一个任务是需要管理Package的加载与卸载,还有Component的显示。
    那么第一份代码就是管理包

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    using FairyGUI;
    
    public class UIPackageManager : BaseManager<UIPackageManager>
    {
    
        //记录包是否Add的字典
        private Dictionary<string, bool> packageAddDict = new Dictionary<string, bool>();
    
        /// <summary>
        /// 将一个UI包add进来
        /// </summary>
        /// <param name="packageName">UI包名</param>
        public void AddPackage(string packageName)
        {
            if (CheckPackageHaveAdd(packageName) == false)
            {
                UIPackage.AddPackage("UI/"+packageName);
            }
        }
    
        /// <summary>
        /// 检查UI包是否已经包进来
        /// </summary>
        /// <param name="packageName">UI包名</param>
        public bool CheckPackageHaveAdd(string packageName)
        {
            return packageAddDict.ContainsKey(packageName);
        }
    
        /// <summary>
        /// 清理没有用到的UI包
        /// </summary>
        public void ClearNotUsePackage()
        {
            //*****************************
        }
    }

    通过一个字典来记录UI的包是否已经加载进来,笔者在想何时卸载,由于是第一款小游戏暂时先不做的那么详细(我懒),如果UI资源比较少,完全可以不卸载。也可以等applicationDidReceiveMemoryWarning过来卸载没有用到的资源,这就涉及UI界面与包的引用关系了,等我想明白再开一贴记录。
    下面第二份代码是界面的管理

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    using FairyGUI;
    
    public class DialogManager : BaseManager<DialogManager>
    {
    
        Dictionary<DialogType, BaseDialog> dialogDict = new Dictionary<DialogType, BaseDialog>();
        /// <summary>
        /// 打开界面
        /// </summary>
        public void OpenDialog(DialogType dialogType)
        {
            DialogInfo dialogInfo = DialogConfigManager.GetInstance().GetDialogInfo(dialogType);
            UIPackageManager.GetInstance().AddPackage(dialogInfo.GetPackName());
            GComponent view = UIPackage.CreateObject(dialogInfo.GetPackName(), dialogInfo.GetDialogName()) as GComponent;
            view.SetSize(GRoot.inst.width, GRoot.inst.height);
            GRoot.inst.AddChild(view);
            dialogDict[dialogType] = DialogConfigManager.GetInstance().GetDialogControl(dialogType);
            dialogDict[dialogType].SetDialogView(view);
            dialogDict[dialogType].OnBeforeCreate();
            dialogDict[dialogType].AddListener();
            dialogDict[dialogType].OnCreate();
            dialogDict[dialogType].OnRefresh();
        }
    
        /// <summary>
        /// 关闭界面
        /// </summary>
        public void CloseDialog(DialogType dialogType)
        {
            if (dialogDict.ContainsKey(dialogType))
            {
                dialogDict[dialogType].RemoveListener();
                dialogDict[dialogType].OnHide();
                dialogDict[dialogType].OnDestory();
                dialogDict[dialogType].GetView().Dispose();
                dialogDict.Remove(dialogType);
            }
        }
    
    }
    

    打开界面判断包是否加载,如果没有则加载包再打开界面
    第三份代码是UI配置的管理

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    using FairyGUI;
    
    public class DialogConfigManager : BaseManager<DialogConfigManager>
    {
    
        public Dictionary<DialogType, DialogInfo> dialogDict;
    
        public DialogConfigManager()
        {
            InitDialogConfig();
        }
    
        public void InitDialogConfig()
        {
            dialogDict = new Dictionary<DialogType, DialogInfo>();
            dialogDict[DialogType.Main] = new DialogInfo("MainUI", "Win_Main");
            dialogDict[DialogType.Farm] = new DialogInfo("FarmUI", "Win_Farm");
        }
    
        public DialogInfo GetDialogInfo(DialogType dialogType)
        {
            return dialogDict[dialogType];
        }
    
        public BaseDialog GetDialogControl(DialogType dialogType)
        {
            switch (dialogType)
            {
                case DialogType.Main:
                    return new MainUIDialog();
                case DialogType.Farm:
                    return new FramUIDialog();
                default:
                    return null;
            }
    
        }
    }
    
    
    public class DialogInfo {
    
        private string _packName;
        private string _dialogName;
    
        public DialogInfo(string packName, string dialogName)
        {
            _packName = packName;
            _dialogName = dialogName;
        }
    
        public string GetPackName()
        {
            return _packName;
        }
    
        public string GetDialogName()
        {
            return _dialogName;
        }
    
    }

    笔者的UI框架没有采用AddComponent挂脚本的方法,因为如果过度使用,未来很难移植到lua中。
    界面配置管理通过GetDialogControl拿到每一个界面对应的累,并将Component Set到类中,方便之后Find组件和控制。

    using UnityEngine;
    using System.Collections;
    using FairyGUI;
    
    public class BaseDialog {
    
        private GComponent _view;
        private DialogType _dialogType;
    
        public BaseDialog()
        {
    
        }
    
        public void SetDialogView(GComponent view)
        {
            _view = view;
        }
    
        public void SetDialogType(DialogType dialogType)
        {
            _dialogType = dialogType;
        }
    
        public GComponent GetView()
        {
            return _view;
        }
    
        /// <summary>
        /// 创建前期 主要用于寻找view上的组件
        /// </summary>
        public virtual void OnBeforeCreate()
        {
    
        }
    
        /// <summary>
        /// 添加监听事件
        /// </summary>
        public virtual void AddListener()
        {
    
        }
    
        /// <summary>
        /// 删除添加事件
        /// </summary>
        public virtual void RemoveListener()
        {
    
        }
    
        /// <summary>
        /// 创建成功 主要用于逻辑注册
        /// </summary>
        public virtual void OnCreate()
        {
    
        }
    
        /// <summary>
        /// 用于缓存界面后的第二次以上打开
        /// </summary>
        public virtual void OnRefresh()
        {
    
        }
    
        /// <summary>
        /// 界面隐藏
        /// </summary>
        public virtual void OnHide()
        {
    
        }
    
        /// <summary>
        /// 界面销毁
        /// </summary>
        public virtual void OnDestory()
        {
    
        }
    
        public void Update()
        {
    
        }
    }

    本帖只作为学习记录,只为提供一个思路,还有很多坑要去填,比如AB模式的异步加载包,包的删除管理等。

    展开全文
  • 自己写框架源码

    千次下载 热门讨论 2013-08-19 17:28:54
    自己写框架. 基础类库。 数据库访问器类库。 数据访问层基础类库。 业务逻辑层基础类库。 UI基础类库。 MEF基础类库。 View Model基础类库。 代码生成器。 工厂类库.
  • 自己动手RPC框架

    千次阅读 2019-01-13 02:08:02
    现在,自我挑战一下,动手一个RPC框架。 高能预警:本文涉及到的知识点如下 Spring Boot2:起步依赖、自动配置,让应用开发变得简单 Spring的Java Bean配置,条件注解:灵活控制注入 基于JDK接口的动态代理...

    在上一篇博客中,介绍了RPC的主要概念和实现原理,然后基于TCP协议实现了一个非常简单的RPC小案例(点此回顾)。

    现在,自我挑战一下,动手写一个RPC框架。

    高能预警:本文涉及到的知识点如下

    • Spring Boot2:起步依赖、自动配置,让应用开发变得简单
    • Spring的Java Bean配置,条件注解:灵活控制注入
    • 基于JDK接口的动态代理了解一下?):发起远程调用对服务消费者来说是透明的
    • ZooKeeper了解一下?):提供树形目录结构,节点变化函数回调
    • Netty了解一下?):高性能的网络通信
    • 自定义注解:哪些类的实例提供远程服务,又是实例的哪些属性需要注入远程服务
    • Java内置的序列化了解一下?):网络中数据以二进制的形式进行传输

    先看下效果

    1、配置文件:开启服务注册、ZK地址和连接超时时间、暴露服务端口。

    2、服务提供者:用RpcService注解说明该bean提供远程调用服务。

    3、服务消费者:RpcReference注解为此属性注入远程调用服务的代理对象。

     

    4、注册中心:服务提供者启动后,在ZK成功创建了相关节点。

    5、调用服务:成功发起了一次远程过程调用。

    嘀,开车啦!

    嗤,源码下载地址:https://download.csdn.net/download/qq_31142553/10913525

    一、原理&流程

    敲黑板讲重点!!!

    Dubbo一样,分为服务提供者、服务消费者、注册中心三个主要角色。后面将逐一进行讲解。

    镇楼图

    RPC架构流程图

     

    二、代码结构

    我们将项目分为两个模块,一个核心模块,一个测试模块。大概代码结构如下

     

    主要maven依赖

            <!-- lombok,简化实体类结构 -->
            <dependency>
    			<groupId>org.projectlombok</groupId>
    			<artifactId>lombok</artifactId>
    			<!-- <optional>true</optional> -->
    		</dependency>
    
            <!-- netty,高性能服务通信 -->
    		<dependency>
    			<groupId>io.netty</groupId>
    			<artifactId>netty-all</artifactId>
    		</dependency>
    
    		<!-- zk,注册中心 -->
    		<dependency>
    			<groupId>org.apache.zookeeper</groupId>
    			<artifactId>zookeeper</artifactId>
    			<version>3.4.12</version>
    		</dependency>

    三、角色详解

    因为基于Java Bean的配置比较灵活,所以我们建立一个全局配置类,在这里配置需要交给Spring IOC容器管理的对象。但是,如果系统不打算使用RPC服务,那就没必要加载这个配置类了。因此,我们自定义一个注解,如果在Spring Boot启动类上使用了此注解,那么此全局配置类才生效。

    1、服务提供者

    概述

    服务提供者系统启动时,如果启用了服务注册功能,就将提供服务的bean信息注册到ZooKeeper,并在内存维护一个interfaceName-bean的映射关系集合,最后在指定端口开启一个监听远程调用请求的服务。

    详解

    是否启用服务注册功能,可以从配置属性读取。采用条件注解的方式,如果启用了,就注册一个专门用于维护与ZooKeeper的连接会话的实例到IOC容器,在构造函数里面初始化它的ZK实例,并判断是否需要创建ZK的服务根节点。然后,还要注册一个RPC服务到IOC容器,这个服务在Spring容器加载完成之后,获取所有带了自定义的、表示提供远程服务的注解的bean,先将它们存到本地内存维护的一个Map集合里面,以接口全类名为key,bean实例为value,这样,远程过程调用的请求过来之后,就从这个map里面根据接口名找到对应的bean来处理了。然后,还要将这些bean实例信息放到ZK上面,以提供服务消费方去查询获取。至于存什么信息呢?首先是需要这些bean的接口全类名,然后是本机启动的监听请求服务的IP和端口。所以,在ZK服务根节点下,创建一个以接口全类名为名称的永久节点,然后创建一个临时序列子节点,以本机IP和监听端口、当前时间戳(处理一台服务器的一个接口有多个实现类的问题)命名。最后,还要启动一个Netty服务端,绑定本机的IP和端口,端口可以写到配置里面、与前文说的保持一致,添加业务处理的Handler,业务处理主要是根据请求的接口名、方法名、参数列表找到本地内存维护的map里面的服务实例,通过反射调用并返回执行结果。

    2、服务消费者

    概述

    服务启动时,从注册中心订阅(先查,后续变化自动触发更新)自己需要的服务到本地列表。方法调用时,利用代理先去本地列表查询到服务提供所在IP和端口,然后发起Netty请求,将响应作为远程调用的执行结果返回。

    详解

    首先,服务消费者系统启动时,先注册一个与ZooKeeper的连接会话的实例到IOC容器。然后,查询所有bean中带了自定义的、表示需要远程服务的注解的属性,根据它们的类型名称到ZK上面查询同名节点,存在的话获取它的所有孩子节点名称,然后保存到一个自己定义的、类似Map<String, Set<String>>结构的集合里,同时还要为类名的节点注册子节点变化监听器,触发时重新读取其子节点更新到集合里。接着,利用反射为属性赋值一个代理对象,这个代理对象在方法被调用时,将方法调用信息封装成请求参数,根据自己的类型名称到集合里面找到符合的服务提供者所在的IP和端口后发起请求,并将响应结果返回。

    四、代码说明

    由于代码量有点大,我也不知道怎么贴。就将这些类是做什么用的简单说明一下,比较关键的部分附上截图。

    推荐感兴趣的小伙伴直接去下载源码:https://download.csdn.net/download/qq_31142553/10913525

    (1)annotation包

    EnableRpcConfiguration:自定义注解,用于Spring Boot启动类上面。有此注解时,配置类RpcConfiguration才生效,系统才使用RPC功能。

    RpcReference:自定义注解,用于Spring Bean的属性上,表明此字段需要注入远程调用的代理对象。

    RpcService:自定义注解,用于Spring Bean的类上面,表明该实例提供远程调用服务。需要设置interfaces属性,指明提供哪些接口的服务。

    (2)client包

    NodeChildrenChangedWatcher:子节点变化观察者,用于服务消费者监听ZooKeeper指定节点的变化从而更新服务信息列表。

    RpcClientHandler:用于服务消费者向服务提供者发送请求并接收响应。

    RpcInjectHandler:客户端核心类,从ZooKeeper获取需要的服务信息,为带RpcReference注解的属性设置远程调用的代理对象。

     

     

    (3) common包

    RpcDecoder:Netty解码器,将字节数组转为Java对象。

    RpcEncoder:Netty编码器,将Java对象转为字节数组。

    RpcRequest:RPC请求封装类,有接口名称、方法名称、参数列表(类型和值)。

    RpcResponse:RPC结果封装类,有响应结果、异常。

    (4)conf包

    Consts:常量,有zk服务根节点 、本机IP。

     RpcConfiguration:RPC配置类,配置所有注入IOC容器的bean。

    (4)server包

    RpcServer:将提供RPC服务的bean存到本地服务列表,并注册到ZooKeeper

    RpcServerHandler:处理服务消费者的请求,反射调用本地方法,并将执行结果返回。

    ServerListener:开启Netty服务端监听。

    (5)util包

    HashMultimap:类似Google Guava的同名类,提供Map<K, Set<V>>结构的集合。

    IpUtils:获取本机IP地址。

    RpcException:RPC异常类。

    SerializationUtils:Java内置的序列化和反序列化功能。

    (6)zk包

    ZkClient:维护服务消费者与ZooKeeper的连接会话。

    ZkServer:维护服务提供者与ZooKeeper的连接会话,并创建服务根节点(需要的话)。

    后续可以考虑加入负载均衡、服务容错等功能! 

    源码下载地址:https://download.csdn.net/download/qq_31142553/10913525

    展开全文
  • 如果你想写自己的Benchmark框架

    万次阅读 2020-07-11 11:03:13
    使用过JMH的同学一定会惊叹它的神奇。JMH作为一个优秀的...作为一个有极客精神的程序员,那么有没有想过去自己实现一个Benchmark框架呢? 在实现Benchmark框架的时候有需要注意些什么问题呢?快来一起看看吧。

    简介

    使用过JMH的同学一定会惊叹它的神奇。JMH作为一个优秀的Benchmark框架带给了我们无数的欢乐。作为一个有极客精神的程序员,那么有没有想过去自己实现一个Benchmark框架呢?

    在实现Benchmark框架的时候有需要注意些什么问题呢?快来一起看看吧。

    八条军规

    这里叫军规实际上不合适,只是借用一下军规的来彰显一下气势!大家不要太介意。

    第一条军规

    工欲善其事,必先利其器。想写好一个JMH当然需要深入了解JVM的运行原理,包括JIT,C1,C2编译器和他们的分层编译原理,JIT运行时的编译优化,包括Loop unrolling, Inlining, Dead Code Elimination,
    Escape analysis, Intrinsics, Branch prediction等等。

    当然,最好是参考一下大牛们写过的JMH框架,找点灵感。

    最后大家要了解,Benchmark框架不是万能的。它只是在特定的环境中JVM的表现。

    因为在Benchmark中我们肯定是要做循环的,一般来说就是某某方法运行多少次,这种比较简单的循环。实际上,JVM运行的代码是非常复杂的。Benchmark远远不能代表JVM的全部。

    但是,见微知著,使用Benchmark还是可以一窥JVM的秘密的。

    第二条军规

    在JMH中,我们一般需要设置warmup和measurement的次数:

    @Warmup(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS)
    @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
    

    这是为什么呢?我们知道JIT中的代码是动态编译成为机器码的,并且是需要一定的时间的。

    只有JIT检测到你这是热点代码,才会对其进行优化。

    我们检测代码的性能,一般是指代码在稳定运行的环境中的情形。而不是指第一次或者前几次运行的时候,因为这个时候,这些代码可能并没有被编译成机器码。这样的出来的结果往往是和实际不相符的。

    第三条军规

    在编写Benchmark的同时,一定要开启JVM的日志。例如: -XX:+PrintCompilation, -verbose:gc等。

    为什么呢?

    大家想想benchmark是做什么的呢?就是统计时间的。

    我们希望在运行benchmark的时候,JVM不要做任何不属于运行代码的任何事情,否则就可能会影响到benchmark的准确性。

    所以开启JVM的日志就是为了做校验。不要在做benchmark的时候有其他操作。

    第四条军规

    注意JIT的分层编译。

    因为Client VM和Server VM的出现,所以在JIT中出现了两种不同的编译器,C1 for Client VM, C2 for Server VM。

    因为javac的编译只能做少量的优化,其实大量的动态优化是在JIT中做的。C2相对于C1,其优化的程度更深,更加激进。

    为了更好的提升编译效率,JVM在JDK7中引入了分层编译Tiered compilation的概念。

    对于JIT本身来说,动态编译是需要占用用户内存空间的,有可能会造成较高的延迟。

    对于Server服务器来说,因为代码要服务很多个client,所以磨刀不误砍柴工,短暂的延迟带来永久的收益,听起来是可以接受的。

    Server端的JIT编译也不是立马进行的,它可能需要收集到足够多的信息之后,才进行编译。

    而对于Client来说,延迟带来的性能影响就需要进行考虑了。和Server相比,它只进行了简单的机器码的编译。

    为了满足不同层次的编译需求,于是引入了分层编译的概念。

    大概来说分层编译可以分为三层:

    1. 第一层就是禁用C1和C2编译器,这个时候没有JIT进行。
    2. 第二层就是只开启C1编译器,因为C1编译器只会进行一些简单的JIT优化,所以这个可以应对常规情况。
    3. 第三层就是同时开启C1和C2编译器。

    在JDK7中,你可以使用下面的命令来开启分层编译:

    -XX:+TieredCompilation
    

    而在JDK8之后,恭喜你,分层编译已经是默认的选项了,不用再手动开启。

    Client编译和Server编译,甚至是OSR都是不同的。大家在写Benchmark的时候一定要注意。

    第五条军规

    注意初始化对性能的影响。

    如果需要加载类,一定要在warmup的阶段进行加载,除非你是想去测试加载的时间。否则会对测试结果有影响。

    同时也不要计算第一次print的时间,因为print也会加载和初始化一些类。

    第六条军规

    要注意反优化和重编译的影响。

    JIT在下面的几个特殊的情况下,需要对代码进行返优化:

    有些特殊的情况下面,确实是需要进行反优化的。

    下面是比较常见的情况:

    1. 需要调试的情况

    如果代码正在进行单个步骤的调试,那么之前被编译成为机器码的代码需要反优化回来,从而能够调试。

    1. 代码废弃的情况

    当一个被编译过的方法,因为种种原因不可用了,这个时候就需要将其反优化。

    1. 优化之前编译的代码

    有可能出现之前优化过的代码可能不够完美,需要重新优化的情况,这种情况下同样也需要进行反优化。

    重编译是指JIT可能会重新优化代码,导致重新编译。

    所以这条规则要求我们warmup的时间要尽可能的长。以便让JIT充分优化。

    第七条军规

    在使用benchMark得出结论之前,一定要去认真的理解JVM的底层代码(Assembly code),找到其现象的本质。

    千万不要冲动的下结论。最好是使用可视化的工具来分析。比如说jitwatch。

    最后一条军规

    在测试的时候一定要避免其他程序的影响 。

    比如说两次测试,第一次测试是单机运行,第二次测试是在有其他服务正在运行的情况下进行的。

    很显然这两次的结果是不能做比较的。我们需要多运行,剔除噪音结果。

    总结

    掌握上面几条规则,相信大家也能够写出属于自己的Benchmarks。

    本文链接:http://www.flydean.com/how-to-write-benchmarks/

    最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

    欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

    展开全文
  • 自己动手写框架(思想)

    千次阅读 2018-05-07 00:01:56
    我们每天都在用别人的框架感觉很牛逼,一大堆配置之后竟然就可以运行程序了。是不是觉得很牛逼?其实不是很复杂,只要理解框架做了什么事情,一切都变得非常容易。首先,框架一般都需要你配置一个xml文件然后获得全...

    我们每天都在用别人的框架感觉很牛逼,一大堆配置之后竟然就可以运行程序了。是不是觉得很牛逼?其实不是很复杂,只要理解框架做了什么事情,一切都变得非常容易。

    首先,框架一般都需要你配置一个xml文件


    然后获得全限定类名,或者属性,或者文本等需要的数据。xml不用多说,扩展性标签语言,曾经想取代html(超文本标签语言)

    可是没能成功,最后又想作为存储数据而存在互联网中,谁知市场上的数据库已经是非常成熟了。最终只能作为配置文件进场了。不过有时候也可以拿xml传递数据,不过json更加适用,速度快,简单化,所以我们谈到xnl只要想到是作为框架的配置文件就好了。


    package com.cszy.test;
    
    import org.dom4j.Document;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
    **获取xml配置文件关键熟悉保存到map集合中
    **/
    
    public class DomUtils {
        public static Map<String,Object> getMap() throws Exception{
            Map<String,Object> map = new HashMap<String,Object>();
            Document document = new SAXReader().read(DomUtils.class.getClassLoader().getResourceAsStream("web.xml"));
            Element elementClass = (Element) document.selectSingleNode("/Web-App/Servlet/Servlet-Class");
            Element elementUrl = (Element) document.selectSingleNode("/Web-App/Servlet-Mapping/Url-Parttrn");
            String classPath = elementClass.getText();
            String elementUrlPath = elementUrl.getText();
            map.put(elementUrlPath,classPath);
            return map;
        }
    }
    
    
    
    package com.cszy.test;
    
    import java.util.Map;
    /**返回需要的数据**/
    public class TestDemo {
        public String test() throws Exception{
            Map<String,Object> map = DomUtils.getMap();
            String classUrl = (String) map.get("/test");
           return classUrl;
        }
    
    }
    



    package com.cszy.test;
    /**被测试的方法**/
    public class TestDom {
        private void test(int i , int j){
            System.out.println("测试起来了:1+1="+(i+j));
        }
    }
    
    
    
    
    package com.cszy.test;
    
    import java.lang.reflect.Method;
    /**测试主方法,主要使用大量当时来动态调用方法**/
    public class MainTest {
        public static void main(String[] args) throws Exception{
            Class<TestDemo> clazz = TestDemo.class; //得到class类对象
            TestDemo mainTest = clazz.newInstance(); //创建实例
            Method method = clazz.getDeclaredMethod("test");
            String url = (String) method.invoke(mainTest);
            Class<?> clazz2 = Class.forName(url); 
        Method method2 = clazz2.getDeclaredMethod("test",int.class,int.class);//加载方法
            method2.setAccessible(true);//暴力反射
            method2.invoke(clazz2.newInstance(),1,1);//调用方法赋值
        }
    }
    

     
     



    展开全文
  • 自己动手Android数据库框架

    千次阅读 2016-01-23 22:18:25
    前言相信不少开发者跟我一样,每次都很烦恼自己写数据库,而且那些数据库语句也经常记不住。当然网上也有很多很好的数据库框架,你可以直接拿来用,但是 很多时候我们的项目,特别是一个小型的Andrond应用原本用到的...
  • 手写Spring框架

    万次阅读 多人点赞 2019-01-25 15:30:05
    在学习完Spring框架之后, 我们知道了 Spring容器, IOC, AOP, 事务管理, SpringMVC 这些Spring的核心内容, 也知道了它们底层实现的基本原理, 比如Spring容器就是个Map映射, IOC底层就是反射机制, AOP底层是动态代理, ...
  • 生怕自己写错了什么,误导了别人,也给自己挖了坑。这篇文章里的东西不一定完全正确,因为毕竟我也算是一个初学者,如果有谁看到了其中的失误或者错误,请及时提醒我。曾经也做过WPF的项目,拖拽控件、查找源码,用...
  • 自己动手写框架1》:缘起

    千次阅读 2015-06-04 13:07:51
    再后来,随着时间的推移,我们的软件代码得越来越多,它们中的一部分具有相当的通用性,可能就会变成一个公共库;它们其中的一部分,在整体的运行机制来说是统一的,可以抽取成公共的部分,但是有一部分又会业务性...
  • 自己动手模仿 springmvc 一个 mvc框架

    千次阅读 热门讨论 2017-05-27 10:23:09
    我觉得,完整的自己动手去实现一个,是最好的方式。 bfmvc模仿springmvc的轻量级web框架,适合学习和搭建小型web项目使用,持续更新项目地址:https://github.com/CFshuming/bfmvc感兴趣的记得star哟~目录介绍
  • 自己手写一个Mybatis框架(简化)

    千次阅读 2018-03-23 10:36:45
    MyBatis框架的核心功能其实不难,无非就是动态代理和jdbc的操作,难的是出来可扩展,高内聚,低耦合的规范的代码。本文完成的Mybatis功能比较简单,代码还有许多需要改进的地方,大家可以结合Mybatis源码去动手...
  • 曾经有人提出过一个看似天方夜谭... 既然是自己动手写框架,我这里想借鉴一下生物圈(Biosphere)这个概念来描述一下。生物圈是指地球上所有生态系统的统合整体,是地球的一个外层圈,其范围大约为海平面上下垂直约10
  • 通过matlab的卷积网络框架,然后复杂的操作比如卷积池化等通过.cu文件的, 调用GPU加速,外面的层为粗粒度的,运行的速度和TensorFlow差一个数量级,也用到 GPU加速了,怎么会慢这么多,会不会因为由于每一层...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 869,570
精华内容 347,828
关键字:

如何自己写框架