最近在用的软件

Gmail Mobile
如果要在手机上使用Gmail,要用这个.另外一个Mail For Exchange,如果要接收来自exchange的邮件就要用这个.

Prism
Mozilla的新玩意(新名字老玩意),可以把web应用做成桌面shortcut(“桌面化”–新词).如果你经常用诸如gmail,googledoc,googlereader,googleearth,flickr,youtube或其他一些web应用….可以试试

Y’z Dock
可以在xp/vista上带给你mac风格的dock.这里有很多docklet下载

Faststone Capture
Shareware,是我见过最贴心的截图工具,但有portable version…

WordPress
就是这个blog

google输入法
其实一直都是紫光的粉丝,只是一次次受打击(先是词库莫名其妙变小,一些很寻常的词居然也会找不到,后来又是莫名其妙的认为我是大舌头,- -比如我打dashetou,她会给我大色头).本来想用搜狗输入法,虽然名字很难听,可是在往没有中文支持的xp上安装时候变成乱码.最终选了这个.反正我也不在乎google和sohu的字库问题.而且用到现在觉得还不错.

写商业计划书之前要做的10件事

翻译-写商业计划书之前要做的10件事
原文

撰写计划书之前最好研究一下计划书应该包含哪些部分.

1.研究所有相关章节
开始写之前,确定你已经理解必要的章节,不同章节的目的和计划书的目标. Business Plan Pro(r)
2005之类的软件会帮助你确保不会漏掉任何章节.但如果你选择自己写,可以参考这两个网站:www.bplans.co.uk和www.businessplanhelp.co.uk,他们会帮助你全面了解每个必要的组成部分,写出令人信服的商业计划.

2.决定法律结构
尽管大多数的企业关注于”创意”或者”想法” — 这是可以理解的,但是日常执行和后勤也是不可忽视的.例如,在做贸易的时候,你要决定是单一供货商,合伙制还是有限公司.决定之前,列出当地的会计师和业务关系或者通过网站(www.startups.co.uk)研究不同选择的特点.类似的,诸如了解你的增值税义务(原文:VAT obligation),注册商标或公司名,以及起草员工合同都需要被考虑到.

3.掌握数据
无论你是否喜欢统计数据,深入地了解会影响到你业务的数据是你成功至关重要的因素,尤其是在计划阶段.开始阶段了解以下这些非常重要:
.你的启动成本
.你的盈亏平衡点
.你的资金需求
.你的之后几个月的现金流预测
免费的计算器可以帮助你计算这些数据.强烈建议你通过一个基本会计打包(原文:basic account package)建立你的业务.QuickBooks(r)
(www.intuit.co.uk) 或 Sage(r) (www.sage.co.uk)会提供这样的服务.

4.获取行业分析数据
尽管你拥有独一无二的地方,但是仍然有很多与你相似的公司存在,作一些市场调研会帮助你更好的了解你的目标市场.
所有的公司被英国政府使用标准工业划分系统(SIC)分为不同的类别;先找到你所在的类别并找到你的SIC编码.这会帮你搜索到你竞争对手和其他业界参与者的有关资料.然后通过类似Cobweb
(www.cobwebinfo.com)的数据源寻找更多的数据资料.Cobweb提供大量的商业档案资料.这会让你获得外部的视角来分析业界其他类似公司.

5.研究市场
当准备投放广告时,不如先使用www.overture.com的关键字助手看看哪些与你的业务或服务有关的关键字被搜索的最多.这会帮助你有效的投放广告或确定一个URL或者使用搜索引擎优化来优化你的网站.你也可以通过输入这些关键字到搜索引擎来找到你的竞争对手.

6.慎重评估需求水平
与估计成本不同,最难预测的事情是你的产品或提供的服务的需求水平.通常的规则是保守地估计可能的需求和使用相似取代方法.
即便是一个新的独一无二的创意也应该用相似取代来估计,而不是凭空编造数据或说自己没有可以比较的数据.一个经典例子,最近伦敦旅游发展项目的昙花一现.一个最主要的问题就是游客的数量远远低于预先估计的数量,因此入不敷出.如果负责人事先研究过英国最主要的吸引游客的地方,他们就会找到潜在游客的上限数量.由于估计的游客数量高过这个上限,这个疯狂的优化假设造成最终的失败 — 成本和收益远不成比例.

7.进入市场策略
由于竞争的激烈,企业家要慎重选择如何进入市场或如果打动客户的芳心.大多数新的公司会考虑为他们的新品牌采用多渠道进入的策略,但是这样做不仅仅成本巨大,而且比单一渠道昂贵许多.互联网营销是一个很吸引人的策略,因为营销成本容易跟踪.此外,找到当前相似市场的供应商所处的位置也可以告诉我们哪些市场活动是最有效的.当然,这些是建立在正确的数据上的.

8.雇用合适的人
除了财务方面的估计,执行力强并可以信赖的人是潜在投资者要研究的.无论企业家和创建人的技能水平如何,他常常是需要协助的.尽管很多非核心的活动是可以外包的,某些部门,例如销售,还是需要随时关注的.你应该列出所有的必要技能,把他们放到模型里定价,发现缺口并合适的候选人.

9.定义并明确客户获得的好处
许多企业家无法清楚的说出他们的所做的事能够带来的好处.因此,”电梯行销”这个词被引入到现代词汇来解决这个问题.–所谓的电梯行销是,你的创意,以及支持他的商业模型,公司方案,市场策略和竞争手段需要你在一段电梯升降的过程中表达出来.
这个简单的方法目的是让企业家用心地思考在描述他的产品或服务时如何使用语言的艺术.同时也是提醒他们要以客户为中心并确保他们集中精力描述这些”好处”.

10.找一个导师
许多的创业者会妄想他们的创意会被别人偷走,并在开始前表现的很不理性.通常,创意都是严密的保护并且只在知己讨论.但是这些”知己”(一般是家人或朋友) 通常很难提出足够具有挑战性的问题因为一来他们不愿意冒犯你,二来他们缺少相关的经验或足够的判断力去严格地分析这个新的风险.正因如此,有重大缺陷的创意可以在还没有“关键时候掉链子”的时候被及时纠正,从而可以正常地发展。强烈建议创业者在早期找一个独立的导师帮你审视你的创意。这些人可以帮你在向投资人或者银行展示之前“敲打”你的创意。最后,形成鲜明对比的是,一些创业者觉得投入越多越好,他们参加每一个商业计划竞赛来获得独立的反馈而不是获奖。

精通技术一定就是一个好的程序员???

19:44 2006-10-10 精通技术一定就是一个好的程序员. 这句话是完全错误.”好的” – 这种东西本身就是一个很模糊的概念.就算是真的大家对”好的”这个标准一样了,对”程序员”的定义又不一样.对”精通”的定义也未必一样.”程序员”的定义取决于,通常情况下,”程序员”应该具备的素质,而这些”素质”本身又存在的定义理解上的差别.因为bull shit终归还是不同的人来看的.而”精通”的概念就更不要说了,我是从来没有弄清楚过,很多时候这样的词是需要context的,可是这里的context也是含糊的–>

所以呢,唉,..

不要觉得我在玩弄概念,其实很多情况下我们是被概念玩弄,想想经常可以看到论坛或者日志的回复都是一些不知所云的家伙,要么是根本没有用大脑,要么就是没有搞清楚出发点在哪里.

这是tm扯到哪里去了.又说胡话了.
一般说”精通技术一定就是一个好的程序员.”这句话的时候,context还是确定的,所以还没有到无法讨论的地步.不过确实是”完全错误”的.首先我不会去贬低钻研技术的同志们,毕竟人个有志.所以如果有逻辑不是很清晰的同志们不要认为我在说”精通技术就一定不是一个好的程序员”或者”好的程序员不需要精通技术”.
程序员是搞技术的,当然要精通技术咯.可是要是埋头钻研技术期望做一个好程序员,那就错了.错的不靠谱.软件的主要参与者是人,好的程序员显然不是单单技术.做什么事情终归还是和其他人一起做,协作.技术高了可以抵掉一部分协作,比如如果你的效率是其他人的10倍,你当然没有必要去沟通去浪费时间去plan,document,kt…, 虽然可以这样的做,但从时间角度也是存在协作的,你的东西存在以后被别人看到,维护的可能.如果你觉得”这个我不管”,”不是我的事情”,那你不只是做不好程序员,而且是个不负责任的人(这样的人最危险),做什么事情都恐怕都不是”好的”. –这样的人”好的”定义和我不一样, 请滚.
所以对技术不要盲目崇拜,我们遇到的问题通常并不是仅仅技术一维.
这些话送给我自己,如果有人觉得有道理,那满好,如果觉得是狗p,抱歉浪费了您的时间.

这是很久之前写在msnspace里的,重新放到这里给自己…

s60上的iphone主题

s60知道吧?
iphone知道吧?
主题知道吧?

iphone-352_3tlju24u.sis

或者这里:http://mosh.nokia.com/content/3746B2586FD6DAB0E040050AEE042851

e61i新玩法 – Mobile Web Server

在e61i上搭建自己的mobile网站,然后可以用PC在任何地方连接你的e61i.可以方便的共享,只是似乎速度比较慢.

1.下载 MobileWebServer 下载
2.如果已经有装S60的Python,要先删除.然后再安装 MobileWebServer
3.需要注册一个用户,然后email验证.同时提供一个二级域名,如: zhangv.mymobilesite.net
4.用e61i连接网络,启动MobileWebServer,用之前注册的用户登录

这样就可以通过Internet访问你的手机的共享资源了.截图看这里.当然需要先登录. 你可以通过设置启动guest.如果你总是时刻都在线而又有很多有趣的东西共享给其他人.这是个不错的选择.或者你喜欢用一个web的界面来操作你的e61i,比如你把手机丢在家里而手机的webserver是启动的,那你照样可以在办公室里通过你的e61i发送短信,共享文件,查看通讯录…更牛x的是可以创建一个手机的blog,当朋友访问你的手机site的时候可以随时看到你的最新动态.

未知的问题:
1.安全性还不知道,可能现在使用无线的用户不多吧
2.在手机上运行这个webserver是不是会占用太多的资源

最近在读的书

<<少即是多>> Seth Godin

虽然这本书很”畅销书”,因为里面的152个妙想大多数都颇有启发性,至少对我. 另外很重要的一点就是他们都很短小,很适合现在大多数”沉迷”快餐文化的可怜人(包括我).

<<中国人的精神>> 辜鸿铭

认识你自己

<<丑陋的中国人>> 柏杨

第二遍,时刻提醒自己

<<5分钟和陌生人成为朋友>>

发现自己在社交方面有点问题,有点像宅男方向发展

Playin’ with E61i

  • 邮件(Email)

Mail For Exchange ->用于Exchange邮件
GmailMobile -> 收Gmail的客户端
BlackBerry Connect ->没用过还
可以通过配置imap来收gmail邮件。似乎更好

  • 无线(WIFI,WLAN)

Fring ->可以通过skype,msn,googletalk,ICQ,twitter或sip服务进行语音通话
Gizmo ->费用不详

  • 软件(Software)

ScreenSnap ->屏幕截取
Google Maps Mobile ->google地图手机版
Opera Mini ->Opera网络浏览器,还是觉得e61i自己的浏览器好用一点.有备无患.用Gmail有问题,而且速度慢
FaceWarp ->变脸,比较好玩
DivxPlayer ->视频播放器
CorePlayer ->我觉得比divx播放器好一点,不过对我来说都差不多,因为并不常用
掌上书院 ->看书的,可以收藏,添加书签,在线下载…支持图片
QReader ->更好地看书软件,速度快使用方便,界面清爽,只是不支持图片
Handy Clock ->强大的时间管理工具,包括世界时钟,世界地图,我主要用闹钟
Handy Profile ->情景模式管理,定时,自定义切换规则
Handy Taskman ->任务管理
AgileMessenger ->all in one的im工具,支持yahoo,msn,googletalk
F-Secure ->防火墙,有备无患
MobyExplorer -> 文件管理器,同时支持ftp
Resco Photo Viewer ->图片管理
Putty -> e61i连接ssh
iSkoot ->e61i上的skype客户端,通过一个本地的网关来连接skype,应该是只支付本地电话费.香港可以,目前不确定国内是否支持.到mosh下载
smart2go ->地图下载,不需要网络连接(不同于googlemap).下载了上海和北京的地图却看不到详细的街道名.
MGtalk ->开源的jabber/googletalk客户端,虽然界面不是很美观,但是因为不像fring那样的proxy client,所以要安全一些.同时还有gmail提醒功能.
Talkonaut ->很棒的im工具,支持gtalk和msn。但是不支持中文输入。
ZTA4 ->最好的输入法
MsnMessenger ->官方的移动客户端,但在香港使用有问题,国内使用GPRS正常.
MoFire -> 我自己写的在手机上发布blog的工具

  • 游戏(Game)

S-Tris2 ->俄罗斯方块
Snake ->Nokia的经典游戏,这个是3250的下载页面,可用
iNES ->FC(红白机)模拟器
vNES ->经典的symbian上fc模拟器,建议大家去买,国产的共享软件,只有25rmb。ines好像是30美刀
古墓丽影 ->还用说吗
SkyForceReloaded -> 傲气雄鹰,如果用nokia不知道这个游戏就有点土了
MicroPool -> 桌球
Chinese Chess -> 象棋,电脑有点笨,操作起来稍显麻烦。
上面的三个到s60.s80.cn下载

  • 在线(online)

GoogleReader -> Google在线rss阅读器
GoogleCalendar -> Google日历
Flickr -> 照片管理
Youtube -> 16亿,e61i内置的浏览器因为没有flash内建支持所以没有办法看

  • 关注(keep watching)

Deepfish -> 微软的mobile浏览器

  • 资源(Resources)

SymbianV3
Series60v3.com
My(and your) E61
Nokia E61 Blog
Wendong’s Smart Phone Weblog
Eseries
MOSH
推荐!
S60下载推荐

最后更新2008-2-1

AOP与OOP

(最初发布在JavaResearch.org,现在整理好放到自己的地方.)

作者:Narayanan A.R. June 15, 2005
翻译:ZhangV 2005-06-28
原文出自:DevX.com
原文链接:http://www.devx.com/Java/Article/28422/0/page/1

首先你要明确的一点,AOP和OOP是两种不同的认识事物的角度,并不是说有了AOP就不要用OOP.AOP所关注的是传统OOP不能优雅解决的问 题.(程序员通常都是完美主义者,当解决某个问题不优雅的时候,那就意味着不完美.)下面将就一个简单的例子来说明他们到底如何的不同.

作为一个使用OOP多年的人来说,当我听说AOP可以解决一些OOP一直都不能优雅地解决的问题时,我觉得应该去探个究竟了.对两种技术的比较最能给我们实际应用提供见解.这里我设计了一个例子:一个OOP应用,其中某些方面适合使用AOP.

本文展示了一个简单的例子.一开始介绍了问题域,然后分别给出传统OOP的解决方法与结合了AOP解决方法.后者使用了 JDK5.0,JUnit,和 AspectWerkz.最后我会说明如何编写代码.读完本文后,我希望你能知道AOP到底是什么,用来解决什么样的问题.

问题域描述
一个软件公司雇佣一个程序员,指定给他一个业务部门并要求他随时向经理报告.当团队成员完成他们的目标时,经理会给他们相应的奖金.公司所需要的方案必须能够增加一个新的雇员并给当前的员工增加奖金.为了方便,我们用CSV文件存储数据.


图1 解决方案模型

类Manager(经理)继承自类Employee,包含一个额外的属性,Managing Project.一个部门可能包含很多员工.多个部门构成了公司.暂不考虑公司这样的一个类,因为它在问题域之外.

解决方案设计
以下流程图描述了解决方案设计.


图2 对象之间的交互(增加一个新的员工,指派给他一个部门和经理)

出于简单的考虑,本文只关注必需的细节.你也可以深入代码得到你想要的其他信息.
下载
EmployeeServiceTestCase, 一个JUnit测试用例,模拟一个最终用户,创建新员工记录,指派部门和经理.它获取所有可用的部门和经理数据并显示在图形界面上.为了实例化域对象 BusinessUnit和Manager,获得的记录将传递给工厂类.之后,通过给EmployeeService传递一个引用来创建一个 Employee对象.这个服务类使用EmployeeFactory创建对象,并把这个对象传给EmployeeRepository 来进行持久化操作.

应用程序中需要面向哪些”Aspect”
到目前为止,对模型和设计的讨论还限于一个较抽象的层面.现在,我转向这个应用的其他方面 – 这对理解AOP的价值至关重要.

操作所需的资源

<pre lang=”java”>

public static Set findAllBusinessUnits() throws RepositoryException {
Set businessUnits = new HashSet();
try {
FileReader businessUnitFile = null;
BufferedReader bufferedBusinessUnitFile = null;
try {
businessUnitFile = new FileReader(FILE_NAME);
bufferedBusinessUnitFile = new BufferedReader(businessUnitFile);
String businessUnitRecord;
while((businessUnitRecord = bufferedBusinessUnitFile.readLine()) != null) {
BusinessUnit businessUnit = BusinessUnitFactory.createBusinessUnit(businessUnitRecord);
businessUnits.add(businessUnit);
}
} finally {
if(bufferedBusinessUnitFile != null) {
bufferedBusinessUnitFile.close();
}
if(businessUnitFile != null) {
businessUnitFile.close();
}
}
} catch(IOException ioe) {
String message = “IOError. Unable to find Business Unit records”;
logger.log(SEVERE, message, ioe);
throw new RepositoryException(message, ioe);
}

logger.log(INFO, “Manager Records returned:” + businessUnits.size());
return businessUnits;
}
</pre>

上面的代码通过FileReader和BufferedReader来读取CSV文件中的业务数据.
应用程序重复地从资源文件中取得数据然后在操作完成后释放. 我们会发现:去掉程序的这两个”Aspect”将提高代码的可读性并达到一个更好的设计,因为去掉这些”多余”的东西,剩下的代码才是这个方法真正的精 髓.这个方法的作用是读取业务单位数据.所以不应该也不需要去知道”如何获取和释放资源以及这个过程中出现的异常”这个”切面”.同样地,使用AOP处理 异常也变得不同.(后面将详细介绍)

持久层
传统的OOP使用持久化类(repository classes)来持久应用程序的持久层.即:

<coolcode lang=”java” linenum=”off”>
public class EmployeeRepository {

public static void createEmployee(Employee employee) throws RepositoryException {
//使用print writer把数据放入csv文件
}

public static String findEmployeeRecordById(String id) throws RepositoryException {
//使用file reader来获得指定id的员工数据
}

public static Employee findEmployeeById(String id) throws RepositoryException {
//使用该方法获取员工数据,Employee对象由工厂类创建
}

public static void updateEmployee(Employee employee) {
//更新员工数据
}
}
</coolcode>

类EmployeeService 使用一个EmployeeRepository给应用中相关雇员提供服务,在一个企业应用中,从域模型 (domain model)中去掉持久层代码是一种设计上的改进.模型设计者和程序员就可以关注各自的业务逻辑和持久层处理.后面你将会看到如何通过 AOP来达到这样的效果.

日志
删除用于调试的日志代码将会极大地改进代码的可读性.考虑下面的代码片断:

1.
2. public Employee createEmployee(String name,
3. String contactNumber,
4. BusinessUnit businessUnit,
5. Manager manager)
6. throws EmployeeServiceException {
7. String id = createNewEmployeeId();
8. Employee employee =
9. EmployeeFactory.createEmployee(id, name, contactNumber, businessUnit, manager);
10. try {
11. EmployeeRepository.createEmployee(employee);
12. } catch(RepositoryException re) {
13. String message = “Created employee successfully:” + employee;
14. logger.log(SEVERE, message);
15. throw new EmployeeServiceException(message, re);
16. }
17. logger.log(INFO, “Created employee successfully:” + employee);
18. return employee;
19. }

上面的代码里包含了一个致命错误和一个成功信息.输出日志这一”Aspect”同样可以移到业务模型外独立实现.

异常处理
异常处理的例子我这里不再赘述,但这节已经通过上面的代码讨论了潜在的问题.当你调用EmployeeRepository 对象的 createEmployee 方法时,你可能会得到一个RepositoryException异常.传统的解决方法是,在这个类中处理.另一种方法是,当 RepositoryException 异常被抛出时createEmployee 方法返回null,catch块中的其他逻辑可以在类外处理这一错误.
错误处理在不同的情况中也会不同.但是,通过AOP可以区分开每种情况.

图3

图3中描述了AOP方法的设计以及在一个更抽象的层次上类间的交互.你可以通过对比图1和图3来更好地理解AOP.
程序的目的是通过BusinessUnit对象读取CSV文件中的记录然后填入类BusinessUnitService 中的map.使用AOP来填充这个map有点类似后门(backdoor)方法 — 控制被委派给BusinessUnit 来读取存储介质中的记录.

AOP就是定义一些切入点(pointcut)和处理方法(advice).一个”切入点”是源代码中一个执行点.前面的例子定义了一个”切入点” — 类 BusinessUnitService中的findBusinessUnits方法.一个”处理方法”顾名思义就是当执行到某个”切入点”时的一块代 码.类BusinessUnitPersistentAspect 包括advice方法findAllBusinessUnits,该方法从存储介质中载入数据,然后使用工厂类创建BusinessUnit 对象.然后这个对象被加入map,map对象的引用通过 BusinessUnitService 对象获得.”切入点”和”处理方法”组成了所谓的”aspect”.

为了读取存储介质中的数据,OOP方法通过一个DAO类来做.而AOP中,你只要定义一个”切入点”和相应的”处理方法”来读取数据.AOP框架会以advice的形式注入代码,既可以在执行期也可以在编译期.

总而言之,当类BusinessUnitService 中的findAllBusinessUnits 方法被调用时,AOP框架会在”切入点”处注入处理方法,通过BusinessUnit 对象预先读取数据来填充map对象.这样,持久层方面的代码就可以移到业务代码之外了.

新方法里的”Aspect”

本节讨论如何用AOP为应用程序的各个”切面”建模

操作资源

类BusinessUnitPersistenceAspect 的持久方法使用了一个buffered reader.你甚至可以定义”切面”的”切面”,但为了简单,这里只关注类的查找方法.

1.
2. @Aspect(“perJVM”)
3. public class BufferedFileReaderAspect {
4.
5. @Expression(“execution(* org.javatechnocrats.aop.withaop.aspects.BusinessUnitPersistenceAspect.find*(..))”)
6. Pointcut businessUnitPersistenceAspect;
7.
8. // 其他”切入点”定义
9.
10. @Expression(“businessUnitPersistenceAspect ||
11. employeePersistenceAspect ||
12. managerPersistenceAspect”)
13. Pointcut allPersistencePointcuts;
14.
15. private Map<Class, String> fileNames;
16.
17. public BufferedFileReaderAspect() {
18. System.out.println(“BufferedFileReaderAspect created”);
19. fileNames = new HashMap<Class, String>();
20. fillFileNames();
21. }
22.
23. @Before(“allPersistencePointcuts”)
24. public void assignReader(JoinPoint joinPoint) throws Throwable {
25. System.out.println(“assignReader advice called”);
26. Object callee = joinPoint.getCallee();
27. IBufferedFileReaderConsumable bufReaderConsumable = (IBufferedFileReaderConsumable)callee;
28. Class persistenceClass = callee.getClass();
29. String fileName = fileNames.get(persistenceClass);
30. FileReader fileReader = new FileReader(fileName);
31. BufferedReader bufferedReader = new BufferedReader(fileReader);
32. bufReaderConsumable.setBufferedReader(bufferedReader);
33. }
34.
35. @AfterFinally(“allPersistencePointcuts”)
36. public void releaseReader(JoinPoint joinPoint) throws Throwable {
37. //释放buffered reader等资源
38. }
39. //其他方法
40. }

上面的代码试图为每一个方法创建”切入点”– 所有以find开头的方法.无论何时这些方法被调用,assignReader方法都会被提前执行.这里它获取被调用的类实例然后设置新建的BufferedReader.

同样地,在releaseReader 方法里,代码会预先关闭buffered reader集合.本节只解释@before和@
AfterFinally 这两个”切入点”.(以J2SE 5.0的标记定义).另外,你也可以在方面定义的xml文件中声明他们.你可以查看例程源代码中的aop.xml文件.

下载

持久化

前面提到,OOP方法使用BusinessUnit 来为应用的持久层填充Map.在下面的高亮代码中(@before一行,以及while循环代码 – 译者注),当BusinessUnitService 中的方法findAllBusinessUnits 被调用时”处理方法 “findAllBusinessUnits 也将被调用.

1.
2. @Aspect(“perJVM”)
3. public class BusinessUnitPersistenceAspect implements IBufferedFileReaderConsumable {
4.
5. private BufferedReader buffFileReader;
6.
7. @Before(“execution(Collection org.javatechnocrats.aop.withaop.BusinessUnitService.findAllBusinessUnits())”)
8. public void findAllBusinessUnits(JoinPoint joinPoint) throws Throwable {
9. System.out.println(“findAllBusinessUnits advice called”);
10. Map<String, BusinessUnit> businessUnits =
11. ((BusinessUnitService)joinPoint.getThis()).getBusinessUnits();
12. String businessUnitRecord;
13. while((businessUnitRecord = buffFileReader.readLine()) != null) {
14. BusinessUnit businessUnit = BusinessUnitFactory.createBusinessUnit(businessUnitRecord);
15. businessUnits.put(businessUnit.getId(), businessUnit);
16. }
17. }
18.
19. public void setBufferedReader(BufferedReader buffFileReader) {
20. System.out.println(“BusinessUnitPersistenceAspect.setBufferedReader called”);
21. this.buffFileReader = buffFileReader;
22. }
23.
24. public BufferedReader getBufferedReader() {
25. System.out.println(“BusinessUnitPersistenceAspect.getBufferedReader called”);
26. return this.buffFileReader;
27. }
28. }

“处理方法”从数据存储中读取记录,使用工厂类创建一个BusinessUnit实例.然后这个实例被加入到Map.该Map掌管程序的所有持久化”aspect”.

日志
本文中的例子没有包含一个完整的日志AOP解决方案.但是,它为java.lang.Object类的toString方法定义了一个”切入点”来获取类 的调试信息.因此,域中的类不需要实现toString方法.通常情况下你可能需要为每一个类都要实现toString方法.

1.
2. @Aspect(“perJVM”)
3. public class LoggingAspect {
4.
5. @Around(“execution(String org.javatechnocrats.aop.withaop..*.toString())”)
6. public Object toStringAdvice(JoinPoint joinPoint) throws Throwable {
7. System.out.println(“toStringAdvice called”);
8. String toString = (String)joinPoint.proceed();
9. Object target = joinPoint.getThis();
10. Field fields[] = target.getClass().getDeclaredFields();
11. List members = new ArrayList(fields.length + 1);
12. members.add(toString);
13. for(Field field : fields) {
14. field.setAccessible(true);
15. Object member = field.get(target);
16. members.add(field.getName() + “=” + member);
17. }
18. return members.toString();
19. }

你也可以用这个样例代码完成错误处理”切面”.

深入源代码

为了理解样例需求的OOP设计,请参看源代码并思考以下几个问题:
下载

* 首先分析oldway包中EmployeeServiceTestCase 类中的代码
* 查看testEmployeeCredit 方法
* 搞懂业务类Employee和BusinessUnit
* 学习 service,repository和factory这些概念.这些是业务驱动设计的主要概念.
* 更深入地理解oldway包中的service,repository和factory类

而AOP地理解则应该是:
* 分析newway包中EmployeeServiceTestCase 类
* 查看service,repository和factory类,基本和前一种差不多.只是你要让”处理方法”截获程序的执行流程.
* 研究aspect类学习”切入点”的定义

要执行程序,你需要做的工作:
* 下载AspectWerkz 2.0 http://aspectwerkz.codehaus.org/
* 设置以下的环境变量:
set JAVA_HOME=c:Program FilesJavajdk1.5.0
set ASPECTWERKZ_HOME=C:aw_2_0_2
set PATH=%PATH%;%ASPECTWERKZ_HOME%bin
set CLASSPATH=
C:aw_2_0_2libaspectwerkz-2.0.RC2.jar;C:aw_2_0_2libaspectwerkz-jdk5-2.0.RC2.jar; classes;C: junit3.8.1resourceslibjunit.jar
* 解压缩源代码和其他文件
* 编译Java文件,但不要编译测试用例否则你调试时会遇到一个错误.
* 进行离线调试.假设你把文件解压缩到c:aop ,类文件解压到c:aopclasses,在c:aop目录下执行以下命令:
% ASPECTWERKZ_HOME%binaspectwerkz -offline etc/aop.xml -cp classes classes
* AOP框架会修改类来注入必要的字节码
* 编译测试用例,使用JUnit运行它.

后记
当你完成了上面的这些工作,你应该有以下的领悟:
* 程序中的交叉关联
* 关于AOP中”切面”的含义
* 如何用AOP来把程序业务层中的交叉关联分离出来,使用”切入点”和”处理方法”
* OOP和AOP时在程序控制流上的不同

从本文你应该也得到一种看待实际开发的新视角.你应该有信心使用AOP来改进项目中的设计,建模,提高代码的重用性.至少,你可以开始使用AOP来处理日志,错误和持久化.

个人觉得,AOP的学习曲线相对较陡,尤其在理解定义”切入点”的句法时.理想的情况是,使用OOP来设计业务模型,使用AOP把业务模型中的交叉关联移出,从而使代码简洁并提高可读性.

AOP的一个缺点是会使调试变得困难,因为不同于OOP,程序流变的复杂了,交互是由编译期或执行期决定.我准备将来做一些自动化工具来解决这个问题.

啥是Spring

(最初发布在JavaResearch.org,现在整理好放到自己的地方.)

有人说spring aop+ spring ioc, 才~~~是spring
简单一点,是一个容器. 什么容器,容纳什么?是对象,或者说bean的容器.
那为什么叫轻量级容器呢?相对于EJB container,使用spring不需要写符合容器规范的代码,即容器不会”侵入”了你的代码.

这 个容器会提供你的应用(程序)中用到的所有对象,并对这些对象进行统一的生命周期管理和组装.在通常的开发中,我们在需要某个对象的时候只是 new MyObject(). 在Java中,这样没有什么不好,因为gc会打理好”善后”工作,是系统级的. 而用spring,在需要某个对象 时,只要向容器请求相应的对象,spring会找到并准备好这些对象并提供给你.她也会打理好”善后”工作,但是是在应用级的.
另一方面,spring还会帮助你打理对象之间的依赖关系.
比如原来的做法:

class A{
}
class B{
A a ;
public B(){ a = new A();}
}

而使用spring的做法
class A{
}
class B{
A a;
public B(){}
void setA(A a){this.a=a}
A getA(){return this.a}
}
(希望你不要单纯地认为spring会写很多代码)
但 从前一个方面,你可能觉得spring只是一个对象容器.从这里你就应该看出,spring是bean容器,因为spring需要你的类符合bean规 范:相应于每一个成员域,都需要提供setter和getter方法.spring要使用这些方法来注入依赖关系,也就是 dependence injection, 或者inversion of control. 我个人觉得还是di更容易理解,直到现在我还是要考虑 怎么去向别人很好的解释ioc.控制反转(倒转),我的理解是就如同上面的两个例子里看到的,依赖(控制)不在体现在代码逻辑里(如第一个例子),而是在 配置文件里,而在代码中我们只提供注入点(也就是setter和getter).

希望我对IoC的概念的讲解能够给你一些启发.
你 可能要问了,为什么我要这样做呢?原来的做法有什么不妥的地方么?没有什么不妥,只是两种理念而已,没有绝对的好还是不好,但我还是给你我的解释–我理 解的IoC的好处,希望有所帮助.通常在程序设计的时候,我们在需要某些功能时,会相应的去设计一些方法,然后根据OO去将方法和一成员变量组成一个类. 实际上,我们最终设计出的程序是:一组类的实例互相交互完成某个特定的任务.
除了一些核心的业务方法,以外我们还要做组装对象的工作.比如我有了 一个工厂,里面有很多机器,机器在开动时要装配相应的模具.那么在工厂的生产过程中, 首先我要有工厂,机器,模具这样三个类.然后我的”动作”有:装 配,开机.通常的做法我们要做装配,然后再去开机.而用spring,我们只是专注于开机.这样我们就把装配这个动作抽离出了核心的”生产过程”.当某些 机器改变了装配模具时,不在需要修改核心业务代码.这就是解耦.如:

public class Production{
public static void main(String[] args){
Factory factory = (Factory)BeanFactory.getBean(“factory”);
factory.launchProduction();
}
}

class Factory{
Machine machine1,machine2;
void launchProduction(){
machine1.start(); machine2.start();
}
// setters and getters
}

class Machine{
Tool tool;
void start(){
}
// setters and getters
}

在launchProduction()方法中只需要开动每台机器即可.而不需要每次都装配机器.装配的工作交给了别人.现在只要按下start按钮.生产就开始了!要是原来:

void launchProduction(){
machine1 = new MachineA();
machine1.setTool(new ToolA());
machine2 = new MachineB();
machine2.setTool(new ToolB());
machine1.start();
machine2.start();
}

这就是工作分工,是不是感觉轻松了许多?从此以后,我们都是面向构件去开发,而不需要过多地在代码中体现构件之间的依赖关系.

AOP
推荐你看一下<<effective enterprise java>>的第一章,对AOP有很清晰,易懂的解释.其实AOP并非很艰深晦涩的概念,但是从架构角度去理解她的重要性可能不是我这样的new fish一时半会儿可以领悟到的.
我这里只是想说,有些概念你要知道是怎么回事,但理解到多深,除了天赋以外更多的是经验和悟.所以不要心急.–像是在自我解嘲.
也许在不知不觉中你就使用了很多AOP的概念,比如servlet里的filter,比如在写一个command类时,给她的调用类在每次调用command时前后加上:preProcess和postProcess…
我不想解释太多,<<eej>>的解释已经足够.

Hope helps.

OSGi 技术

作者:OSGi.org
翻译:ZhangV 2006-03-13
原文出自:OSGi.org
原文链接:http://www.osgi.org/osgi_technology/index.asp?section=2

简介

OSGi 规范为网络化的服务定义了一个标准的,面向组件的计算环境.给网络设备添加OSGi服务平台,使之可以有能力在网络的任何地点管理软件组件的生命周期.组 件可以在运行期间被安装,更新或删除,无需打断设备的其他操作.软件组件是可以动态查找和使用其他组件的库或程序.软件组件可以通过购买或自行开发. OSGi联盟已经开发了许多标准的组件接口,诸如HTTP服务器,配置,日志管理,安全,用户管理,xml等等这些常用功能.可以从不同的提供商那里获得 这些即插即用的兼容实现.

软件组件体系正面临一个日益凸现的问题:大量需要开发和维护的配置.而标准化的OSGi组件体系极大的简化了这个配置过程.

框架
OSGi规范的核心组件是OSGi框架.他为应用提供了一个被称为包捆(bundle)标准环境.OSGi包括这样四层:
L0.执行环境
L1.模块
L2.生命周期管理
L3.服务注册表
此外还包含一个安全系统.

执行环境就是Java环境.J2SE,CDC,CLDC,MIDP等都是合法的执行环境.OSGi同时根据核心定义(foundation profile)和一个最简版本制定了一个标准的执行环境.
模块层定义了类装载策略.OSGi框架是一个强大的类装载模型.以Java为基础但加入了模块化的思想.在Java中,只有一个包含了所有的可用类和资源类路径.OSGi的模块层还为一个模块提供了私有类以及模块之间的连接.
生命周期层将包捆动态地安装,启动,停止,更新和卸载,包捆依赖于模块层的类装载但提供了一套API来在运行期管理所有的模块.扩展的依赖机制用于确保正确模块依赖关系.
服 务注册表为包捆提供一个互操作模型实现动态性.包捆可以通过传统的类共享来互操作,但是类共享在当动态安装和卸载代码时会表现得很不稳定.服务注册表提供 了一个易于理解的模型来在包捆之间共享对象.大量的事件被定义于处理服务之间的交互.服务如同Java对象一样,可以代表任何事物.许多服务和对象是一样 的,像http服务器,服务就是现实中的一个对象,比如一个附近的蓝牙电话.

安全是建立在Java和Java2安全模型之上.语言级的限 制避免了许多可能出现的隐患(The language by design limits many possible constructs). 比 如,病毒常用的缓冲区溢出是不可能的.访问修饰符可以限制代码的可见性.OSGi通过”允许私有类”扩展了这一模型,在标准Java中不包含这种机制. Java2安全模型提供一个易理解的模型来检查代码对资源的访问权限.OSGi加入了完全的对访问请求动态管理.

标准服务

在框架之上,OSGi联盟制定了许多服务.服务由一个Java接口定义.包捆可以实现这个接口并把实现注册到服务注册表.服务的用户可以从服务注册表中找到他,或者对服务的加入或取消做出反应.
以下各部分给出OSGi release 3服务的一个简单介绍.更多资料可以找OSGi服务平台release 3的书籍或PDF下载.要注意每个服务都是先被抽象地定义然后由不同厂商独立实现.

框架服务

OSGi 框架提供一个权限管理服务(permission admin service ),一个包管理服务(package admin servie),和一 个启动级别服务(start level service).这些服务是可选的 and direct the orperation of the Framework(不知道怎么译).
• 访问管理(Permission Admin) – 当前或将来的包捆的访问权限可以通过这个服务来操作.
• 包管理(Package Admin) – 包捆之间共享类和资源.包捆的更新可能需要系统重新更新包捆之间的依赖关系.该服务提供系统实际包的共享状态并刷新共享的包.如,取消或者重新计算依赖关系.
• 启动级别(Start Level) – 启动级别是一个包捆的集合,这个集合中的包捆必须一同运行或者要在其他服务启动之前初始化.启动级别服务设置当前的启动级别,制定某个包捆的启动级别,查看当前设置.

系统服务

系 统服务提供横向功能(horizontal function),这些在每个真实的系统中都是存在的.比较常见的有,日志服务 (Log Service),配置管理服务(Configuration Admin Service),设备访问服务 (Device Access Service),用户管理服务(User Admin SErvice),IO连接服务 (IO Connector Service)和参数选择服务(Preferences Service).
• 日志服务 – 信息,警告,调试信息的纪录,或者处理错误.他接收日志纪录信息然后分配他们给其他订阅了这些信息的包捆
• 配置管理服务 – 该服务提供一个易伸缩的动态模型来设置和获得配置信息
• 设备访问服务 – 设备访问是配置一个驱动器到一个新设备并自动下载实现该驱动器的包捆的机制
• 用户管理服务 – 该服务使用一个用户信息数据库(私有和公有)来鉴权和授权.
• IO连接服务 – 实现了CDC/CLDC的javax.microedition.io包作为一个服务.该服务允许包捆提供新的,可选协议方案.
• 参数选择服务 – 提供属性数据库的访问.和Windows的注册表或Java的Preferences类.

协议服务
OSGi联盟定义了以下外部协议服务:
• Http服务 – 一个servlet容器.包捆可以提供servlet.OSGi的动态更新机制服务平台使得Http服务变得非常诱人,加入新的servlet而不需要重启.

• UPnp 服务 – 通用即插即用(Universal Plug and Play)是一个正在兴起的用于用户电子设备的标准,OSGi UPnP 将一个 UPnP网络设备映射到服务注册表.或者,将一个服务映射到UPnP网络(该服务在release 3中被推荐).
• Jini服务 – Jini是一个网络协议,用于在网络上发现Jini服务并下载执行.(该服务在release 3中被推荐).

其他服务
• 关联管理服务(Wire Admin Service) – 通常包捆会自己建立查找服务的规则.但是在很多情况下,这是一个发布时需要考虑的问题.因此关联管理服务会通过一个配置文件把不同的服务连接起来.使用消费者和生产者的概念来达到对象之间的互操作.
• XML解析服务 – 允许一个包捆定位一个解析器并使用相应的属性.与JAXP兼容.

结论
OSGi规范的适用范围很广.因为它通过一个很简单的层使得同一个虚拟机的Java组件高效率的交互.通过一个扩展的安全模型来使组件运行在一个安全的环境中.通过恰当的访问限制,组件可以被重用和组合.OSGi 框架还提供了一个扩展的部署机制来让这种交互可行,安全.

各 个领域构建在OSGi之上的中间件的大量出现,这就给OSGi软件组件创造了一个很大的软件市场. The rigid definition of the OSGi Service Platform enables components that can run on a variety of devices, from very small to very big.

采用OSGi规范可以降低软件开发成本,同时提供新的商业机会.

进一步阅读
OSGi Service Platform, Release 3下载:
http://www.osgi.org/osgi_technology/download_specs2.asp?section=2
或买书:
https://secure.inventures.com/osgi/sales/R3Book_order_form.asp

OSGi联盟的技术白皮书:
http://www.osgi.org/documents/osgi_technology/osgi-sp-overview.pdf
更深入介绍OSGi的白板白皮书(whiteboard whitepaper):
http://www.osgi.org/documents/osgi_technology/whiteboard.pdf