您的位置 首页 java

「每天一个知识点」教你如何写框架

天才程序员去创造工具,大众程序员去使用工具, 我想大部分人都处于”使用” 这个层次。

那些创造了语言、系统、工具、框架的程序员是我们崇拜的对象,也是我们努力奋斗的目标, 希望有一天我们也能像他们那样, 攀上代码的高峰, 会当凌绝顶, 一览众山小

创造是一件很难的事情,但是模仿却简单的多, 今天聊一点框架相关的知识,那些想自己写框架的,想重复造轮子的同学可以看看。

别误会,我说的是重复造轮子,不是重复发明轮子。 重复造轮子能让你体会一下创造者的艰辛和快乐,提升一下自己的内功和境界。

所谓的框架,和工具不同, 工具拿过来直接可用, 而框架只是个半成品。 换句话说就是大牛写的框架代码,加上我们写的代码,才能形成一个系统,才能运行起来。

你想一想,单独的Struts, Spring ,Hibernate能运行吗? 肯定不行吧。框架是个半成品(但不是残次品), 我们要想用起来,非得自己填上代码不可。

这就有点难搞了,那些大牛们写框架的时候得考虑用户怎么配合才行, 所以得定义好边界, 哪些是框架的任务,哪些是程序员应该做的扩展。 我们想修改框架的东西,门儿都没有,对修改完全封闭。 但是框架又提供了一些地方让程序员扩展, 这就是著名的面向对象设计的原则之一: Open-Close原则

模板方法

想达成这个目标,最容易的方式就是”继承”, 在Java世界常用的就是 抽象类

抽象类有这样的好处:

1. 没法实例化去执行(符合框架半成品的特点)

2. 可以被继承, 抽象方法需要使用者去实现。

3. 可以在抽象类中写代码,写框架相关的代码, 还可以调用抽象方法。

完美达到了Open-Close原则, 举个例子会看得更加清楚一些。

假设你要写一个MVC的框架, 你希望定义一个抽象类AbstractAction,把一些框架应该做的事封装起来,比如抽取HttpRequest的参数,形成一个Map 以便传递给具体的Action使用,这些操作和步骤是子类不能修改的 — Close

虽然是封闭的, 但是框架的使用者却可以去继承这类,实现那个抽象的execute 方法, 放置自己的业务代码。 —Open

当然它除了实现自己的代码之外,没法修改AbstractAction中的任何东西, 或者说,对超类一无所知。 — 又是Close

这样一来,你的框架就得到了这个效果: Don’t call me , I’ll call you (别打电话找我,我会去找你的)(注: 这就是Struts1 背后的思想)

反射+声明+约定

上面的方法看起来很美, 但是有个巨大的问题,就是对客户侵入性太强。

表现在两个方面:

(1) 子类(业务类)很不自由, 被迫继承一个它不想继承的类

(2) 难于做单元测试,你也许注意到了, AbstractAction 其实是依赖HttpRequest, 和HttpResponse的,这两个对象一般需要web 容器跑起来才能得到。

很容易想到, 如果业务类是一个普通的 POJO 多好:

如果我不说,估计你会以为这是一个普通的 java class , 实际上,它就是一个普通java class。

它虽然叫做LoginAction , 但是和框架一毛钱关系也没有, 毕竟它啥也没有继承, 你的框架怎么知道它就是一个潜在的Action 类?这时候需要一点点声明性的工作, 告诉框架,这是一个Action 类, 声明可以用xml ,也可以用注解,例如用xml声明的话,使用框架的程序员需要这么做

这时候框架通过解析XML就会知道: 奥,这是一个Action类,让我把它创建起来吧!怎么创建? 没看到配置文件中的类名吗,java 反射出马,轻松搞定。

接下来的问题是:怎么把Http Reqeust 中的参数怎么传递给这个类? 还是用反射!

看到LoginAction 的set username 和 setPassword没有, 框架和使用者约定好这么办:如果从浏览器传递到服务器的的参数是username=liuxin&password=123456, 那你框架应该做的事情就是调用

setUsername(“liuxin”) , setPassword(“123456”)

框架和使用者还可以再增加一个约定: 调用了setXXX方法以后,就去调用exectue 方法,这是个真正的业务方法。

如果觉得这样的约定太强, 还可以采用声明的方式:

(注:这其实就是strut2背后的思想)

如果你讨厌繁琐的xml, 现在Java提供了另外一种强大的武器: Java 注解

Java注解能够让你在源代码中添加一些”元数据”, 为一个类或者方法的增加一些”额外”的信息。作为框架开发者, 你需要给使用者提供上图中用到的几个注解

@Action 用来表明这是一个Action 类

@RequestMapping 表明如果用户通过浏览器访问/login , 那这个excute 方法就会被执行。

还要加上这么一个约定 : 如果用户访问的是/login?username=liuxin&password=123456的话那么execute 方法的 username和password 两个参数将会绑定到值”liuxin” 和 “123456”

有了这些注解和约定,你的框架就能找到程序员写的Action 类,并且直到如何调用方法, 如何传递参数了。(注:这其实就是spring mvc背后的思想)

文章来源:智云一二三科技

文章标题:「每天一个知识点」教你如何写框架

文章地址:https://www.zhihuclub.com/191669.shtml

关于作者: 智云科技

热门文章

网站地图