Hasor:在简化开发上的设计
首先引用Wiki的介绍一下Hasor:
原则:引用Wiki 简单、清晰、可靠、方便、快捷,可以说是Hasor在设计所有模块时的目标。Hasor从现在到未来都会遵循下面这些原则。 在Hasor是一系列项目的组合,其中hasor的生命周期管理是由hasor-core提供。后面链接的这篇文章详细介绍了hasor提供的模块生命周期管理以及启动过程,http://my.oschina.net/u/1166271/blog/143873。 前言: hasor的核心是由hasor-core提供,它主要负责Settings、Context、Binder三个部分的功能支持。以及hasor模块生命周期支持。根据hasor所遵循的单一职责,所有hasor预期被设计的功能都被分割到不同的模块中。这些模块有些已经完成开发等待第二次重构,有些则只是处于规划状态或是开发到一半的状态。根据体系规划图来看hasor的设计还是很大的。对于波及面这么广的框架hasor应该如何架构,这显得尤其重要。 首先Hasor采用的是模块化设计;通过分割模块将不同功能彼此隔离起来。同时考虑到,这些功能不见得都会在项目中派上用场因此模块的设计要做到绝对隔离。这样开发者在选择模块时就会减少很多麻烦。对于项目而言物理级别的分割,可以有效的帮助项目开发者改造不符合要求的模块或者仿造一个相似功能的模块。能做到这一点也正因为Hasor的模块可以被分割的粒度很小,也够整体化。从而避免“牵一发而动全身”的现象。 其次Hasor的模块设计被要求尽量面向接口,这样做的好处之一是即使有一天不在使用Hasor作为项目核心支持只要重新实现相关接口就能将原有项目重新运行起来。此外Hasor面向接口的设计还可以用来通过Hasor来桥接服务的不同实现,或者切换提供者。下一段内容就会讲解到hasor-cache是如何实现这种思想的。 ICache是如何桥接生产着消费者的? 在上面这张图中Cache和@NeedCache是hasor-cache模块面向应用程序提供的两个接口。它们分别以接口和注解形式体现。App Code代表需要使用缓存服务的程序代码段,这段代码可以通过@NeedCache方式或者直接调用Cache接口方式获得hasor-cache模块提供的缓存服务。而Cache接口的实现可以是由不同的提供者提供,通过实现Cache接口可以轻松的将应用程序使用的缓存服务替换成为其他缓存提供商。在一个恰当的设计中即使更换缓存服务提供商也可以不修改任何代码(通过代理Cache并且利用Hasor的动态配置载入监听器实现)。下面先看一下示例代码。 //下面两个类分别定义了MapCache、AuthSessionCache两个不同的缓存服务提供商。其中MapCache是作为默认缓存提供商 //在实际项目中,我们可以采用诸如OSCache、Cache4j等这样的缓存框架来提供服务,对于稍大一点的项目可以换成分布式缓存框架提供缓存。 @DefaultCache @CacheDefine(value = "MapCache" ......) public class MapCache<T> implements Cache<T> { .... } @CacheDefine(value = "AuthSessionCache" ...... ) public class AuthSessionMapCache<T>implements Cache<T> { ...... } /*下面这段代码是Cache接口的完整定义。*/ public interface Cache<T> { /**初始化Cache*/ public void initCache(AppContext appContext); /**销毁Cache*/ public void destroy(AppContext appContext); /**将一个对象放入缓存。*/ public boolean toCache(String key,T value); /**将一个对象放入缓存。*/ public boolean toCache(String key,T value,long timeout); /**根据key从缓存中获取缓存对象。*/ public T fromCache(String key); /**判断缓存中是否有要求的对象。*/ public boolean hasCache(String key); /**删除某个缓存的内容*/ public boolean remove(String key); /**刷新指定key的缓存时间*/ public boolean refreshCache(String key); /**清空缓存*/ public boolean clear(); } 然后可以通过下面两种方式获取MapCache、AuthSessionCache缓存接口。
方式1:(通过代码片段) AppContext appContext=... String cacheName = "MapCache" or "AuthSessionCache" CacheManager cacheManager = appContext.getInstance(CacheManager.class); Cache authSessionCache = cacheManager.getCache(cacheName); 方式2:(通过Guice注入) public class InternalSecurityContext{ @Named("MapCache" or "AuthSessionCache") private Cache cacheService = null; ...... }当然直接使用Cache接口固然可以利用到Cache服务的众多功能,但是往往在实际项目中我们仅仅想将结果缓存。hasor-cache的设计可以更简单的让你使用Cache服务。见下面代码:
@NeedCache(cacheName="MapCache" or "AuthSessionCache") public String foo(String param1,int param2){ return index++; } //使用默认缓存,还记得上面定义的默认缓存了么? @NeedCache() public String foo(String param1,int param2){ return index++; }如果仅仅缓存结果那么上面这种使用方式更加贴心,Hasor提供一种扩展的方式帮助你处理不同类型参数如何取得指纹。您可能要问为什么要对参数取指纹,这是由于Cache的key是字符串格式。它不支持对象,所以任何使用这种方式缓存对象时候都面临取得参数特征。哪怕你现在已经取得了Cache接口也会面临上述问题。 使用注解声明Cache这种方式不仅为我们剩下繁琐的代码,而且可以让应用程序可缓存服务接口进行隔离。即使您项目在后续维护中不打算使用hasor-cache作为缓存支持,那么在换做其他缓存框架时任然可以通过Aop监控@NeedCache重新将程序的缓存功能支撑起来。这也是hasor最小化入侵的一个体现。 这种思想在Hasor中有很多实例,权限控制、事件支持等都有缩影。 综述 在实际开发中我们经常会遇到需要(权限、缓存、Ioc/Aop、MVC、模板、上传下载、数据源、远程调用)等等格式各样的功能需求。同时在软件发展这么多年的今天,也不见得谁可以直接提供一个功能完备的体系结构或者框架出来。我们都是跟着需求走、跟着行业发展前进。正所谓“没有银弹”。既然如此,那么作为设计能提供一些什么可以共开发者反复不断的使用就成了设计本身要考虑的事情之一。 Hasor并没有走框架整合路线,他只是坚持最简化原则设计Api。并且在服务提供者和开发者之间建立一个友好的界面。 说一点Hasor的历史希望对正在设计自己框架的人有所帮助。在开发Hasor之前我已经做了有将近5年架构设计。在这几年中我一直在尝试打造一款全能的可以和.Net这样平台所比拟的平台框架。但是随着开发的进行和实践。我越来越发现凡是以(功能完备、完美整合、全面支持)这样目的设计最后都走进了死胡同。 其主要原因来自于以下两个方面:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |