﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-耐心无止境 成功一瞬间</title><link>http://www.blogjava.net/jhyan/</link><description /><language>zh-cn</language><lastBuildDate>Tue, 12 May 2026 21:38:22 GMT</lastBuildDate><pubDate>Tue, 12 May 2026 21:38:22 GMT</pubDate><ttl>60</ttl><item><title>linux 下netbeans不能使用调试功能；tomcat shutdown出现拒绝链接（connection refused）提示</title><link>http://www.blogjava.net/jhyan/archive/2009/06/18/282969.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Thu, 18 Jun 2009 00:56:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2009/06/18/282969.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/282969.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2009/06/18/282969.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/282969.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/282969.html</trackback:ping><description><![CDATA[<br />
<br />
安装了fedora11 和netbeans 6.7rc2后，发现不能使用调试功能，提示拒绝链接；<br />
<br />
同样，启动tomcat后可以正常访问web应用，但停止tomcat时却提示拒绝链接，提示信息如下：<br />
<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">2009</span><span style="color: #000000;">-</span><span style="color: #000000;">6</span><span style="color: #000000;">-</span><span style="color: #000000;">17</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">9</span><span style="color: #000000;">:</span><span style="color: #000000;">53</span><span style="color: #000000;">:</span><span style="color: #000000;">03</span><span style="color: #000000;">&nbsp;org.apache.catalina.connector.Connector&nbsp;pause<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">严重:&nbsp;Protocol&nbsp;handler&nbsp;pause&nbsp;failed<br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">java.net.ConnectException:&nbsp;Connection&nbsp;refused<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.PlainSocketImpl.socketConnect(Native&nbsp;Method)<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:</span><span style="color: #000000;">333</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:</span><span style="color: #000000;">195</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.PlainSocketImpl.connect(PlainSocketImpl.java:</span><span style="color: #000000;">182</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.SocksSocketImpl.connect(SocksSocketImpl.java:</span><span style="color: #000000;">366</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.Socket.connect(Socket.java:</span><span style="color: #000000;">519</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.Socket.connect(Socket.java:</span><span style="color: #000000;">469</span><span style="color: #000000;">)</span></div>
上述问题都是同一原因造成的。<br />
<br />
<br />
经过调试tomcat发现，tomcat在停止的时候链接的是［计算机名：8009］；而我的计算机名称是［ylhome.com］，由于我没有在hosts里面配置［ylhome.com］，导致被解析成了外网地址［75.125.148.76］，所以tomcat在停止时候无法链接该地址的8009端口。<br />
<br />
<br />
我修改hosts使得计算机名映射到127.0.0.1后，netbeans调试功能和tomcat的停止都正常了。<br />
<br />
当然大家也可以把计算机名字修改为localhost,该名称一般会自动加入hosts的。<br />
<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/jhyan/aggbug/282969.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2009-06-18 08:56 <a href="http://www.blogjava.net/jhyan/archive/2009/06/18/282969.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux下安装VPN客户端</title><link>http://www.blogjava.net/jhyan/archive/2009/04/26/267553.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Sun, 26 Apr 2009 04:21:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2009/04/26/267553.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/267553.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2009/04/26/267553.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/267553.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/267553.html</trackback:ping><description><![CDATA[<br />
<br />
1. 安装 pptp,pptpconfig<br />
<br />
命令：<br />
<br />
＃yum install pptp<br />
<br />
# rpm -Uvh <a href="http://pptpclient.sourceforge.net/yum/stable/fc6/pptp-release-current.noarch.rpm" target="_blank">http://pptpclient.sourceforge.net/yum/stable/fc6/pptp-release-current.noarch.rpm</a><br />
# yum --enablerepo=pptp-stable install pptpconfig<br />
<br />
2.<br />
&nbsp;启动pptp config<br />
<br />
在第2个标签页里面的routing style,默认所client to LAN。<br />
<br />
实现到内网的连接可以选择如下两种方式：<br />
<br />
a. 简单的做法:把routing style 设置为all to tunnel<br />
b.routing style 为默认，添加routes<br />
<br />
&nbsp;&nbsp;&nbsp; 点击 &#8220;Edit Network Routes...&#8221;，添加routes。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 比如公司内网是192.168.1.0/24<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 就添加192.168.1.0/24,下面的name无所谓了．<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ok之后点start就自动进行连接了，连接后即可从本机访问到公司内网<br />
<br />
<br />
<img src ="http://www.blogjava.net/jhyan/aggbug/267553.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2009-04-26 12:21 <a href="http://www.blogjava.net/jhyan/archive/2009/04/26/267553.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>值得思考的问题</title><link>http://www.blogjava.net/jhyan/archive/2009/03/25/261854.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Wed, 25 Mar 2009 06:25:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2009/03/25/261854.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/261854.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2009/03/25/261854.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/261854.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/261854.html</trackback:ping><description><![CDATA[<br />
<br />
在jdon上看了一个帖子，感受颇深，有一种&#8220;一语惊醒梦中人&#8221;的感觉。<br />
<br />
我们为什么选择spring（或者其他框架），为什么出现了IOC,AOP,ORM等等？简单回答是&#8220;解决问题&#8221;，但他们解决不同的问题。<br />
<br />
需要继续思考一下，希望能有所&#8220;突破&#8221;<br />
<br />
参考url：http://www.jdon.com/jivejdon/thread/35373.html<br />
<br />
<br />
防止断链，转载如下：<br />
<br />
<fieldset><legend title="转载内容">转载内容</legend><span class="tpc_content"><br />
一晃眼搞了7、8年的企业应用管理和研究，各种技术、思想翻来覆去折腾了很久，最近总算是有点持拨云见目的感觉了，于是放出点大标题和各位论论道。<br />
<br />
主要观点其实在一年半前，已经在jdon首发的文章&#8220;坚持发扬<a id="id_http://www.jdon.com/jivejdon/key/ejb" class="hotkeys ajax_query=EJB" href="http://www.jdon.com/jivejdon/key/ejb" _counted="undefined" ajaxid="query=EJB" framewidth="350" frameheight="undefined" _eventid="25"><strong>EJB</strong></a>、Spring的光辉思想，将组件化进行到底！&#8221;(可参 http://www.jdon.com/jivejdon/thread/31834.html)进行过论述。当时虽然观点比较激烈，然实际上笔者领悟得不够深刻，故有后面一年多的RoR和PHP之实践。随着时间的推移，与各相关方(上级领导、企业领导、用户、开发商主管、设计人员、开发人员、维护人员等等)的更多观点接触，让我逐渐深入领悟了Java和<a id="id_http://www.jdon.com/dl/best/spring.htm" class="hotkeys ajax_query=Spring" href="http://www.jdon.com/dl/best/spring.htm" _counted="undefined" ajaxid="query=Spring" framewidth="350" frameheight="undefined" _eventid="26"><strong>Spring</strong></a>所蕴含的开发哲学和思想，于是又有此文。<br />
(上文刚刚收到blog，由于是老文，不再发布了，仅作为整理收录)<br />
<br />
如果说，每种编程语言和技术都有自己的目标和归宿和话，那么简单来说，JavaEE和后来的<a id="id_http://www.jdon.com/dl/best/spring.htm" class="hotkeys ajax_query=Spring" href="http://www.jdon.com/dl/best/spring.htm" _counted="undefined" ajaxid="query=Spring" framewidth="350" frameheight="undefined" _eventid="27"><strong>Spring</strong></a>是为企业应用而生的。他们诞生的基本目标，正是为了解决困扰企业应用多年的各种复杂问题。故而他们能够达到现在的领导地位，并将一直延续下去。<br />
<br />
世间各种事业，都应该是&#8220;统一规划，分步实施&#8221;。放到信息工程来说，就是&#8220;自顶向下设计，自底向上实现&#8221;。道理谁都明白，可现实当中执行下来，总是要走样。问题就在于，这二者该如何结合？于是实际项目中，企业用户、分析师、设计师、程序员、维护人员总是不欢而散，最后往往各行其事，一盘散乱。上层的总是抱怨下层在&#8220;乱搞&#8221;，而下层则嘲笑上层只会&#8220;空谈&#8221;。结果往往是早已扔进档案袋的系统方案和图表，一堆各种公司、各种程序的&#8220;系统&#8221;，蒙头蒙脑瞎忙的维护人员。<br />
<br />
那为什么结合不了？因为大家没有&#8220;共同语言&#8221;。开初UML跳出来了，分析师讲得头头是道，程序员看得心烦意乱，用户更是云山雾水。于是连MF都有点烦了，干脆推起了RoR。这乍东西一看太理想了。几乎是分析员可以直接实现程序，而程序员也可以直接分析了。可惜世间难有完美的事物，RoR这种过于&#8220; 霸道&#8221;的东西也许还是有问题的。前有foxpro，后有VB、PB，也许是笔者总是心有余悸，对这种过于&#8220;完美&#8221;的东西还是先放一放吧。<br />
<br />
那是不是说，大家真的不可能有&#8220;共同语言&#8221;？笔者以为，有，但要折衷(又闻到了实用中庸主义的味道了吧)。如题，OO、DI、AOP、TDD和Refector正是当前的解决之道。<br />
<br />
OO是根本，可以作为基本的&#8220;共同语言&#8221;。图表不必要像UML那么复杂，否则最后除了分析师谁都不会看。只需要简单建上模型，标上属性和接口功能，最多连几根线说明相互关系，这样大家都懂(也就是说，这个类是个什么东西，有什么属性，要实现些什么功能)。这种东西既可做系统说明书，也可以给开发人员，甚至生成Doc做维护文档。<br />
大家要说这不是&#8220;空谈&#8221;吗？要的就是空谈(就好比不识字的老百姓也会谈治国问题)，就是只谈&#8220;有什么&#8221;和&#8220;做什么&#8221;，这样才能有共识。但这种&#8220;空谈&#8221;其实最难最费时，因为要&#8220;共识&#8221;。有了共识之后就可以下一步了。<br />
<br />
下一步是实现。这个阶段，分层、DI、AOP就可以大展本领了。Spring流行那会，大家是言必DI和<a id="id_http://www.jdon.com/jivejdon/key/aop" class="hotkeys ajax_query=AOP" href="http://www.jdon.com/jivejdon/key/aop" _counted="undefined" ajaxid="query=AOP" framewidth="350" frameheight="undefined" _eventid="28"><strong>AOP</strong></a>。可惜风头一过，现在RoR和 <a id="id_http://www.jdon.com/jivejdon/query/taggedThreadList.shtml?tagID=373" class="hotkeys ajax_query=Seam" href="http://www.jdon.com/jivejdon/query/taggedThreadList.shtml?tagID=373" _counted="undefined" ajaxid="query=Seam" framewidth="350" frameheight="undefined" _eventid="29"><strong>Seam</strong></a>时尚年代，很多人大概忘了七七八八。其实笔者现在看来，分层、DI和<a id="id_http://www.jdon.com/jivejdon/key/aop" class="hotkeys ajax_query=AOP" href="http://www.jdon.com/jivejdon/key/aop" _counted="undefined" ajaxid="query=AOP" framewidth="350" frameheight="undefined" _eventid="30"><strong>AOP</strong></a>是继<a id="id_http://www.jdon.com/jivejdon/query/searchThreadAction.shtml?query=%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1&amp;view=on" class="hotkeys ajax_query=OO" href="http://www.jdon.com/jivejdon/query/searchThreadAction.shtml?query=%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1&amp;view=on" _counted="undefined" ajaxid="query=OO" framewidth="350" frameheight="undefined" _eventid="31"><strong>OO</strong></a>之后最重要的思想，它们的核心在于&#8220;接口和实现分离&#8221;。这样一来，就可以把&#8220;做什么&#8221;和&#8220;怎么做&#8221;分家，这才是它们的伟大之处。大家天天把&#8220;高内聚、低耦合&#8221;挂在嘴边，各搞一套，乱七八糟。J2EE太复杂，大家觉得用不上。好不容易Rod推行了用得上的标准方法，大家本可以有&#8220;共同语言&#8221;了。可惜人之天生的惰性又把我们推回到&#8220;一体化&#8221;的泥潭，一代代程序员和系统就这么不了了之了。<br />
<br />
OO还是要坚持，它是当前信息世界和现实世界实现映射的最好方法。DI和<a id="id_http://www.jdon.com/jivejdon/key/aop" class="hotkeys ajax_query=AOP" href="http://www.jdon.com/jivejdon/key/aop" _counted="undefined" ajaxid="query=AOP" framewidth="350" frameheight="undefined" _eventid="32"><strong>AOP</strong></a>也是要坚持，只有这样才能屏蔽掉具体实现技术疯狂变化的信息世界。坚持<a id="id_http://www.jdon.com/jivejdon/query/searchThreadAction.shtml?query=%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1&amp;view=on" class="hotkeys ajax_query=OO" href="http://www.jdon.com/jivejdon/query/searchThreadAction.shtml?query=%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1&amp;view=on" _counted="undefined" ajaxid="query=OO" framewidth="350" frameheight="undefined" _eventid="33"><strong>OO</strong></a>，我们才能不受数据存储方式变化的困扰；坚持分层、ID、AOP，我们才能明确地分工合作，摆脱系统规模和事务要求变化所带来的烦恼。<br />
<br />
最后还有TDD和Refactor，业务在变，系统在变，我们的技术也在变。一定要能测试和重构，要能很好地测试和重构，否则系统必被变化所毁。要想能够很好地测试和重构，如果你的系统没有<a id="id_http://www.jdon.com/jivejdon/query/searchThreadAction.shtml?query=%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1&amp;view=on" class="hotkeys ajax_query=OO" href="http://www.jdon.com/jivejdon/query/searchThreadAction.shtml?query=%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1&amp;view=on" _counted="undefined" ajaxid="query=OO" framewidth="350" frameheight="undefined" _eventid="34"><strong>OO</strong></a>、分层、DI、AOP，大家是否真可以充满底气地回答&#8220;能&#8221;。在这一个问题上，Java是最令我放心的伙伴，而<a id="id_http://www.jdon.com/dl/best/spring.htm" class="hotkeys ajax_query=Spring" href="http://www.jdon.com/dl/best/spring.htm" _counted="undefined" ajaxid="query=Spring" framewidth="350" frameheight="undefined" _eventid="35"><strong>Spring</strong></a>更总是带来惊喜。<br />
<br />
DDD(领域驱动设计)是一个好的设想，而如今像<a id="id_http://www.jdon.com/dl/best/spring.htm" class="hotkeys ajax_query=Spring" href="http://www.jdon.com/dl/best/spring.htm" _counted="undefined" ajaxid="query=Spring" framewidth="350" frameheight="undefined" _eventid="36"><strong>Spring</strong></a>这类的标准化框架则可以把这个设想变为现实。在这个设想里，管理人员、分析师和用户定义模型功能要求，架构师根据要求选择技术方案，不同的程序员(有做dao的、做service的、做view的)根据接口要求实现代码，通过测试后提交。而因为有支持分层、DI、AOP的框架存在(比如说<a id="id_http://www.jdon.com/dl/best/spring.htm" class="hotkeys ajax_query=Spring" href="http://www.jdon.com/dl/best/spring.htm" _counted="undefined" ajaxid="query=Spring" framewidth="350" frameheight="undefined" _eventid="37"><strong>Spring</strong></a>)，布署人员就可以简单地把他们组装在一起。<br />
面对不断的需求变化，分析师仍然只需增加/变动模型和功能接口，测试人员和编程人员按作相应变化即可。<br />
总体设计、分步实施、按需定制、分工合作、无缝组装，这种工业标准化的软件开发方式才是企业应用的答案。而<a id="id_http://www.jdon.com/jivejdon/query/searchThreadAction.shtml?query=%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1&amp;view=on" class="hotkeys ajax_query=OO" href="http://www.jdon.com/jivejdon/query/searchThreadAction.shtml?query=%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1&amp;view=on" _counted="undefined" ajaxid="query=OO" framewidth="350" frameheight="undefined" _eventid="38"><strong>OO</strong></a>、分层、ID、AOP、TDD和Refactor是真正支撑这个开发方式的支柱。以这样的方式，DDD会真正成为现实。<br />
<br />
<br />
信息发达国家的软件业其实很大程度上已经实践了这种开发方式(想想那些大规模的外包吧)。这些年国内搞Java的，张嘴闭口便是SSH。可惜很多人搞了一些年后，还是&#8220;不识庐山真面目&#8221;，成天抱怨&#8220;好烦&#8221;。在这样浮燥的产业环境下，国内大多数企业应用的质量是低劣的。<br />
即使你天天在写Java、天天在用<a id="id_http://www.jdon.com/dl/best/spring.htm" class="hotkeys ajax_query=Spring" href="http://www.jdon.com/dl/best/spring.htm" _counted="undefined" ajaxid="query=Spring" framewidth="350" frameheight="undefined" _eventid="39"><strong>Spring</strong></a>，如果不能够&#8220;知其所以然&#8221;，那么你的SSH注定是偷工减料的豆腐渣。所以在此劝诸位从事企业应用的同道，好好静下心来，认真思考一下你的应用所面对的各种问题，再好好思考一下<a id="id_http://www.jdon.com/jivejdon/query/searchThreadAction.shtml?query=%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1&amp;view=on" class="hotkeys ajax_query=OO" href="http://www.jdon.com/jivejdon/query/searchThreadAction.shtml?query=%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1&amp;view=on" _counted="undefined" ajaxid="query=OO" framewidth="350" frameheight="undefined" _eventid="40"><strong>OO</strong></a>、DI、AOP、TDD和Refator给你带来的福音。<br />
<br />
愿大家的系统质量都能更上一层楼，这样才可变恶性竞争为良性合作，让我国的信息系统发挥更大更好的作用。 </span></fieldset><br />
<br />
<img src ="http://www.blogjava.net/jhyan/aggbug/261854.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2009-03-25 14:25 <a href="http://www.blogjava.net/jhyan/archive/2009/03/25/261854.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tuscany学习笔记一（java组件实现中服务定义与解析）</title><link>http://www.blogjava.net/jhyan/archive/2008/12/20/247521.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Sat, 20 Dec 2008 10:01:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/12/20/247521.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/247521.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/12/20/247521.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/247521.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/247521.html</trackback:ping><description><![CDATA[在学习tuscany到过程遇到一个疑问（java组件实现是如何解析java类文件中的服务的？如果没有配置服务，默认服务应该是什么？），开始的时候一直无法想清楚，通过阅读源码终于了解了部分解析过程<br />
<br />
以tuscany中的Calculator为例说明服务的定义：<br />
<br />
1.&nbsp; 如果按照例子本身的代码和配置，我们应该如何获取服务呢？<br />
<br />
<br />
<span style="color: #000000;">CalculatorService实现代码</span><br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;calculator;<br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;org.osoa.sca.annotations.Reference;<br />
<br />
<br />
</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;*&nbsp;An&nbsp;implementation&nbsp;of&nbsp;the&nbsp;Calculator&nbsp;service.<br />
&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;CalculatorServiceImpl&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;CalculatorService&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;AddService&nbsp;addService;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;SubtractService&nbsp;subtractService;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;MultiplyService&nbsp;multiplyService;<br />
。。。。。。。。。。。。。<br />
</span></div>
<br />
配置：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">component&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="CalculatorServiceComponent"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">implementation</span><span style="color: #ff0000;">.java&nbsp;class</span><span style="color: #0000ff;">="calculator.CalculatorServiceImpl"</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">reference&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="addService"</span><span style="color: #ff0000;">&nbsp;target</span><span style="color: #0000ff;">="AddServiceComponent"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">reference&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="subtractService"</span><span style="color: #ff0000;">&nbsp;target</span><span style="color: #0000ff;">="SubtractServiceComponent"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">reference&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="multiplyService"</span><span style="color: #ff0000;">&nbsp;target</span><span style="color: #0000ff;">="MultiplyServiceComponent"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">reference&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="divideService"</span><span style="color: #ff0000;">&nbsp;target</span><span style="color: #0000ff;">="DivideServiceComponent"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">component</span><span style="color: #0000ff;">&gt;</span></div>
<br />
&nbsp; a. 例子中获取服务的方法：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">CalculatorService&nbsp;calculatorService&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scaDomain.getService(CalculatorService.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">CalculatorServiceComponent</span><span style="color: #000000;">"</span><span style="color: #000000;">);</span></div>
<br />
通过上述代码我们就可以获取相应的服务了，我们不仅要问，为什么能够获取相应的服务呢？<br />
<span style="color: red;"><br />
根据java组件实现规范说明，如果组件只包含一个服务，那么我们在获取服务的时候可以省略服务的名字。</span><br />
<br />
<span style="font-size: 18pt;"><span style="color: red;">我的问题是：省略的服务名字是什么？</span></span><br />
<br />
<br />
b. 完整获取服务的方法：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">CalculatorService&nbsp;calculatorService1&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">scaDomain.getService(CalculatorService.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">CalculatorServiceComponent/CalculatorServiceImpl</span><span style="color: #000000;">"</span><span style="color: #000000;">);</span></div>
<br />
大家通过比较就可以知道，其实省略的<span style="color: red;"><span style="color: #060000;">服务名字是</span> CalculatorServiceImpl</span><br />
<br />
为什么是这个名字，大家可以参考源码中的 <br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(services.isEmpty())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;class&nbsp;is&nbsp;the&nbsp;interface</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addService(type,&nbsp;clazz);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br />
<br />
2. 自己定义一个服务<br />
<br />
自己在实现中添加服务声明<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">1</span>&nbsp;<span style="color: #000000;">@Service(CalculatorService.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">2</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;CalculatorServiceImpl&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;CalculatorService&nbsp;{<br />
</span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;AddService&nbsp;addService;<br />
</span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;SubtractService&nbsp;subtractService;<br />
</span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;MultiplyService&nbsp;multiplyService;<br />
</span><span style="color: #008080;">7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;DivideService&nbsp;divideService;<br />
。。。。。。<br />
</span></div>
<br />
<br />
我们可以通过如下方式获取服务：<br />
<br />
a. 例子中的方式<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">CalculatorService&nbsp;calculatorService&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scaDomain.getService(CalculatorService.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">CalculatorServiceComponent</span><span style="color: #000000;">"</span><span style="color: #000000;">);</span></div>
<br />
b. 完整方式<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">CalculatorService&nbsp;calculatorService1&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">scaDomain.getService(CalculatorService.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">CalculatorServiceComponent/CalculatorService</span><span style="color: #000000;">"</span><span style="color: #000000;">);</span></div>
<br />
<span style="color: #ff0000;">我们通过如下方式就<span style="font-size: 24pt;">＊不能＊</span>获取服务了</span><br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">CalculatorService&nbsp;calculatorService1&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">scaDomain.getService(CalculatorService.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">CalculatorServiceComponent/CalculatorServiceImpl</span><span style="color: #000000;">"</span><span style="color: #000000;">);</span></div>
<br />
<br />
原因很简单，实现不会再添加默认服务（<span style="color: #000000;">CalculatorServiceImpl</span>）了<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
源码摘录如下：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">org.apache.tuscany.sca.implementation.java.introspect.impl.HeuristicPojoProcessor<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">T</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;visitEnd(Class</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">T</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;clazz,&nbsp;JavaImplementation&nbsp;type)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;IntrospectionException&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">org.apache.tuscany.sca.assembly.Service</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;services&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;type.getServices();<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(services.isEmpty())&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;heuristically&nbsp;determine&nbsp;the&nbsp;service</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;following&nbsp;is&nbsp;quoted&nbsp;from&nbsp;Java&nbsp;Specification&nbsp;1.2.1.3.&nbsp;Introspecting&nbsp;services&nbsp;offered&nbsp;by&nbsp;a&nbsp;Java&nbsp;implementation<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;In&nbsp;the&nbsp;cases&nbsp;described&nbsp;below,&nbsp;the&nbsp;services&nbsp;offered&nbsp;by&nbsp;a&nbsp;Java&nbsp;implementation&nbsp;class&nbsp;may&nbsp;be&nbsp;determined<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;through&nbsp;introspection,&nbsp;eliding&nbsp;the&nbsp;need&nbsp;to&nbsp;specify&nbsp;them&nbsp;using&nbsp;@Service.&nbsp;The&nbsp;following&nbsp;algorithm&nbsp;is&nbsp;used&nbsp;<br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;to&nbsp;determine&nbsp;how&nbsp;services&nbsp;are&nbsp;introspected&nbsp;from&nbsp;an&nbsp;implementation&nbsp;class:<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;If&nbsp;the&nbsp;interfaces&nbsp;of&nbsp;the&nbsp;SCA&nbsp;services&nbsp;are&nbsp;not&nbsp;specified&nbsp;with&nbsp;the&nbsp;@Service&nbsp;annotation&nbsp;on&nbsp;the&nbsp;<br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;implementation&nbsp;class,&nbsp;it&nbsp;is&nbsp;assumed&nbsp;that&nbsp;all&nbsp;implemented&nbsp;interfaces&nbsp;that&nbsp;have&nbsp;been&nbsp;annotated&nbsp;<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;as&nbsp;@Remotable&nbsp;are&nbsp;the&nbsp;service&nbsp;interfaces&nbsp;provided&nbsp;by&nbsp;the&nbsp;component.&nbsp;If&nbsp;none&nbsp;of&nbsp;the&nbsp;implemented&nbsp;<br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;interfaces&nbsp;is&nbsp;remotable,&nbsp;then&nbsp;by&nbsp;default&nbsp;the&nbsp;implementation&nbsp;offers&nbsp;a&nbsp;single&nbsp;service&nbsp;whose&nbsp;type&nbsp;<br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;is&nbsp;the&nbsp;implementation&nbsp;class.<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Class</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;interfaces&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;getAllInterfaces(clazz);<br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(Class</span><span style="color: #000000;">&lt;?&gt;</span><span style="color: #000000;">&nbsp;i&nbsp;:&nbsp;interfaces)&nbsp;{<br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(i.isAnnotationPresent(Remotable.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">||</span><span style="color: #000000;">&nbsp;i.isAnnotationPresent(WebService.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">))&nbsp;{<br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addService(type,&nbsp;i);<br />
</span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">25</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">26</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(services.isEmpty())&nbsp;{<br />
</span><span style="color: #008080;">27</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;class&nbsp;is&nbsp;the&nbsp;interface</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">28</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addService(type,&nbsp;clazz);<br />
</span><span style="color: #008080;">29</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">30</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">31</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Method</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;methods&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;getAllUniquePublicProtectedMethods(clazz,&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">32</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">type.getReferenceMembers().isEmpty()&nbsp;</span><span style="color: #000000;">||</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">!</span><span style="color: #000000;">type.getPropertyMembers().isEmpty())&nbsp;{<br />
</span><span style="color: #008080;">33</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;references&nbsp;and&nbsp;properties&nbsp;have&nbsp;been&nbsp;explicitly&nbsp;defined<br />
</span><span style="color: #008080;">34</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(type.getServices().isEmpty())&nbsp;{<br />
</span><span style="color: #008080;">35</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;calculateServiceInterface(clazz,&nbsp;type,&nbsp;methods);<br />
</span><span style="color: #008080;">36</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(type.getServices().isEmpty())&nbsp;{<br />
</span><span style="color: #008080;">37</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ServiceTypeNotFoundException(clazz.getName());<br />
</span><span style="color: #008080;">38</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">39</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">40</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;evaluateConstructor(type,&nbsp;clazz);<br />
</span><span style="color: #008080;">41</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">42</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">43</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;calcPropRefs(methods,&nbsp;services,&nbsp;type,&nbsp;clazz);<br />
</span><span style="color: #008080;">44</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;evaluateConstructor(type,&nbsp;clazz);<br />
</span><span style="color: #008080;">45</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">46</span>&nbsp;</div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/jhyan/aggbug/247521.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-12-20 18:01 <a href="http://www.blogjava.net/jhyan/archive/2008/12/20/247521.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HP中国区总裁的退休感言 （转载） </title><link>http://www.blogjava.net/jhyan/archive/2008/12/02/243902.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Tue, 02 Dec 2008 04:58:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/12/02/243902.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/243902.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/12/02/243902.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/243902.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/243902.html</trackback:ping><description><![CDATA[<p><strong>转载自：<a href="http://www.loveayang.com.cn/post/2008/09/HPe4b8ade59bbde58cbae680bbe8a381e79a84e98080e4bc91e6849fe8a880-efbc88ZTefbc89.aspx">http://www.loveayang.com.cn/post/2008/09/HPe4b8ade59bbde58cbae680bbe8a381e79a84e98080e4bc91e6849fe8a880-efbc88ZTefbc89.aspx</a><br />
</strong></p>
<p><strong><br />
</strong></p>
<p><strong>一、工作与生活</strong> </p>
<p>我有个有趣的观察，外企公司多的是25--35岁的白领，40岁以上的员工很
少。二三十岁的外企员工是意气风发的，但外企公司40岁附近的经理人是很尴尬的。我见过的40岁附近的外企经理人大多在一直跳槽，最后大多跳到民企——比
方说唐骏。外企员工的成功很大程度上是公司的成功，并非个人的成功。西门子的确比国美大，但并不代表西门子中国经理比国美的老板强，甚至可以说差得很远。
而进外企的人往往并不能很早理解这一点，把自己的成功90％归功于自己的能力。实际上，外企公司随便换个中国区总经理并不会给业绩带来什么了不起的影响。
好了，问题来了。当这些经理人40多岁了，他们的薪资要求变得很高，而他们的才能其实又不是那么出众，作为外企公司的老板，你会怎么选择？有的是只要不高
薪水的，要出位的精明强干、精力冲沛的年轻人——有的是，为什么还要用你？<br />
从上面这个例子，其实可以看到我们的工作轨迹。二三十岁的时候，生活的
压力还比较小，身体还比较好。上面的父母身体还好，下面又没有孩子，不用还房贷，也没有孩子要上大学，当个外企小白领还是很光鲜的，挣得不多也够花了。但
是人终归要结婚生子，终归会老。到了40岁，父母老了，要看病要吃药，要有人看护，自己要还房贷，要过基本体面的生活，要养小孩&#8230;&#8230;那个时候需要挣多少钱
才够花才重要。所以，看待工作，眼光要放远一点，一时的谁高谁低并不能说明什么。<br />
从这个角度上来说，我不太赞成过于关注第一份工作的薪水，更没有
必要攀比第一份工作的薪水，这在刚刚出校园的学生中间是很常见的。正常人大概要工作35年，这好比是一场马拉松比赛。和真正的马拉松比赛不同的是，这次比
赛没有职业选手，每个人都只有一次机会。要知道，有很多人甚至坚持不到终点，大多数人最后是走到终点的，只有少数人是跑过终点的。因此在刚开始的时候，去
抢领先的位置并没有太大的意义。刚进社会的时候如果进500强公司，大概能拿到3k-6k/月的工资，有些特别技术的人才可能可以到8k/月。可问题
是，5年以后拿多少？估计5k-10k了不起了。起点虽然高，但增幅有限，而且后面的年轻人追赶的压力越来越大。<br />
我前两天问我的一个销售，你会的这些东西一个新人2年就都学会了，但新人所要求的薪水却只是你的一半，到时候你怎么办？<br />
职
业生涯就像一场体育比赛，有初赛、复赛、决赛。初赛的时候大家都刚刚进社会，大多数都是实力一般的人。这时候努力一点、认真一点很快就能让人脱颖而出，于
是有的人二十多岁做了经理，有的人迟些也终于赢得了初赛，三十多岁成了经理。然后是复赛，能参加复赛的都是赢得初赛的。每个人都有些能耐，在聪明才智上都
不成问题，这个时候再想要胜出就不那么容易了，单靠一点点努力和认真还不够，要有很强的坚忍精神，要懂得靠团队的力量，要懂得收服人心，要有长远的眼
光&#8230;&#8230;<br />
看上去赢得复赛并不容易，但还不是那么难。因为这个世界的规律就是给人一点成功的同时让人骄傲自满，刚刚赢得初赛的人往往不知道自己赢得的
仅仅是初赛，有了一点小小的成绩大多数人都会骄傲自满起来，认为自己已经懂得了全部，不需要再努力再学习了，他们会认为之所以不能再进一步已经不是自己的
原因了。虽然他们仍然不好对付，但是他们没有耐性，没有容人的度量，更没有清晰长远的目光。就像一只愤怒的斗牛，虽然猛烈，最终是会败的。而赢得复赛的人
则象斗牛士一样，不急不躁，跟随着自己的节拍，慢慢耗尽对手的耐心和体力。赢得了复赛以后，大约已经是一位很了不起的职业经理人了，当上了中小公司的总经
理，大公司的副总经理，主管着每年几千万乃至几亿的生意。<br />
最终的决赛来了。说实话我自己都还没有赢得决赛，因此对于决赛的决胜因素也只能凭自己的
猜测而已。这个时候的输赢或许就像武侠小说里写得那样，大家都是高手，只能等待对方犯错了。要想轻易击败对手是不可能的，除了使上浑身解数，还需要一点运
气和时间。世界的规律依然发挥着作用，赢得复赛的人已经不只是骄傲自满了，他们往往刚愎自用，听不进去别人的话，有些人的脾气变得暴躁，心情变得浮躁，身
体变得糟糕，他们最大的敌人就是他们自己。在决赛中要做的只是不被自己击败，等着别人被自己击败。这和体育比赛是一样的，最后高手之间的比赛，就看谁失误
少谁就赢得了决赛。<br />
</p>
<p><strong>二、 </strong><strong>根源</strong><br />
你工作快乐么？你的工作好么？<br />
有
没有觉得干了一段时间以后工作很不开心？有没有觉得自己入错了行？有没有觉得自己没有得到应有的待遇？有没有觉得工作像一团乱麻每天上班都是一种痛苦？有
没有很想换个工作？有没有觉得其实现在的公司并没有当初想象得那么好？有没有觉得这份工作是当初因为生存压力而找的，实在不适合自己？你从工作中得到你想
要得到的了么？你每天开心么？<br />
天涯上愤怒的人很多，你有没有想过，你为什么不快乐？你为什么愤怒？<br />
其实，你不快乐的根源，是因为你不知道要什么！你不知道要什么，所以你不知道去追求什么，你不知道追求什么，所以你什么也得不到。<br />
我
总觉得，职业生涯首先要关注的是自己，自己想要什么。大多数人大概没想过这个问题，唯一的想法只是我想要一份工作，我想要一份不错的薪水。我知道所有人对
于薪水的渴望，可是你想每隔几年重来一次找工作的过程么？你想每年都在这种对于工作和薪水的焦急不安中度过么？不想的话，就好好想清楚。饮鸩止渴，不能因
为口渴就拼命喝毒药。越是焦急，越是觉得自己需要一份工作，越饥不择食。越想不清楚，越容易失败，你的经历越来越差，下一份工作的人看着你的简历就皱眉
头。于是你越喝越渴，越渴越喝，陷入恶性循环。最终只能哀叹世事不公或者生不逢时，只能到天涯上来发泄一把，在失败者的共鸣当中寻求一点心理平衡罢了。大
多数人都有生存压力，我也是。有生存压力就会有很多焦虑，积极的人会从焦虑中得到动力，而消极的人则会因为焦虑而迷失方向。所有人都必须在压力下做出选
择，这就是世道——你喜欢也罢不喜欢也罢。<br />
一般我们处理的事情分为重要的事情和紧急的事情，如果不做重要的事情就会常常去做紧急的事情。比如锻炼
身体保持健康是重要的事情，而看病则是紧急的事情。如果不锻炼身体保持健康，就会常常为了病痛烦恼。又比如防火是重要的事情，而救火是紧急的事情，如果不
注意防火，就要常常救火。找工作也是如此，想好自己究竟要什么是重要的事情，找工作是紧急的事情，如果不想好，就会常常要找工作。往往紧急的事情给人的压
力比较大，迫使人们去赶紧做。相对来说重要的事情反而没有那么大的压力，大多数人做事情都是以压力为导向的。压力之下，总觉得非要先做紧急的事情，结果就
是永远到处救火，永远没有停歇的时候——很多人的工作也像是救火队一样忙碌痛苦，也是因为工作中没有做好重要的事情——那些说自己活在水深火热为了生存顾
不上那么多的朋友，今天找工作困难是当初你们没有做重要的事情，是结果不是原因。如果今天你们还是因为急于要找一份工作而不去思考，那么或许将来要继续承
受痛苦找工作的结果。<br />
我始终觉得我要说的话题沉重了点，需要很多思考，远比唐笑打武警的话题来的枯燥乏味。但是，天下没有轻松的成功。成功，要付代价。请先忘记一切的生存压力，想想这辈子你最想要的是什么？所以，最要紧的事情，先想好自己想要什么。<br />
<strong>三、什么是好工作</strong><br />
当
初微软有个唐骏，很多大学里的年轻人觉得这才是他们向往的职业生涯。我在清华BBS里发的帖子被这些学子们所不屑，那个时候学生们只想出国或者去外企。不
过如今看来，我还是对的。唐骏去了盛大，陈天桥创立的盛大，一家民营公司。一个高学历的海归在500强的公司里拿高薪水，这大约是很多年轻人的梦想。问题
是，每年毕业的大学生都在做这个梦，好的职位却只有500个。<br />
人都是要面子的，也是喜欢攀比的，即使在工作上也喜欢攀比，不管那是不是自己想要
的。大家认为外企公司很好，可是好在哪里呢？好吧，他们在比较好的写字楼，这是你想要的么？他们出差住比较好的酒店，这是你想要的么？别人会羡慕一份外企
公司的工作，这是你想要的么？那一切都是给别人看的，你干嘛要活得那么辛苦给别人看？！！另一方面，他们薪水福利一般，并没有特别了不起；他们的晋升机会
比较少，很难做到很高阶的主管；他们虽然厌恶常常加班，却不敢不加班，因为&#8220;你不干有得是人干&#8221;；大部分情况下会找个台湾人/香港人/新加坡人来管你，而
这些人又往往有些莫名其妙的优越感。你想清楚了么，500强一定好么？找工作究竟是考虑你想要什么，还是考虑别人想看什么？<br />
我的大学同学们大多数
都到美国了，甚至毕业这么多年了，还有人最近到国外去了。出国真的有那么好么？我的大学同学们大多数还是在博士、博士后、访问学者地边缘挣扎着，至今只有
一个正经在一个美国大学里拿到个正式的教职。国内的教授很难当么？我有几个表亲也去了国外了，他们的父母独自在国内，没有人照顾，有好几次人亲在家里昏倒
都没人知道。出国，真的这么光彩么？就像有人说的：&#8220;很多事情就像看A片，看的人觉得很爽，做的人未必。&#8221;<br />
人总想找到那个最好的，可是，什么是最好的？你觉得是最好的那个，是因为你的确了解，还是因为别人说它是最好的？即使它对于别人是最好的，对于你也一定是最好的么？<br />
对
于自己想要什么，自己要最清楚，别人的意见并不是那么重要。很多人总是常常被别人的意见所影响，亲戚的意见、朋友的意见、同事的意见&#8230;&#8230;问题是，你究竟是
要过谁的一生？人的一生不是父母一生的续集，也不是儿女一生的前传，更不是朋友一生的外篇，只有你自己对自己的一生负责，别人无法也负不起这个责任。自己
做的决定，至少到最后，自己没什么可后悔的。对于大多数正常智力的人来说，所做的决定没有大的对错，无论怎么样的选择，都是可以尝试的。比如你没有考入自
己上的那个学校，没有入现在这个行业，这辈子就过不下去了，就会很失败？不见得。<br />
我想，好工作应该是适合你的工作。具体点说，应该是能给你带来你
想要的东西的工作。你或许应该以此来衡量你的工作究竟好不好，而不是拿公司的大小、规模、外企还是国企、是不是有名、是不是上市公司来衡量。小公司未必不
是好公司，赚钱多的工作也未必是好工作。你还是要先弄清楚你想要什么，如果你不清楚你想要什么，你就永远也不会找到好工作，因为你永远只看到你得不到的东
西，你得到的，都是你不想要的。<br />
可能最好的已经在你的身边，只是你还没有学会珍惜。人们总是盯着得不到的东西，而忽视了那些已经得到的东西。<br />
<strong>四、普通人</strong><br />
我
发现中国人的励志和国外的励志存在非常大的不同。中国的励志比较鼓励人立下大志愿，卧薪尝胆，有朝一日成富成贵。而国外的励志比较鼓励人勇敢面对现实生
活，面对普通人的困境，虽然结果也是成富成贵，但起点不一样。相对来说，我觉得后者在操作上更现实，而前者则需要用999个失败者来堆砌一个成功者的故
事。<br />
我们都是普通人。普通人的意思就是，概率这件事是很准的。因此，我们不会买彩票中500万，我们不会成为比尔&#183;盖茨或者李嘉诚，我们不会坐飞机掉下来，我们当中很少的人会创业成功，我们之中有30％的人会离婚，我们之中大部分人会活过65岁&#8230;&#8230;<br />
所
以请你在想自己要什么的时候，要得&#8220;现实&#8221;一点。你说我想要做李嘉诚，抱歉，我帮不上你。成为比尔&#183;盖茨或者李嘉诚这种人，是靠命的，看我写的这篇文章绝
对不会让你成为他们——即使你成为了他们，也绝对不是我这篇文章的功劳。&#8220;王侯将相宁有种乎&#8221;，但真正当皇帝的只有一个人，王侯将相人也不多。目标定得高
些对于喜欢挑战的人来说有好处，但对于大多数普通人来说，反而比较容易灰心沮丧，很容易就放弃了。<br />
回过头来说，李嘉诚比你有钱大致50万倍，他比
你更快乐么？或许有。但有没有比你快乐50万倍？一定没有。他比你最多也就快乐一两倍，甚至有可能还不如你快乐。寻找自己想要的东西不是和别人比赛，比谁
要得更多、更高，比谁的目标更远大。虽然成为李嘉诚这个目标很宏大，但你并不见得会从这个目标以及追求目标的过程当中获得快乐，而且基本上你也做不到。你
必须听听你内心的声音，寻找真正能够使你获得快乐的东西，那才是你想要的东西。<br />
你想要的东西，或者我们把它称之为&#8220;目标&#8221;。目标其实并没有高低之
分，你不需要因为自己的目标没有别人远大而不好意思。达到自己的目标其实就是成功，成功有大有小，快乐却是一样的。我们追逐成功，其实追逐的是成功带来的
快乐，而非成功本身。职业生涯的道路上，我们常常会被攀比的心态蒙住眼睛，忘记了追求的究竟是什么，忘记了是什么能使我们更快乐。<br />
社会上一夜暴富
的新闻很多，这些消息总会在我们的心里面掀起很多涟漪。涟漪多了就变成惊涛骇浪，心里的惊涛骇浪除了打翻承载你目标的小船，并不会使得你也一夜暴富。&#8220;只
见贼吃肉，不见贼挨揍&#8221;。我们这些普通人既没有当&#8220;贼&#8221;的勇气，又缺乏当&#8220;贼&#8221;的狠辣、绝决。虽然羡慕&#8220;吃肉&#8221;，却更害怕&#8220;挨揍&#8221;，偶尔看到几个没&#8220;挨揍
&#8221;的&#8220;贼&#8221;就按奈不住，或者心思活动，或者大感不公，真要叫你去做&#8220;贼&#8221;，却也不敢。<br />
我还是过普通人的日子，要普通人的快乐，至少晚上睡得着觉。 </p>
<p><strong>五、跳槽与积累</strong><br />
首
先要说明，工作是一件需要理智的事情，所以不要在工作上耍个性。天涯上或许会有人觉得你很有个性而叫好，但煤气公司、电话公司不会因为觉得你很有个性而免
了你的帐单。当你很帅地炒掉了你的老板，当你很酷地挖苦了一番招聘的HR，账单还是要照付，只是你赚钱的时间更少了，除了你自己，没人受损失。<br />
我
并不反对跳槽，但跳槽决不是解决问题的办法，而且频繁跳槽的后果是让人觉得没有忠诚度可言，而且不能安心工作。现在很多人从网上找工作，很多找工作的网站
常常给人出些&#8220;馊主意&#8221;。要知道他们是盈利性企业，当然要从自身盈利的角度来考虑，大家越是频繁跳槽、频繁找工作他们越是生意兴隆，所以鼓动人们跳槽是他
们的工作。所以他们会常常告诉你，你拿的薪水少了，你享受的福利待遇差了，又是&#8220;薪情快报&#8221;又是&#8220;赞叹自由奔放的灵魂&#8221;。至于是否会因此让你不能安心，你
跳了槽是否解决问题，是否更加开心——那些，他们管不着。<br />
要跳槽肯定是有问题。一般来说问题发生了，躲是躲不开的。很多人跳槽是因为这样或者那样
的不开心，如果这种不开心在现在这个公司不能解决，那么在下一个公司多半也解决不掉。你必须相信，90%的情况下你所在的公司并没有那么烂，你认为不错的
公司也没有那么好。就像《围城》里说的，&#8220;城里的人拼命想冲出来，而城外的人拼命想冲进去&#8221;。每个公司都有每个公司的问题，没有问题的公司是不存在的。换
个环境你都不知道会碰到什么问题，与其如此，不如就在当下把问题解决掉。很多问题当你真的想要去解决的时候，或许并没有那么难。有的时候你觉得问题无法解
决，事实上，那只是&#8220;你觉得&#8221;。<br />
人生的曲线应该是曲折向上的，偶尔会遇到低谷，但大趋势总归是曲折向上的，而不是像脉冲波一样每每回到起点。我见
过不少面试者，30多岁了，四五份工作经历，每次多则3年少则1年。30多岁的时候回到起点从一个初级职位开始干起，拿基本初级的薪水，和20多岁的年轻
人一起竞争，不觉得有点辛苦么？这种日子好过么？<br />
我非常不赞成在一个行业不超过3年以后换行业。基本上，35岁以前我们的生存资本靠打拼，35岁
以后生存的资本靠的就是积累，这种积累包括人际关系、经验、人脉、口碑&#8230;&#8230;如果常常更换行业，代表几年的积累付之东流，一切从头开始。如果换了两次行
业，35岁的时候大概只有5年以下的积累，而一个没有换过行业的人至少有了10年的积累，谁会占优势？工作到2--3年的时候，很多人觉得工作不顺利，好
像到了一个瓶颈，心情烦闷，就想辞职，乃至换一个行业，觉得这样所有一切烦恼都可以抛开，会好很多。其实这样做只是让你从头开始，到时候还是会发生和原来
行业一样的困难。熬过去就向上跨了一大步，要知道每个人都会经历这个过程，每个人的职业生涯中都会碰到几个瓶颈，你熬过去了而别人没有熬过去你就领先了。
跑长跑的人会知道，开始的时候很轻松，但是很快会有第一次的难受，但过了这一段又能跑很长一段，接下来会碰到第二次的难受，坚持过了以后又能跑一段。如此
往复，难受一次比一次厉害，直到坚持不下去了。大多数人第一次就坚持不了了，一些人能坚持到第二次，第三次虽然大家都坚持不住了，可是跑到这里的人也没几
个了，这点资本足够你安稳活这一辈子了。<br />
一份工作到两三年的时候，大部分人都会变成熟手。这个时候往往会陷入不断的重复，有很多人会觉得厌倦，有
些人会觉得自己已经搞懂了一切，从而懒得去寻求进步了。很多时候的跳槽是因为觉得失去兴趣了，觉得自己已经完成比赛了，其实这个时候比赛才刚刚开始。工作
两三年的人，无论是客户关系、人脉、手下、与领导的关系、在业内的名气&#8230;&#8230;还都是远远不够的。但稍有成绩的人总是会自我感觉良好的，每个人都觉得自己跟客
户关系铁得要命，觉得自己在业界的口碑好得很。其实，可以肯定地说，一定不是。这个时候，还是要拿出前两年的干劲来，稳扎稳打——积累才刚刚开始。<br />
你足够了解你的客户么？你知道他最大的烦恼是什么么？<br />
你足够了解你的老板么？你知道他最大的烦恼是什么么？<br />
你足够了解你的手下么？你知道他最大的烦恼是什么么？<br />
如果你不知道，你凭什么觉得自己已经积累够了？如果你都不了解，你怎么能让他们帮你的忙，做你想让他们做的事情？如果他们不做你想让他们做的事情，你又何来的成功？<br />
<strong>六、等待</strong><br />
&#8220;等待&#8221;，这是个浮躁的人们最不喜欢的话题。本来不想说这个话题，因为会引起太多的争论，而我又无意和人争论这些，但是考虑到对于职业生涯的长久规划，这是一个躲避不了的话题，还是决定写一写，不爱看的请离开吧。<br />
并
不是每次穿红灯都会被汽车撞，并不是每个罪犯都会被抓到，并不是每个错误都会被惩罚，并不是每个贪官都会被枪毙，并不是你的每一份努力都会得到回报，并不
是你的每一次坚持都会有人看到，并不是你每一点付出都能得到公正的回报，并不是你的每一个善意都能被理解&#8230;&#8230;这个，就是世道。好吧，世道不够好，可是，你
有推翻世道的勇气么？如果没有，你有更好的解决办法么？有很多时候，人需要一点耐心，一点信心。每个人总会轮到几次不公平的事情，而通常，安心等待是最好
的办法。<br />
有很多时候我们需要等待，需要耐得住寂寞，等待属于你的那一刻。周润发等待过，刘德华等待过，周星驰等待过，王菲等待过，张艺谋也等待
过&#8230;&#8230;看到了他们如今的功成名就的人，你可曾看到当初他们的等待和耐心？你可曾看到金马奖影帝在街边摆地摊？你可曾看到德云社一群人在剧场里给一位观众说
相声？你可曾看到周星驰的角色甚至连一句台词都没有？每一个成功者都有一段低沉苦闷的日子，我几乎能想象得出来他们借酒浇愁的样子，我也能想象得出他们为
了生存而挣扎的窘迫。在他们一生中最灿烂美好的日子里，他们渴望成功，但却两手空空，一如现在的你。没有人保证他们将来一定会成功，而他们的选择是耐住寂
寞。如果当时的他们总念叨着&#8220;成功只是属于特权阶级的&#8221;，你觉得他们今天会怎样？<br />
曾经我也不明白有些人为什么并不比我有能力却要坐在我的头上，年
纪比我大就一定要当我的领导么？为什么有些烂人不需要努力就能赚钱？为什么刚刚改革开放的时候的人能那么容易赚钱，而轮到我们的时候，什么事情都要正规化
了？有一天我突然想到，我还在上学的时候他们就在社会里挣扎奋斗了，他们在社会上奋斗积累了十几二十年，我们新人来了，他们有的我都想要，我这不是在要公
平，我这是在抢劫。因为我要得太急，因为我忍不住寂寞。二十多岁的男人，没有钱，没有事业，却有蓬勃的欲望。<br />
人总是会遇到挫折的，人总是会有低潮
的，人总是会有不被人理解的时候的，人总是有要低声下气的时候，这些时候恰恰是人生最关键的时候。因为大家都会碰到挫折，而大多数人过不了这个门槛——你
能过，你就成功了。在这样的时刻，我们需要耐心等待，满怀信心地去等待。相信生活不会放弃你，机会总会来的。至少，你还年轻，你没有坐牢，没有生治不了的
病，没有欠还不起的债。比你不幸的人远远多过比你幸运的人，你还怕什么？！路要一步步走，虽然到达终点的那一步很激动人心，但大部分的脚步是平凡甚至枯燥
的。但没有这些脚步，或者耐不住这些平凡枯燥，你终归是无法迎来最后的那些激动人心。<br />
逆境，是上帝帮你淘汰竞争者的地方。要知道，你不好受，别人也不好受，你坚持不下去了，别人也一样。千万不要告诉别人你坚持不住了，那只能让别人获得坚持的信心，让竞争者看着你微笑的面孔，失去信心，退出比赛。胜利属于那些有耐心的人。<br />
在
最绝望的时候，我会去看电影《The Pursuit of Happyness》《Jerry
Maguire》，让自己重新鼓起勇气。因为，无论什么时候，我们总还是有希望。当所有的人离开的时候，我不失去希望，我不放弃。每天下班坐在车里，我喜
欢哼着《隐形的翅膀》看着窗外，我知道，我在静静等待，等待属于我的那一刻。<br />
原帖里伊吉网友的话我很喜欢，抄录在这里：<br />
&#8220;每个人都希望，自己是独一无二的特殊者。<br />
含着金匙出生、投胎到好家庭、工作安排到电力局、拿1万月薪这样的小概率事件，当然最好轮到自己。<br />
红军长征两万五、打成右派反革命、胼手胝足牺牲尊严去奋斗，最好留给祖辈父辈和别人。<br />
自然，不是每个吃过苦的人都会得到回报。<br />
但是，任何时代，每一个既得利益者身后，都有他的祖辈父辈奋斗挣扎乃至流血付出生命的身影。<br />
羡慕别人有个好爸爸，没什么不可以。<br />
问题是，你的下一代，会有一个好爸爸吗？<br />
至于问到为什么不能有同样的赢面概率？我只能问：为什么物种竞争中，人和猴子不能有同样的赢面概率？<br />
物竞天择。猴子的灵魂不一定比你卑微，但你身后有几十万年的类人猿进化积淀。&#8221; </p>
<p><strong>七、入对行与 </strong><strong>跟对人</strong><br />
在中国，大概很少有人是一份职业做到底的。虽然如此，第一份工作还是有些需要注意<br />
第
一份工作对人最大的影响就是入行，现代的职业分工已经很细，我们基本上只能在一个行业里成为专家，不可能在多个行业里成为专家。很多案例也证明即使一个人
在一个行业非常成功，到另外一个行业，往往完全不是那么回事情。&#8220;你想改变世界，还是想卖一辈子汽水？&#8221;是乔布斯邀请百事可乐总裁约翰&#8226;斯考利加盟苹果时
所说的话，结果这位在百事非常成功的约翰，到了苹果表现平平。其实没有哪个行业特别好，也没有哪个行业特别差，或许有报道说哪个行业的平均薪资比较高，但
是他们没说的是，那个行业的平均压力也比较大。看上去很美的行业一旦进入才发现很多地方其实并不那么完美，只是外人看不见。<br />
说实话，我自己都没有发大财，所以我的建议只是让人快乐工作的建议，不是如何发大财的建议，我们只讨论一般普通打工者的情况。<br />
我
认为选择什么行业并没有太大关系，看问题不能只看眼前。比如，从前年开始，国家开始整顿医疗行业，很多医药公司开不下去，很多医药行业的销售开始转行。其
实医药行业的不景气是针对所有公司的，并非针对一家公司，大家的日子都不好过，这个时候跑掉是非常不划算的。大多数正规的医药公司即使不做新生意撑个两三
年总是能撑的，大多数医药销售靠工资撑个两三年也是可以撑的。国家不可能永远捏着医药行业不放的，两三年以后光景总归还会好起来的，那个时候别人都跑了而
你没跑，那时的日子应该会好过很多。有的时候觉得自己这个行业不行了，问题是，再不行的行业，做得人少了也变成了好行业。当大家都觉得不好的时候，往往却
是最好的时候。大家都觉得金融行业好，金融行业门槛高不说，有多少人削尖脑袋要钻进去，竞争激烈。进去以后还要时时提防，一个疏忽，就被后来的人给挤掉
了，压力巨大，又如何谈得上快乐，也就未必是&#8220;好&#8221;工作了。<br />
太阳能这个东西至今还不能进入实际应用的阶段，但是中国已经有7家和太阳能有关的公司
在纽交所上市了；国美、苏宁、永乐其实是贸易型企业，也能上市；鲁泰纺织连续10年利润增长超过50%；卖茶的一茶一座、卖衣服的海澜之家都能上市&#8230;&#8230;其
实选什么行业真的不重要，关键是怎么做。事情都是人做出来的，关键是人。<br />
有一点是需要记住的：这个世界上有史以来直到我们能够预见得到的未来，成
功的人总是少数，有钱的人总是少数，大多数人是一般的，普通的，不太成功的。因此，大多数人的做法和看法，往往都不是距离成功最近的做法和看法。因此大多
数人说好的东西不见得好，大多数人说不好的东西不见得不好。大多数人都去炒股的时候说明跌只是时间问题，大家越是热情高涨的时候，跌的日子越近。大多数人
买房子的时候，房价不会涨，而房价涨的差不多的时候，大多数人才开始买房子。不会有这样一件事情让大家都变成功，发了财，历史上不曾有过，将来也不会发
生。有些东西即使一时运气好得到了，还是会在别的时候、别的地方失去的。<br />
年轻人在职业生涯刚开始的时候，尤其要注意的是，要做对的事情，不要让自
己今后几十年的人生总是提心吊胆，更不值得为了一份工作赔上自己的青春年华。我的公司是个不行贿的公司，以前很多人不理解，甚至自己的员工也不理解。不过
如今，我们是同行中最大的企业，客户乐意和我们打交道，尤其是在国家打击腐败的时候，每个人都知道我们做生意不给钱的名声，都敢于和我们做生意。而勇于给
钱的公司，不是倒了，就是跑了，要不就是每天睡不好觉，人还是要看长远一点。很多时候，看起来最近的路，其实是最远的路，看起来最远的路，其实是最近的
路。<br />
跟对人是说，入行后要跟个好领导、好老师。刚进社会的人做事情往往没有经验，需要有人言传身教。对于一个人的发展来说，一个好领导是非常重要的。所谓&#8220;好&#8221;的标准，不是他让你少干活多拿钱，而是以下三个。<br />
首
先，好领导要有宽广的心胸。如果一个领导每天都会发脾气，那几乎可以肯定他不是个心胸宽广的人，能发脾气的时候却不发脾气的领导，多半是非常厉害的领导。
中国人当领导最大的毛病是容忍不了能力比自己强的人，所以常常可以看到的一个现象是，领导很有能力，手下一群庸才或者手下一群闲人。如果看到这样的环境，
还是不要去的好。<br />
其次，领导要愿意从下属的角度来思考问题，这一点其实是从面试的时候就能发现的。如果这位领导总是从自己的角度来考虑问题，几乎
不听你说什么，这就危险了。从下属的角度来考虑问题并不代表同意下属的说法，但他必须了解下属的立场。下属为什么要这么想，然后他才有办法说服你。只关心
自己怎么想的领导，往往难以获得下属的信服。<br />
最后，领导敢于承担责任。如果出了问题就把责任往下推，有了功劳就往自己身上揽，这样的领导不跟也罢。选择领导，要选择关键时刻能抗得住的领导，能够为下属的错误买单的领导，因为这是他作为领导的责任。<br />
有
可能，你碰不到好领导，因为，中国的领导往往是屁股决定脑袋的领导。因为他坐领导的位置，所以他的话就比较有道理，这是传统观念官本位的误区，可能有大量
的这种无知无能的领导，只是，这对于你其实是好事。如果将来有一天你要超过他，你希望他比较聪明还是比较笨？相对来说这样的领导其实不难搞定，只是你要把
自己的身段放下来而已。多认识一些人，多和比自己强的人打交道，同样能找到好的老师。不要和一群同样郁闷的人一起控诉社会，控诉老板，这帮不上你，只会让
你更消极。和那些比你强的人打交道，看他们是怎么想的，怎么做的，学习他们，然后跟更强的人打交道。<br />
<strong>八、选择</strong><br />
我们每天做的最多的事情，其实是选择，因此在谈职业生涯的时候不得不提到这个话题。<br />
我
始终认为，在很大的范围内，我们究竟会成为一个什么样的人，决定权在我们自己。每天我们都在做各种各样的选择，我可以不去写这篇文章，去别人的帖子拍拍砖
头，也可以写下这些文字，帮助别人的同时也整理自己的思路；我可以多注意下格式让别人易于阅读，也可以写成一堆；我可以就这样发上来，也可以在发以前再看
几遍；你可以选择不刮胡子就去面试，也可以选择出门前照照镜子&#8230;&#8230;每天，每一刻我们都在做这样那样的决定。我们可以漫不经心，也可以多花些心思。成千上万
的小选择累计起来，就决定了最终我们是个什么样的人。<br />
从某种意义上来说，我们的未来不是别人给的，是我们自己选择的。很多人会说我命苦啊，没得选
择啊&#8230;&#8230;如果你认为&#8220;去微软还是去IBM&#8221;、&#8220;上清华还是上北大&#8221;、&#8220;当销售副总还是当厂长&#8221;这种才叫选择的话，的确你没有什么选择，大多数人都没有什么
选择。但每天你都可以选择是否为客户服务更周到一些，是否对同事更耐心一些，是否把工作做得更细致一些，是否把情况了解得更清楚一些，是否把不清楚的问题
再弄清楚一些&#8230;&#8230;你也可以选择是否在痛苦中继续坚持，是否抛弃掉自己的那些负面的想法，是否原谅一个人的错误，是否相信我在这里写下的这些话，是否不要再
犯同样的错误&#8230;&#8230;<br />
生活每天都在给你选择的机会，每天都在给你改变自己人生的机会。你可以选择赖在地上撒泼打滚，也可以选择咬牙站起来。你永远都有
选择。有些选择不是立杆见影的，需要累积，比如农民可以选择自己常常去浇地，也可以选择让老天去浇地。诚然，你今天浇水下去，苗不见得今天马上就长出来，
但常常浇水，大部分苗终究会长出来的。如果你不浇，收成一定很糟糕。<br />
每天，生活都在给你机会。它不会给你一叠现金也不会拱手送你个好工作，但实际
上，它还是在给你机会。我的家庭是一个普通的家庭，没有任何了不起的社会关系。我的父亲在大学毕业以后就被分配到了边疆，那个小县城只有一条马路。他们那
一代人其实比我们更有理由抱怨，他们什么也没得到，年轻的时候文化大革命，书都没得读，支援边疆插队落户，等到老了，却要给年轻人机会了。他有足够的理由
像成千上万那样的青年一样，坐在那里抱怨生不逢时，怨气冲天。然而，在分配到边疆的十年之后，国家恢复招研究生，他考回了原来的学校。研究生毕业，他被分
配到了安徽一家小单位里。又是三年以后，国家招收第一届博士生，他又考回了原来的学校，成为中国第一代博士，那时的他比现在的我年纪还大。生活并没有放弃
他，他也没有放弃生活。10年的等待，他做了他自己的选择。他没有放弃，他没有破罐子破摔，所以时机到来的时候，他改变了自己的人生。你最终会成为什么样
的人，就决定在你的每个小小的选择之间。<br />
你选择相信什么，你选择和谁交朋友，你选择做什么，你选择怎么做&#8230;&#8230;我们面临太多的选择。而这些选择当
中，意识形态层面的选择又远比客观条件的选择来得重要得多。比如，选择做什么产品其实并不那么重要，而选择怎么做才重要。选择用什么人并不重要，而选择怎
么带这些人才重要。大多数时候选择客观条件并不要紧，大多数关于客观条件的选择并没有对错之分，要紧的是选择怎么做。一个大学生毕业了，他要去微软也好，
他要卖猪肉也好，他要创业也好，他要做游戏代练也好，只要不犯法，不害人，都没有什么关系，要紧的是，选择了以后怎么把事情做好。<br />
除了这些，你还
可以选择时间和环境。比如，你可以选择把这辈子最大的困难放在最有体力、最有精力的时候，也可以走一步看一步，等到了40岁再说。只是到了40多岁，那正
是一辈子最脆弱的时候。上有老下有小，如果在那个时候碰上了职业危机，实在是一件很苦恼的事情。与其如此，不如在20多岁30多岁的时候吃点苦，好让自己
脆弱的时候活得从容一些。你可以选择在温室里成长，也可以选择到野外磨砺，你可以选择在办公室吹冷气的工作，也可以选择40度的酷热下去见你的客户。只
是，这一切最终会累积起来，引导你到你应得的未来。<br />
我不敢说所有的事情你都有得选择，但是绝大部分事情你有选择，只是往往你不把这当作一种选择。认真对待每一次选择，才会有比较好的未来。<br />
<strong>九、选择职业</strong><br />
职
业的选择，总的来说无非就是销售、市场、客服、物流、行政、人事、财务、技术、管理几个大类。有个有趣的现象就是，500强的CEO当中最多的是销售出
身，第二多的人是财务出身，这两者加起来大概超过95％。现代IT行业也有技术出身成为老板的，但实际上，后来他们还是从事了很多销售和市场的工作，并且
表现出色，公司才获得了成功。完全靠技术能力成为公司老板的，几乎没有。这是有原因的，因为销售就是一门跟人打交道的学问，而管理其实也是跟人打交道的学
问，这两者之中有很多相通的东西，它们的共同目标就是&#8220;让别人去做某件特定的事情。&#8221;而财务则是从数字的层面了解生意的本质，从宏观上看待生意的本质，对
于一个生意是否挣钱，是否可以正常运作，有着最深刻的认识。<br />
公司小的时候是销售主导公司，而公司大的时候是财务主导公司。销售的局限性在于只看人
情不看数字，财务的局限性在于只看数字不看人情。公司初期，运营成本低，有订单就活得下去，跟客户也没有什么谈判的条件，别人肯给生意做已经谢天谢地了。
这个时候订单压倒一切，客户的要求压倒一切，所以当然要顾人情。公司大了以后，一切都要规范化，免得因为不规范引起一些不必要的风险，同时运营成本也变
高，必须提高利润率，把有限的资金放到最有产出的地方。对于上市公司来说，股东才不管你客户是不是最近出国，最近是不是哪个省又在搞严打，到了时候就要把
业绩拿出来，拿不出来就抛股票，这个时候就是数字压倒一切。<br />
前两天听到有人说一句话觉得很有道理：开始的时候我们想&#8220;能做什么&#8221;，等到公司做大了
有规模了，我们想&#8220;不能做什么&#8221;。很多人在工作中觉得为什么领导这么保守，这也不行那也不行，错过很多机会。很多时候是因为你还年轻，你想的是&#8220;能做什么
&#8221;，而作为公司领导要考虑的方面很多，他比较关心&#8220;不能做什么&#8221;。<br />
我并非鼓吹大家都去做销售或者财务，究竟选择什么样的职业，和你究竟要选择什么
样的人生有关系。有些人就喜欢下班按时回家，看看书听听音乐，那也挺好，但就不适合找个销售的工作了，否则会是折磨自己。有些人就喜欢出风头，喜欢成为一
群人的中心，如果选择做财务工作，大概也干不久，因为一般老板不喜欢财务太积极，也不喜欢财务的话太多。先想好自己要过怎样的人生，再决定要找什么样的职
业。有很多的不快乐，其实是源自不满足。而不满足，很多时候是源自于心不定。而心不定则是因为不清楚究竟自己要什么，不清楚要什么的结果就是什么都想要，
结果什么都没得到。<br />
我想，我们还是因为生活而工作，不是因为工作而生活。生活是最要紧的，工作只是生活中的一部分。我总是觉得生活的各方方面都是
相互影响的，如果生活本身一团乱麻，工作也不会顺利。所以要有娱乐，要有社交，要锻炼身体，要有和睦的家庭&#8230;&#8230;最要紧的，要开心。我的两个销售找我聊天，
一肚子苦水。我问他们，2年以前你什么都没有，工资不高，没有客户关系，没有业绩，处于被开的边缘，现在的你比那时条件好了很多，为什么现在却更加不开心
了？如果你做得越好越不开心，那你为什么还要工作？首先的首先，人还是要让自己高兴起来，让自己心态好起来。这种发自内心的改变会让你更有耐心，更有信
心，更有气质，更能包容&#8230;&#8230;否则，看看镜子里的你，你满意么？<br />
有人会说，你说得容易，我每天加班，不加班老板就会把我炒掉，每天累得要死，哪有时
间娱乐、社交、锻炼？！那是人们把目标设定太高的缘故。如果你还在动不动就会被老板炒掉的边缘，那么你当然不能设立太高的目标，难道你还想每天去打高尔
夫？！你没时间去健身房锻炼身体，但是上下班的时候多走几步可以吧，有楼梯的时候走走楼梯不走电梯可以吧，办公的间隙扭扭脖子、拉拉肩膀、做做俯卧撑可以
吧&#8230;&#8230;谁规定锻炼就一定要拿出每天2个小时去健身房？！你没时间社交，每月参加郊游一次可以吧，周末去参加个什么音乐班，绘画班之类的可以吧，去尝试认识
一些同行，和他们找机会交流交流可以吧&#8230;&#8230;开始的时候总是有些难的，但迈出这一步就会向良性循环的方向发展。而每天工作得很苦闷，剩下的时间用来咀嚼苦
闷，只会陷入恶性循环，让生活更加糟糕。<br />
虽然离开惠普仅有十五天，但感觉上惠普已经离我很远。我的心思更多得放在规划自己第二阶段的人生，这并非代表我对惠普没有任何眷恋，主要还是想以此驱动自己往前走。<br />
万科的王石登珠穆朗玛峰的体验给我很多启发。虽然在出发时携带大量的物资，但是登顶的过程中，必须不断减轻负荷，最终只有一个氧气瓶和他登上峰顶。登山如此，漫长的人生又何尝不是。<br />
我宣布退休后，接到同事、朋友、同学的祝贺。大部分人都认为我能够在这样的职位上及年龄选择退休，是一种勇气，也是一种福气。 还有一部分人怀疑我只是借此机会换个工作，当然还有一些人说我在HP做不下去了，趁此机会离开。<br />
我多年来已经习惯别人对我的说三道四，但对于好友，我还是挺关心大家是否真正理解我的想法，这也是写这篇文章的目的。<br />
由于受我父亲早逝的影响，我很早就下定决心，要在有生之年实现自己的愿望。我不要像我父亲一样，为家庭生活忙碌一辈子，临终前感伤，懊恼自己有很多没有实现的理想。<br />
一本杂志的文章提到我们在生前就应该思考自己的墓志铭，因为那代表你自己对完美人生的定义，我们应该尽可能在有生之年去实现它。我希望我的墓志铭上除了与家人及好友有关的内容外，是这样写着：<br />
1. 这个人曾经服务于一家全球最大的IT公司（HP）25年，和她一起经历过数次重大的变革，看着她从以电子仪表为主要的业务变革成全球最大的IT公司。<br />
2. 这个人曾经在全球发展最快的国家（中国）工作16年，并担任HP中国区总裁7年，见证及经历过中国改革开放的关键、最新突破阶段，与中国一起成长。<br />
3. 这个人热爱飞行，曾经是一个有执照的飞行员，累积飞行时数超过X小时，曾经在X个机场起降过。<br />
4. 这个人曾经获得管理硕士学位，在领导管理上特别关注中国企业的组织行为及绩效，并且在这个领域上获得中国企业界的认可。<br />
我
费时25年才总结第1和第2两项成果，我不知还要费时多久才能达成第3和第4的愿望。特别是第4个愿望需要经历学术的训练，才能将我的经验总结成知识，否
则我的经验将无法有效影响及传授他人。因此，重新进入学校学习，拿一个管理学位是有必要的，更何况这是我一个非常重要的愿望。<br />
另一方面，我25年
的时间都花在运营(Operation)的领域，兢兢业业的做好职业人士的工作。这是一份好工作——特别是在HP——这份工作也帮助我建立财务的基础，支
持家庭的发展。但是我不想终其一生，都陷入在运营的领域，我想像企业家一样，有机会靠一些点子(Ideas)赚钱。虽然风险很高，但是值得一试。即使失
败，也不枉走一回，这也是第4个愿望其中的一部份。<br />
Carly Fiorina曾经对我说过：&#8220;这个世界上有好想法的人很多，但有能力去实现的人很少。&#8221;2007年5月21日在北大演讲时，有人问起哪些书对我影响较大。我想对我人生观有影响的其中一本书叫&#8220;<strong><em>TriggerPoint</em></strong>&#8221;，它的主要观点是：人生最需要的不是规划，而是在适当的时机掌握机会，采取行动。<br />
我
这些愿望在我心中已经酝酿一段很长的时间，开始的时候，也许一年想个一两次，过了也就忘掉，但逐渐的，这个心中的声音愈来愈大，出现的频率也愈来愈高。当
它几乎每一个星期都会来与我对话时，我知道时机已经成熟。但和任何人一样，要丢掉自己现在所拥有的、所熟悉的环境及稳定的收入，转到一条自己未曾经历过、
存在未知风险的道路，需要绝大的勇气、家人的支持和好友的鼓励。有舍才有得，真是知易行难，我很高兴自己终于跨出了第一步。<br />
我要感谢HP的EER
提前退休优惠政策，它是其中一个关键的TriggerPoints，另一个关键因素是在去年五六月发生的事。当时我家老大从大学毕业，老二从高中毕业。在
他们继续工作及求学前，这是一个黄金时段，让我们全家可以相聚一段较长的时间，我为此很早就计划休一个长假，带着他们到各地游玩，但这个计划因为工作上一
件重要的事情（Mark
Hurd访华）不得不取消。这个事件刺激了我必须严肃地去对待那心中的声音，我会不会继续不断的错失很多关键的机会?我已经年过50，我会不会走向和我父
亲一样的道路？<br />
人事部老总Charles跟我说，很多人在所有对他有利的星星都排成一列时，还是错失时机。我知道原因，因为割舍及改变对人是多么
的困难。我相信大部分的人都有自己人生的理想，但我也相信很多人最终只是把这些理想当成是幻想，然后不断地为自己寻找不能实现的藉口。南非前总统曼德拉曾
经说过：&#8220;与改变世界相比，改变自己更困难。&#8221;真是一针见血。<br />
什么是快乐及有意义的人生？我相信每一个人的定义都不一样。对我来说，能实现我墓志铭上的内容就是我的定义。在中国惠普总裁的位置上固然可以吸引很多的关注及眼球，但是我太太及较亲近的好友都知道那不是我追求的，那只是为扮演好这个角色必须尽力做好的地方。<br />
做一个没有名片的人士，虽然只有十多天的时间，但我发现我的脑袋里已经空出很多空间及能量，让我可以静心的为我ChapterII的新生活做细致的调研及规划。<br />
我预订以两年的时间来完成转轨的准备工作，并且花多点时间与家人共处。这两年的时间我希望拿到飞行执照，拿到管理有关的硕士学位，提升英文的水平，建立新的网络，多认识不同行业的人，保持与大陆的联系。希望两年后，我可以顺利回到大陆去实现我第四个愿望。<br />
毫不意外，在生活上，我发现很多需要调整的地方。<br />
二
十多年来，我生活的步调及节奏几乎完全被公司及工作所左右，不断涌出的Deadline及任务驱动我每天的安排。一旦离开这样的环境，第一个需要调整的就
是要依靠自己的自律及意志力来驱动每天的活动。睡觉睡到自然醒的态度绝对不正确，放松自己，不给事情设定目标及时间表，或者对错失时间目标无所谓，也不正
确。没有年度，季度，月及周计划也不正确。<br />
担任高层经理多年，已经养成交待事情的习惯，自己的时间主要花在思考、决策及追踪项目的进展情况。更多
是依靠一个庞大的团队来执行具体的事项，及秘书来处理很多协调、繁琐的事情。到美国后，很多事情需要打&#8220;800电话&#8221;联系，但这些电话很忙，常让你在
Waitingline上等待很长的时间。当我在等待时，我可以体会以前秘书工作辛苦的地方，但同时也提醒我自己，在这个阶段要改变态度，培养更大的耐性
及自己动手做的能力。<br />
生活的内容也要做出很大的调整，多出时间锻炼身体，多出时间关注家人，多出时间关注朋友，多出时间体验不同的休闲活动及飞行。一步步的，希望生活逐步调整到我所期望的轨道上，期待这两年的生活既充实又充满乐趣及意义。<br />
第
一个快乐的体验就是准备及参加大儿子的订婚礼。那种全心投入，不需担忧工作数字的感觉真好。同时我也租好了公寓，买好了家具及车子，陪家人在周末的时候到
Reno及Lake
Tahoe玩了一趟。LakeTahoe我去了多次，但这次的体验有所不同，我从心里欣赏到它的美丽。但同时我也在加紧调研的工作，为申请大学及飞行学校
做准备，这段时间也和在硅谷的朋友及一些风险投资公司见面，了解不同的产业。<br />
我的人生观是：&#8220;完美的演出来自充分的准备；勇于改变自己，适应不断变化的环境，机会将不断出现；快乐及有意义的人生来自于实现自己心中的愿望，而非外在的掌声&#8221;。<br />
我
离开时，有两位好朋友送给我两个不同的祝语，Baron的是&#8220;多年功过化烟尘&#8221;，杨华的是&#8220;莫春者，风乎舞雩，咏而归&#8221;，它们分别代表了我离开惠普及走向
未来的心情。我总结人生有三个阶段：一个阶段是为现实找一份工作，一个阶段是为现实但可以选择一份自己愿意投入的工作，一个阶段是为理想去做一些事情。<br />
我珍惜我的福气，感激HP及同事、好朋友给我的支持、鼓励及协助，将这篇文字化我心声的文章与好友分享。
</p>
<img src ="http://www.blogjava.net/jhyan/aggbug/243902.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-12-02 12:58 <a href="http://www.blogjava.net/jhyan/archive/2008/12/02/243902.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>写cookie备忘</title><link>http://www.blogjava.net/jhyan/archive/2008/11/13/240321.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Thu, 13 Nov 2008 07:02:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/11/13/240321.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/240321.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/11/13/240321.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/240321.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/240321.html</trackback:ping><description><![CDATA[<br />
写cookie时，cookie的内容不能包含分号（；），否则在ie下会造成cookie内容不完整，ff下没有问题，估计是因为ie根据分号解析cookie<br />
<br />
<br />
比如，正常情况下，<br />
<br />
cookie1=value1<br />
cookie2=value2<br />
<br />
但是，如果<br />
<br />
cookie1="value1;value11;value12"<br />
cookie2=value2<br />
<br />
在ie下面可能会造成<br />
<br />
cookie1="value1<br />
cookie2=value2<br />
<br />
还有可能是：<br />
<br />
cookie1="value1;value11;value12;cookie2=value2"<br />
<br />
<br />
<img src ="http://www.blogjava.net/jhyan/aggbug/240321.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-11-13 15:02 <a href="http://www.blogjava.net/jhyan/archive/2008/11/13/240321.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>超越SOA：动态业务应用的新企业应用框架（2）转载</title><link>http://www.blogjava.net/jhyan/archive/2008/10/06/232644.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Mon, 06 Oct 2008 05:08:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/10/06/232644.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/232644.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/10/06/232644.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/232644.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/232644.html</trackback:ping><description><![CDATA[<h3>第二部分：动态业务应用构建实践——两个自适应系统的故事</h3>
<p>生产力提高是生活水平提高的基本组成。美国的经验表明，长期的生产力强劲增长表现为伴随组织结构和企业资金安排变化的技术革新，以及人力资本的投
入。但是，支撑这些生产力增长的决定因素的是一个更基本的因素：社会对其自身进行重大转变的意志，以及对技术进步和随那个进步而来的经济机会将使人们改善
其生活的信心。<a href="http://www.infoq.com/infoq/url.action?i=272&amp;t=f" target="_blank"></a><br />
</p>
<p>&#8211;Roger W. Ferguson Jr.和William L. Wascher，美国经济学会在政府中做的经济专题演讲：过去生产力大爆炸的教训，《经济学展望杂志》，2004年春季18卷，第2期</p>
<p>&#8220;一旦着手自动化这些[企业]流程，技术实现大约占10%，其余90%都是变更和流程管理&#8221;</p>
<p>&#8211;Mark Evans，Tesoro Petroleum的CIO，管理自动化，2004年3月</p>
<h4>第一部分总结</h4>
<p>在<a href="http://www.infoq.com/cn/articles/dynamic-business-applications">本文的第一部分</a>，
我们介绍了一种构建新型IT系统的企业架构，我们称之为动态业务架构（DBA）。这些DBA非常适合支持具有动态操作（包含最新业务的一个分类）的企业。
第一部分还指出，用例是当前系统架构和设计的基本输入，并描述了依赖通过它收集的需求对当前企业架构方法的种种制约。这一新提出的新框架使用企业事件模型
作为起点，并将企业视为一个具有清晰信息架构的自适应系统。以新的自适应系统和信息理论为基础，在基础层级，该框架同时捕捉企业流程和业务变更。用例仅在
设计过程的后期作为一种需求细化方法被引入。这种框架优先的方式受到了传统工程方法学的启发，但针对像企业这样的自适应系统进行了修改。</p>
<h4>介绍</h4>
<p>告别手工作坊并向软件工程加入正确工程技术的时候到了。这是将复杂软件应用（尤其是在企业领域中）构建成高度可靠、易于改变和方便调试的公共标准的
唯一方法。选择并执行正确的系统架构是使这种方法发挥作用的最重要因素。我们建议的解决方案使得围绕唯一一个系统架构进行标准化（不考虑软件应用）并避免
成本高昂的重新构架成为可能。</p>
<p>正如本文第一部分提到的，构架软件应用和设计其它工程产品之间有一个根本性的区别。因为软件是和信息打交道，而信息是变更的&#8220;载体&#8221;，那么必须在最
基础的级别将变更构建到信息架构之中。此外，业务操作变更的方式和技术团体将变更引入系统的方式走得是完全不同的路径。它们各自都是对变更反应不同并具有
不同操作的组织（一个是业务和一个是技术）。在构架过程中，可以把这两个组织作为两个不同的自适应系统对待。这正是我们选择&#8220;两个自适应系统的故事&#8221;作为
本文第二部分副标题的原因。</p>
<p>在设计企业应用的过程中涉及两个自适应系统。</p>
<p>本文第一部分提到，能成功应对构建DBA复杂性的唯一方法是使用架构先行的方法论。几个世纪以来，工程师们一直在使用这种方法论——但总是设计&#8220;静
态&#8221;架构。一旦要应用变更，系统极可能必须先停止工作再进行修改。例如，要改变由装配线组装的产品必须先停止装配线，然后应用变更，最后重新启动装配线。</p>
<p>当今为业务构建IT系统的软件工程师们很可能就是遵循的同样套路。当业务变化提出了修改应用的需求时，它很可能就触发了一个成本高昂的升级。开发者
必须从头开始一个新业务需求，并且旧的设计常常经受大量的重新构架。这种升级周期可能需要几个月。如果企业应用是由外部开发商按照自己的日程构建的，那么
整个过程可能耗时更长而且结果可能达不到业务预期。Mark Evans说得好，超过90%的努力只直接和应用变更相关。</p>
<p>籍由新的自适应系统理论和它们信息架构（参见局外人观点）的帮助，我们建议的企业应用设计解决方案引入了两个互补但唯一的框架。这两个框架让我们可
以有效地处理和协调业务操作和技术团体操作中的变更。对设计过程而言，业务操作和技术团体操作可以被视为两个截然不同的自适应系统，它们各自都有自己的需
求。</p>
<p>业务操作可由基础动态业务平台的通用概念来表示。根据自适应系统理论，任何企业业务功能均有3类基础流程。主流程类型支持正常操作，而其他两个则负
责引入变化：内部决策制订流程处理管理和其他企业变更决策；业务环境变更流程处理客户决策和变更的其他外部来源。因此，我们提出的业务流程框架（基本动态
业务平台）是围绕着业务操作或价值循环构建起来的，它包含的两类变更由两个不同的变更管理平台来处理。从信息处理观点来看，实现这些操作的系统可以比作围
绕事件模型构建的&#8220;信息装配线&#8221;（参见第一部分）。企业的业务操作可以按照类似源自丰田精益制造最佳实践的价值流程图（Value Stream
Mapping）方法论的方法来识别。结果是，生命周期/事件模型成为系统设计和架构的主要驱动力，不可靠的用例集合不再是系统架构的主要输入。</p>
<p>技术操作有其自身的挑战和独特的动态性。技术操作的主要目标是如何使不同的团队在引入变更的过程中能最大限度的合作。基础动态业务应用是具有两类流程的自适应系统：操作和操作变更。这两个流程将技术支持（操作）和技术开发（操作变更）与业务用户联系在了一起。</p>
<img alt="" _href="img://Fig1.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig1.jpg" />
<p>图1. 构建和维护基础业务动态平台既需要业务流程框架，也需要业务系统变更管理框架。</p>
<p>两个框架必须合并到一个既考虑技术团队操作，又考虑业务用户活动的独特系统设计中。这个系统是围绕服务器端架构设计的。虽然仿效了它们的结构和控制层次，但是这是为不同类型用户合作提供支持的唯一方法。</p>
<h4>设计服务器端基础设施的复杂性比桌面应用的要高几个数量级</h4>
<p>每个企业软件的设计者都认识到，实现完整的企业客户/服务器应用要比构建桌面应用更复杂。对于桌面应用，接口是围绕一个角色、一个主要任务和一个清
晰接口构建的，整个应用运行在单独一台机器之上。接口可以通过一系列函数实现来构建。对于服务器端应用，实现要复杂得多。复杂性的来源之一就是，服务器端
应用要实现包括管理员在内的多个角色。管理员不可能扮演一个被动角色，他需要一个可以在必要时改变操作参数的界面。此外，为了保证正常使用，技术支持必须
对应用进行监测。</p>
<p>要更好地理解实现桌面应用和实现客户/服务器应用之间的区别，我们可以看看将一个桌面应用变成客户/服务器应用需要经过哪些步骤。假设我们需要使用
作为服务器端应用实现的MS
Word写信。首先，你需要一个技术支持负责设置字体、页面和所有其他设置。每当你需要不同设置的时候，你都必须请求这个技术支持完成变更。在你写信时，
管理员必须审定字体，信头等等。一旦完成这些，同一管理员可能还需在它发送前对其进行审核。这个例子虽然看起来简单，但是它可以帮助我们理解当试图将桌面
开发过程中获得的知识外推到客户/服务器应用时，软件架构师面临的挑战。</p>
<p>事实上，当多个用户在使用同一个应用时（业务上或技术上），它需要完全不同的方法。架构必须是分布式（用户可能在不同地点、使用不同机器）、有状态
（状态不再由硬编码到应用中的下一个窗口来定义）、动态性（管理员或外部用户可能需要一个业务实体能在运行时被改变，类似经理可能要求一个产品或服务不能
再以相同价格出售或客户可能要求订单改变的方式）和层次性（所有组织有一个控制层级，这样不同用户就能对流程进行不同控制）的任务或流程提供支持。所有这
些新性质都必须被内嵌至应用的基础之中，否则它就必须在每次进行变更时被重写。</p>
<p>但是这并非设计服务器端应用的唯一区别。当桌面应用崩溃时，用户只需重启它就行了。因为它实现的是简单任务，重新做一遍即可，即便丢失了大部分数
据。用户并不需要一个专门的技术团队来帮助他运行应用程序。对于客户/服务器应用而言，情况就完全不一样了。由于多个用户同时工作，一旦出现问题，只有具
有技术知识和有权使用工具监测应用的技术支持团队能够制定如何使应用恢复正常操作的决策。并且技术团队自己的操作蓝图完全不同于业务操作蓝图。技术团队有
自己的流程控制层次、自己的分布式环境、自己实现变更的方法和自己的状态。</p>
<p>结果是，构架一个能在企业级运行的客户/服务器应用要比构架一个桌面应用复杂几个数量级。服务器端的主要复杂度源于它必须支持两个自适应系统，一个
是技术团体，另一个是业务团队，他们各自又都有自己的操作和控制层次。在构架同时支持管理和技术支持两个自适应系统的应用时，需要遵守应用于自适应系统及
其相关信息的法则。</p>
<p>在构架这类复杂系统的过程中，如果有一个理想的架构，那么就用不着在每次业务或技术引入变更时重新返工了。理想情形是拥有一个标准组件集合，它具有
用事件模型实现的定义良好的行为。在不同控制级别实现的事件模型将这些组件链接到一个控制层次中。在桌面中，一组自身具有事件模型的定义良好的组件由一个
清晰的控制层级链接到了一起。服务器端就要落后得多了。使用中的J2EE、.NET或其它现存专有架构都缺少为分布式、动态性、有状态和层次性环境提供支
持的基本组件。由于Web标准是无状态、扁平、静态和只针对单服务器的，它们对单个自适应系统都无法提供很大帮助，更别提两个了。</p>
<p>根据自适应系统及其关联信息的法则，一个控制层次总是符合3个模式：</p>
<ul>
    <li>初始化过程总是相同的自顶向下顺序 </li>
    <li>层级之间的信息传播总是遵照确定的规则：命令流自顶向下，反馈流自底向上 </li>
    <li>每个层级有其自身的正常操作，它们在收到一个反馈或命令之前不会改变。处理命令或反馈总是需要变更管理的能力。并且由于有两类交互——命令和反馈——因而需要两类不同的变更管理</li>
</ul>
<p>我们将展示如何使用标准组件（它们一起被链接在一个动态、有状态且分布式的控制层次中）为服务器端应用实现一个标准架构。但是首先，我们将先给出另一个任何计算机使用者都熟悉的以事件为中心的平台。</p>
<h4>微软将它的未来建立在了针对GUI的一系列组件和一个静态事件模型之上</h4>
<p>微软之所以如此成功有许多原因，但是其中一点非常突出。他们不顾来自Apple和IBM的诸多批评和竞争，将Windows操作系统构建成了一个桌
面标准。一种解释可能是，微软是第一家不仅提供与Apple利用Mac完成的工作类似的操作环境，而且还拥有一组最方便的OS和GUI组件的公司。这些组
件被实现成了可供调用的API。利用这个组件模型，包括微软在内的软件公司就能够构建数据库、办公应用和类似Visual
Basic这样的开发工具。这些应用都能利用被构建成结构体和控件的Windows内置层次事件模型。</p>
<p>在开发Windows时，微软拥有的优势在于，大多数OS和GUI的主要组件，连同它们的事件模型一起，要么已经是现成的，要么就是可以凭直觉方便
地构建。对于任何桌面应用来说，控制层次看起来异乎寻常的简单。在GUI栈的顶端是扮演其余GUI组件容器的各个窗口。打开窗口，内嵌的控件也就自动地被
初始化。关闭窗口，每个组件也跟着一起关闭。用API捕获那些事件以及Windows应用的开发都和一个插件架构十分相称。</p>
<a _href="resource://Fig2_lg.jpg" href="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig2_lg.jpg"><img alt="" _href="img://Fig2.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig2.jpg" /></a>
<p>图2. 微软Windows控制层次模型——一个用户、一个应用、一个位置、一组静态功能</p>
<p>这些API的实现就是Windows操作系统自身。它是控制初始化过程的那个层级，也是最终必须处理错误而不是崩溃或丢失数据的层级。在服务器端，
组件、它们的事件和控制层次被一个需求搞复杂了，那就是为有状态、动态、分布式和层次性任务提供本地支持。这正是自适应企业操作平台（AEOP）的主要目
标。</p>
<h4>围绕动态结构和控制进行设计，AEOP提高了生产力</h4>
<p>一些年前，IBM招募了上千名企业架构师决心降低它们各垂直行业的客户化解决方案个数。一年多之后，他们将它们的数目由超过60个降低到了不到20
个。付出巨大的努力和不算优秀的结果显示了问题的巨大。尽管投入了庞大的资源，但IBM确实难以创建能对他们客户都适用的通用解决方案，不管他们在行业的
深度和公司大小。一种可能令他们努力复杂化的一件事是，他们是以一组不完善的遗留解决方案开始的。</p>
<p>我们的目标是相同的：创建一个几乎普遍适用于所有行业的通用解决方案。如果有从一个新鲜想法开始的自由，我们一开始就会关注那些我们认为最重要的基
本原则。大多数企业架构虽然依赖现有技术、组件或象SOA这样的趋势，但是AEOP架构要优于它们。它从一开始就认识到技术在企业中扮演的根本角色就是提
高生产力。这个角色对所有技术解决方案（不论它是否是IT）都是有效的。在IT情形下，由于业务的动态性和存在于企业系统各用户之间的复杂关系，架构需要
围绕企业流程的结构、控制和动态性来构建。</p>
<p>这种方法还提供了一种手段来解决由Nicholas Carr的《IT没什么大不了的（IT doesn't
matter）》产生的讨论，该文发表于2003年5月的《哈佛商业评论》。询问IT是否是业务相关的，就好像询问装配线是否是业务相关的一样。它不仅对
诸如通用或丰田这样的公司至关重要，而且是任何一家制造业公司的一部分，包括象Intel这样的高科技行业明星。装配线的影响力对那些定制产品或服务无处
不在的行业（如食品或保健领域）来说要小得多。虽然在象通用这样的公司看来装配线是重要的，但是它不过是高生产力的促成因素。相同的事实也适用于IT，它
可能对那些依赖信息处理运营的公司来说是一回事，但是对其他公司可能就无关紧要了。IT唯一的不同之处在于，它远没有装配线技术成熟。</p>
<p>要分析IT如何能提高生产力，就要了解那些决定了技术如何被交付和使用的基本商业机制。我们必须看看信息处理的基本角色，并询问驱动企业运营的核心
信息元素是什么。在工程领域，这一过程得到了相当好的理解，可以从几个例子看出这一点。当一个工程师开始设计一架飞机时，他从来不会把飞机看作一个诸如螺
母、螺钉、电线、连接器、泵、电动发动机、杠杆、面板等这样零件的集合。他查看连接它们的方式和它们在交付功能过程中扮演的角色。一架飞机的结构是围绕机
翼、引擎、座舱和主机身建造的，并采用一种能够最大化不同参与者间交互的控制层级。建筑师在设计一栋房子时也是这样。在建筑师清楚房中需要的卧室数目和生
活的家庭人员个数之前，待安装的空调、器具或电线型号都不重要。</p>
<p>在当今的方法中，企业软件大多都是围绕技术组件和标准被构架/设计的。需求是一种评估生产力增长或企业软件结构、控制和动态性的一种补救方法。事实
上，高级别架构推荐只以表现层、业务层和持久层为中心。当前还没有一种架构方法提供一个解决方案来支持现实中的动态、分布式、有状态和层次的业务流程架
构。</p>
<p>为了更好地类比，不妨让我们看看工程师是如何设计装配线的。首先，它们以易于维护和维修为设计目标。这就是为什么装配线架构和设计是围绕可交换性、
模块化和标准化组件建造的原因。由于装配线不会动态变化，那么第二个标准就是要易于针对新模型重新进行配置。这正是机器人在装配线上如此流行的原因。不管
任务有多复杂，都可以方便地针对范围广泛的当前和将来任务重新编程。只有在这两个标准被满足之后，设计工程师才会着手努力最优化每个特殊的任务。</p>
<p>为了构架/设计一个通用的AEOP，我们识别出了3个需要在设计中被解决的基本因素，它们对生产力的提高有重大影响。它们几乎对所有企业都是相同的，不论这些企业涉及的领域或生产规模：</p>
<p><strong>1）通过为技术支持、开发人员和业务用户之间的合作操作提供支持，提高技术团队操作的生产力</strong></p>
<p>对整个架构影响最大的是不同技术团队和业务用户之间的关系以及需求变更引入的方式。由于IT团队是在应用上花费时间最多的一个团队，提高它的生产力应该是架构的首要任务。</p>
<p>在这一背景下，技术团队正常操作的结构与控制并不复杂。业务用户打开一个触发业务事件的应用。这些事件使应用处理信息。技术支持团队监测应用。应用虽然处于生产环境，但是开发团队常常要计划下次升级并实现新的需求变更。</p>
<p>整个处理的控制遵循相同的层次架构：在控制金字塔的顶端是开发者团队。因为是他们实现未来的功能，他们对实现拥有所有控制权。接下来是技术支持团
队，因为他们可以停止和重启服务器或改变部分系统配置。对应用拥有最小控制权的团队包括业务用户、经理或工人。他们对应用脚本只能唯命是从。</p>
<p>由于企业是动态的，功能变更的请求可能出现得非常早，甚至在应用安装和运转之前。事实上，需求只有在下次开会的时候才生效。结果，在我们查看什么对
生产力有驱动作用的时候就会发现，如何将变更转换为代码是一个重要因素。在AEOP中，当发生变更时，你会发现总是存在同样的用户组。开发团队是接受变更
请求的团队，监测应用的团队安装它并接受配置来支持它，接着是业务团队接受培训来使用新功能。</p>
<p>作为这个结构和控制层级的结果，企业应用的顶层总是围绕3个平台构建的：一个为开发团队实现功能、一个为技术支持团队实施它和一个支持业务用户。它们每个都有自己的主生命周期和驱动设计的事件模型。</p>
<p>因为AEOP主要是支持技术团队操作的动态性，所以这种&#8220;3个平台&#8221;的结构、它们的组件和事件模型都是围绕变更请求的生命周期而构建的。</p>
<p><strong>2）通过为3类基本业务用户之间的合作事件提供支持，提高业务操作的生产力</strong> </p>
<p>不同类型基本业务用户间合作是生产力的第二大影响因素。在任何企业流程中最多有3类基本用户，分别代表了自适应系统的3个方面：代表操作的工人、代
表决策制定流程的经理和代表经济环境（它使价值循环成为闭环）的客户。价值循环的其他业务参与者，如供应商和政府代理，都扮演次要角色，并且它们的流程都
可以使用这3种基本流程（操作、管理和环境）中的一个标识。</p>
<p>业务是动态的。业务中最大的生产力杠杆之一是变更引入流程的效率。业务中有两类变更：经理引入的内部变更和消费者引入的外部变更。这些变更在某个时
间作为更新被引入到企业应用中。一个有效的架构/设计必须解决这种动态性。一种理想的企业应用架构能够只需最少的代码和配置改变就能适应大多数变更。由于
业务日益依赖支持它们运营的技术，一个快速而有效的更新应用方法对整个生产力十分重要。</p>
<p>基于这一点，AEOP针对业务操作中的高级合作只定义了3类企业架构：</p>
<ul>
    <li>静态架构：纯操作性的——目前所有的企业软件都属于此类。除了最简单的配置变更之外，完成业务流程变更通常都至少要求IT部门停止应用的运转。静态架构的行为类似于汽车制造商在引入新模型时停止装配线。</li>
    <li>仅
    内部（内部决策）驱动的动态架构：提供了对动态操作的支持并实现了经理和工人之间的关系。在这种情况下，在正常操作期间，以及在变更动态应用于当前所有实
    例时，经理决策是被自动考虑到的。因为经理和工人在不同的时间线上操作，他们需要处理内部决策的变更管理平台来嫁接他们的活动。客户在其中不扮演指导角色
    的那些流程都属于这个类别。</li>
    <li>扩展的（内部和外部决策）动态架构：提供了对动态操作的支持并使全部3类基本用户（工人、经理
    和客户）之间的合作自动化。这是最复杂的业务操作架构。它有两个不同的变更管理平台，一个针对正常操作应用于内部决策的方式，另一个针对那些希望改变订单
    在正常操作时的执行方式的客户。</li>
</ul>
<p>注意，在任何企业中，不论什么类型的业务流程，它总是与管理&#8220;命令和控制&#8221;的结构和客户反馈&#8220;相连&#8221;的。结果，不论应用的目标业务流程是什么，每个应用都属于&#8220;全动态类别&#8221;。</p>
<p>操作平台架构的动态性是以业务变更生命周期为中心的。它们受内部决策（经理制定内部决策）和外部变更（客户可以决定给进行中的已有订单和服务施加变化）驱动。</p>
<p><strong>3）通过提供在生命周期/事件级别完全解耦的架构，提高开发团队的生产力</strong> </p>
<p>前一个生产力因素跟业务变更对架构/设计的影响息息相关。理想情况下，架构/设计中的业务变更可以通过变更管理模块的界面来完成。该界面使经理和客户有权自动向工作中所有操作应用变更。</p>
<p>有时，变更需要开发团队实现新功能。在实现新功能时，应用的架构/设计应该支持高生产力。</p>
<p>当前方法是将一系列组件归到有数据库访问权限的&#8220;业务层&#8221;上。这种设计有一个基本错误。在这一设计中的数据库很可能是关系数据库，它保存层次性信息或有状态信息的能力很差。它们很可能依赖缓存机制，它们需要消耗惊人的计算资源，在后台持续更新大量数据。</p>
<p>无论怎样，企业中的所有业务流程都会链接到主业务实体（一个产品或一个服务）。对于一个链接到主业务实体的业务流程来说，现有历史是最重要的方面。
即使对最简单的交易来说也是如此。去一个商店买东西的前提是，你的金融资源将为你提供购买产品所需的足够金融&#8220;资源&#8221;，而且商店有&#8220;待售&#8221;的产品。一个实
体的历史由最终描述它整个生命周期的事件组成。由于可能改变实体状态的事件可以在业务结构内的任何位置和多个控制级别被触发，围绕这个业务实体动态构建的
AEOP架构必须是有状态、层次性和分布式的。</p>
<p>由于生命周期围绕事件而构建，围绕它们可以构建整个AEOP。任何事件实现都可以按照同一种通用方法完成：整个生命周期可以被认为是反映主业务实体
转换信息的&#8220;装配线&#8221;。因此，可以用相同的结构来实现事件，并装配：1）从各需要位置（分布式）检索出来的信息元素；2）在某一时刻瞬间存在的（如，检索
一张信用卡交易的账户信息必须以实时方式完成）信息元素；3）可由一定的业务流程实现的信息元素；4）已经应用了一定的业务规则的信息元素。</p>
<p>AEOP的另一个优势是能够围绕同一个事件模型设计两类变更管理。最终，这个操作平台的实现可以在事件级别解耦。操作平台可以作为一个插件API基础设施来构建，就像Windows API是围绕着桌面集成事件模型构建的一样。</p>
<p>需要注意的是，文献中记载的EDA（事件驱动架构）跟AEOP事件模型是不一样的。EDA是围绕非结构化事件流构建的，而AEOP是围绕由一组生命周期模板链接在一起的结构化事件流构建的。</p>
<a _href="resource://Fig3_lg.jpg" href="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig3_lg.jpg"><img alt="" _href="img://Fig3.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig3.jpg" /></a>
<p>图3. AEOP控制层次模型——按变更类型分组的多个用户、多个客户端应用、多个分布地点、多个静态功能</p>
<p>组件及其事件的AEOP层级包含5级：</p>
<ul>
    <li>OS级：在这里可以找到所有OS组件，如内核、文件系统、网络和I/O。OS可能还有GUI组件，运行监测各种应用及其活动的图形化工具时会用到它们。 </li>
    <li>技
    术级：在这里可以找到所有传统的基于服务器的组件，如应用服务器、BPM引擎、业务规则引擎、数据库。这儿还有实现了Web和Web服务、消息传递等标准
    的组件。它们或多或少扮演了和飞机设计中标准零部件相同的角色。螺母、螺钉、电动发动机、液压泵、电线、连接器、座椅、电子面板、马达对许多其他工业设备
    都是通用的，不只限于飞机。可是它们在尽可能简化和标准化设计的过程中扮演了一个关键角色。</li>
    <li>AEOP技术操作级：这是拥有
    特定于AEOP组件的顶级级别。这里有3种组件——安装/启动/持久化/恢复平台、系统平台和操作平台。它们分别代表了合作运行客户/服务器应用的3个小
    组：业务用户团队、技术支持团队和开发团队。每个组件实现了特定的事件，如技术支持团队能监测错误和重启应用。对于那些需要和外部系统合作的应用，还存在
    被称为外部系统监督者平台的第4类组件。这个组件管理与外部系统交互的初始化、正常操作和错误翻译。</li>
    <li>AEOP业务操作级：它是业务实现的顶级级别，在操作平台之下的一级。它也包含了3个主要组件：正常操作、内部决策管理变更和外部环境交互（即客户决策）管理变更。这里包括许多其他组件，如外部系统操作翻译器、系统Map、许可证管理器等。 </li>
    <li>AEOP事件处理级：这是实现的插件级。在这一级实现了被激活业务流程的整个正常操作。由于每个功能被分解成了事件级的函数，整个架构围绕事件模型被解耦了。这可以包括操作错误、操作变更，以及甚至安全访问。</li>
</ul>
<p>显然，在这个AEOP的简短描述中还有很多组件和事件没有被覆盖到。在下一节我们将围绕这3个组件进一步分析其细节。</p>
<p>AEOP事件模型和事件驱动架构（EDA）之间存在着差异。EDA是一种提倡产生事件、检测事件、消费事件、对事件做出反应的软件架构模式（来自维
基百科）。EDA缺失的是如何捕捉业务流程的结构和控制。此外，AEOP区别了3类事件，一个针对正常操作、一个驱动内部变更和一个针对外部变更。它们负
责不同的待处理模块，而EDA则使用相同的方法处理所有模块。AEOP使用生命周期在一个分布式、层次、有状态和动态的结构中将事件分组。</p>
<h4>AEOP中的信息&#8220;装配线&#8221;是围绕动态生命周期模式的多联装（Multi-shell）容器构建的</h4>
<p>所有现代软件平台都是围绕某种形式的容器模式构建的。AEOP也不例外。基于J2EE的应用服务器甚至有两类容器：Servlet和EJB。操作系
统可被视为是一种应用程序的容器。容器的概念和&#8220;计算机资源是有限的&#8221;这一思想有一定联系。容器在AEOP架构中的使用是不同的：</p>
<ul>
    <li>容器创建和管理的对象是业务实体资源的直接表示。例如，AEOP操作容器管理整个订单生命周期，不仅仅是反映现有计算机资源的对象。 </li>
    <li>容器可以区分作为正常事件序列一部分、改变受管资源状态的调用和触发正常操作之外变更的调用。由于存在两类变更，因而每个容器都关联两类变更管理模块。为了提供比现有静态架构更好的企业动态现实支持，AEOP容器支持受管资源的动态生命周期。 </li>
    <li>容
    器并非类似J2EE应用服务器中的单独结构。各容器按照控制层次链接在了一起。集成的事件模型驱动了系统外产生事件的接收和处理。在这种情况下，既不在最
    顶端也不在最底端的容器扮演了双重角色，一个作为资源生命周期管理器，另一个作为受管理的资源。这就是给予系统容器的多联装（Multi-shell）结
    构。</li>
</ul>
<p>整个AEOP架构和实现是围绕描述容器（它管理代表真实业务实体的资源）的模式而构建的，对正常操作和变更进行了区别，是反映业务控制层级的结构的一部分。</p>
<img alt="" _href="img://Fig4.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig4.jpg" />
<p>图4. AEOP多联装（Multi-shell）容器架构将技术置于顶端，业务操作置于中间，事件处理置于底部</p>
<p>每个AEOP容器可能处理3类事件：（1）由&#8220;事件模型&#8221;模块标识的正常操作；（2）来自由控制层级中上层容器发出的内部变更的事件；或（3）来自由控制层级中下层容器发出的外部变更的事件。</p>
<p>除了主生命周期及其关联的事件模型，那里还有被认为是正常操作&#8220;静态部分&#8221;的业务实体。例如，在正常操作期间不期望改变的项目价格或物理位置。它们
是通过所谓的&#8220;静态模型&#8221;的模块捕捉到的。这并不意味着它们就是固定且隔离于业务动态之外。静态模型只有通过变更管理流程使用内部和外部变更来更新。</p>
<p>AEOP控制层次可被用来设置容器的模式：初始化、操作和关闭。只有处于操作模式的容器才能处理事件。</p>
<p>在AEOP架构中，有3个相关元素：1）组件和控制的高级别技术结构，2）操作平台，3）事件处理平台。</p>
<p>高级别AEOP技术代表整个应用，该应用可被认为是一个自适应系统。它有3个主要平台，并且它们各自也都可被认为是一个自适应子系统：上面的平台扮
演了管理角色，下面的平台扮演了环境角色。每个平台自己都有定义良好的、实现了自身功能的事件模型，并且它还要和其他两个进行交互。在每个平台上我们都可
以发现一个仓储，它可以是一个缓存数据库或一个较传统的关系数据库。</p>
<p>与外部系统的集成遵循相同的事件模型。根据外部系统类型的不同，可以使用的集成策略有两种。如果AEOP只有访问持久化仓储的权限，它可以使用始终
运行的调度任务来查看数据库记录中的数据变更。第二个方法依赖API调用，如果可以将外部系统实现改成在主业务实体变更时发起调用，那么就可以实施这个策
略。</p>
<img alt="" _href="img://Fig5.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig5.jpg" />
<p>图5. 高级别AEOP多联装（Multi-shell）容器架构</p>
<p>这3个平台中的每一个也都是围绕特定生命周期元素构建的。操作平台围绕主业务实体生命周期，系统运行时平台围绕用户会话，安装/持久化平台围绕版本控制生命周期。</p>
<p>虽然数据只能按照苛刻的事件模型蓝图来处理，但是相同的数据却可以被任何有权访问系统且有正确证书的用户访问。但是，很少有针对平台用户的数据查看
工具。例如，系统运行时平台有一个针对运行时错误的查看器，它被用来监测用户和分布式系统。这一工具也可在各子系统失效时重新启动它们。</p>
<p>AEOP技术级还实现了一个完整的初始化过程。启动过程中，在用户可以运行第一个任务之前，应用必须经历3个步骤：</p>
<ul>
    <li><strong>启动应用：</strong>系统管理员启动主应用。这是通过启动像Tomcat（J2EE
    servlet容器）以及Axis这样的容器（Web服务平台）做到的。应用可以将Spring框架加载到一个轻量级容器中，并使用Spring
    bean配置文件加载初始的&#8220;启动&#8221;模块。&#8220;启动&#8221;模块初始化&#8220;系统&#8221;模块。该模块负责主应用的硬编码配置。它还可能包含对现有远程数据源的硬连接、读取
    远程部署的应用版本的Web服务端点、测试方法和对各种分布式系统的开放互联性，以及提供正常操作、性能和日志相关数据的功能。产生数据的主要用户是开发
    者和技术支持。</li>
    <li><strong>安装/启动/持久化/恢复 &#8220;系统&#8221;模块：</strong>这个模块实现了所有系统相关的功能，包括检查系统配置。它的主要功能是将一个包含所有资源（远程数据源、用户、版本、集群中的服务器、连接、安全数据等）及其状态的系统Map载入缓存。该模块提供了应用监视器。这个模块的主要用户是技术支持。步骤：
    <ul>
        <li>此阶段的第一个步骤是验证分布式系统上线并正在运行。如果远程系统没有激活，一个被调度的操作变更将被发送给操作系统，由它使那些依赖它们的任务无效。它还将把它们的缓存数据设为&#8220;过时&#8221;。它还将给应用仪表盘发送一个信号，并在日志中记录。 </li>
        <li>一旦这个工作完成，它就验证那些远程数据位置的软件版本是否正确。如果不正确，它将使它们失效，并给应用仪表盘发送一个信号和日志记录的动作。 </li>
        <li>最后一步是检查那些远程分布式系统的数据定义。如果它们改变了，将采取同前一活动相同的步骤。</li>
    </ul>
    </li>
    <li><strong>启动主应用运转：</strong>这是用户可以访问应用之前的最后一个步骤。它将操作上下文，连同所有激活的用户实例和它们的状态载入缓存。操作上下文的一部分是指向分布式系统数据及其状态，以及这些分布式系统操作上下文的指针。这个模块的主要用户是业务用户。</li>
</ul>
<img alt="" _href="img://Fig6.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig6.jpg" />
<p>图6. 系统控制层级确定的3个主要容器的状态</p>
<p>初始化之后，同一架构被用来控制主应用的操作就绪状态。它有3个场景：</p>
<ul>
    <li>用户运行/创建查询时产生的错误：这是最普通的场景。一旦错误被操作模型子平台检测到，系统就被设置成&#8220;操作错误&#8221;模式，一
    条消息将被发送给系统模型子平台，并且待显示的新状态/警报被发送给监测主应用的技术支持团队。出于日志记录的目的（这是给开发团队的信息），同一错误将
    被发送给安装/持久化/恢复模型子平台。用户也将收到一条显示当前事件状态以及可用选择的消息。一个选择是由前一步恢复实例。因为整个操作是围绕保证前一
    事件被成功完成的事件模型构建而成的，这令这一选择成为可能。</li>
    <li>经理或数据源管理员改变操作上下文：在这个情况下，主应用被设置成特殊的&#8220;操作变更&#8221;模式。当前受变更影响、正在运行任务的所有用户都将被通知。他们有两个选择：要么经历一个实例更新过程，要么简单地忽略。 </li>
    <li>产生了一个环境系统错误：在这个情况下，监测IT环境的技术支持团队会得到通知。它是通过能够监测集群或J2EE/NET应用服务器的工具做到的。此时，主应用将试图记录最近的活动或帮助调试的应用服务器堆栈信息。</li>
</ul>
<p>接下来的细节是关于AEOP操作平台的。事件模型是围绕业务实体的类型构建的。每个产品类型的服务有其自己的生命周期，它由自己的事件蓝图表示。事
件蓝图是定义良好的有序事件集合。每个蓝图关联一组变更类型。内部或外部事件可以是正常操作的一部分，或可以代表不同类型的变更。每个事件必须被清晰地标
出，因为它是要被一定的模块处理的。这种方法不同于事件驱动的架构方法，后者将事件视为&#8220;在你的企业内部或外部发生的值得注意的东西&#8221;。它也不同于
EDA，EDA是以事件结构为中心的，比如它需要有事件头、事件体、事件时戳等。AEOP没有任何这些限制，因为整个结构是由它的类型决定的。</p>
<img alt="" _href="img://Fig7.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig7.jpg" />
<p>图7. AEOP的&#8220;信息装配线&#8221;是围绕业务操作的容器被构建的</p>
<p>操作平台使得3类基本用户——工人（他们支持正常操作），经理（他们触发内部操作变更）和外部业务团体（即用户）——之间的交互自动化。</p>
<p>最后一个要详细描述的平台是AEOP事件处理。&#8220;装配线&#8221;概念能在超过一个世纪的时间里如此流行，其中一个原因就是，每一步可以轻易地和其余的步骤
解耦。除此之外，不管他需要执行什么工作，每个&#8220;岗位&#8221;的工人都将遵循相同步骤。当一个产品的主实例到达这个&#8220;岗位&#8221;，它就像一个需要使用各种零件&#8220;填充
&#8221;的空
&#8220;壳&#8221;一样。这些零件有两类：在当前&#8220;岗位&#8221;待组装的特殊零件；对装配过程只起帮助作用的零件，我们称这些零件为&#8220;工具&#8221;。例如，一个&#8220;工具&#8221;可能是帮助
装配过程的某种胶水。这三个待组装元素有它们自己的仓库，它们有自己的&#8220;到达&#8221;时间安排，并且它们遵循特殊的装配过程逻辑。一旦组装完成，在到达下一个&#8220;
组装岗位&#8221;之前，那个零件实例不会发生任何事情。</p>
<p>&#8220;信息装配线&#8221;跟真实的装配线概念非常相似。在事件处理期间，我们遇到的是同类信息：代表主业务实体的&#8220;壳&#8221;，特定于一个事件和需要被增加实例的信
息，以及被称为&#8220;工具&#8221;、只特定于需要被增加事件的信息。&#8220;工具&#8221;类型信息的主要特征是，它是有限的，可以为同一事件多次使用它，并且在处理事件过程中你
可能把它&#8220;用光&#8221;，在某种程度上类似装配过程期间用来粘住零件的&#8220;胶水&#8221;。在订单处理中，&#8220;工具&#8221;信息的一个例子就是企业给客户的赊账限额。他可能一次性
使用所有可用赊账限额支付产品，或者他可能决定只使用部分，他可以使用它支付多次购买，并且在一个购买过程中他可能把它&#8220;用光&#8221;了。</p>
<p>另外它与&#8220;仓库概念&#8221;也很相似。&#8220;待装配&#8221;信息对何时开始检索它有明确的规则。例如，当客户用信用卡支付帐单时，账户信息是实时从银行检索出来的。保存在任何其他数据&#8220;仓库&#8221;中的值都不是一个有效的值。</p>
<p>处理事件期间，从各系统取信息可以通过事件&#8220;定位&#8221;层和事件&#8220;调度器&#8221;层来完成。只有在完成这两步之后，&#8220;信息&#8221;才能按照逻辑进行&#8220;装配&#8221;。&#8220;定位
&#8221;层使用一种面向消息的组件，&#8220;调度器&#8221;层使用以调度为中心的组件，&#8220;逻辑&#8221;层使用BPM/业务规则引擎作为主组件。次序总是不变的。</p>
<p>调度器在架构/设计中的任务不仅仅是安排不同任务的时间，它的另一个任务是帮助设计一个在事件层完成控制状态变化的多线程架构。这是通过使用调度器
作为一个事件模块做到的，它把在状态变化期间可能有并行任务的流程转换成单独的&#8220;泳道&#8221;。这样，我们就可以在事件层像调度器处理每个事件子任务那样来实现
状态变化逻辑了。这样，流程&#8220;泳道&#8221;中的失效将使整个系统处于一个清晰可辨的状态中。 </p>
<img alt="" _href="img://Fig8.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig8.jpg" />
<p>图8. AEOP事件处理容器——定位、调度和逻辑</p>
<p>结合所有这3个元素，&#8220;信息装配线&#8221;可以被构建成对任何企业系统都是通用的，不论企业涉足的领域和规模大小。这与装配线的方法类似，起源于汽车制造业，后来扩展至所有其他制造行业。</p>
<p>AEOP事件处理容器针对内外部变更有两类变更管理模块。假如一个事件被标识为一个变更，决策表将把具体的变更类型和特殊事件联系起来。这个架构是
作为一组插件来设计的，它是根据现有实例的状态被调用的。例如，在订单处理中，对于预付和未付订单而言，处理价格变更的方法是不同的。</p>
<h4>总结——数天内完成架构、数周内完成设计、数月内完成实现——构建集成的DBA服务器端基础设施的简易之道</h4>
<p>AEOP方法有诸多优点。主要优点是它标准化了服务器端应用的架构，这正是当今IT所缺失的。它将这个服务器端实现转变成事件插件代码的编写，类似微软Windows应用的编写方式。</p>
<a _href="resource://Fig9_lg.jpg" href="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig9_lg.jpg"><img alt="" _href="img://Fig9.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig9.jpg" /></a>
<p>图9. 自适应操作平台支持动态、拥有控制层级、分布式和有状态的业务</p>
<p>使用AEOP实现应用的3步骤包括：</p>
<ol>
    <li>获取对象流和变更类型</li>
    <li>获取3个平台的组件</li>
    <li>构建每个事件处理的5个模型</li>
</ol>
<p>在这个架构中，像SOA这样的技术和架构概念扮演配角。像BPM引擎、调度器、消息传递这样的组件在架构中有明确的角色，但是它们对设计的影响很
小。这类似于飞机设计中各零件扮演角色的方式。电动发动机、电线、螺母和螺钉对整个飞机的功能至关重要，但是它们对设计过程却非如此。</p>
<p>由于这种方法不依赖于业务，可以构建类似微软Visual C++向导或Visual Basic这样的工具进一步使实现过程自动化。这不仅提高了开发团队的生产力，而且还有助于开发者关注实现的真实方面，而不是与错误的架构&#8220;搏斗&#8221;。</p>
<p><strong>即将到来的第三部分——案例研究和局外人观点 <br />
本文将在第三部分继续，它探讨一个真实实现的案例研究和新的自适应系统理论的简要总结。</strong></p>
<p>查看英文原文：<a target="_blank" href="http://www.infoq.com/cn/articles/beyond-soa-dba-part-2">Beyond SOA, a New Type of Framework for Dynamic Business Applications - Part II</a>。</p>
<p><br />
</p>
<p>转自：http://www.infoq.com/cn/articles/beyond-soa-dba-part-2<br />
</p>
<p><br />
</p>
<img src ="http://www.blogjava.net/jhyan/aggbug/232644.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-10-06 13:08 <a href="http://www.blogjava.net/jhyan/archive/2008/10/06/232644.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>超越SOA：动态业务应用的新企业应用框架(1) 转载</title><link>http://www.blogjava.net/jhyan/archive/2008/10/06/232641.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Mon, 06 Oct 2008 05:05:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/10/06/232641.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/232641.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/10/06/232641.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/232641.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/232641.html</trackback:ping><description><![CDATA[<h2><br />
</h2>
<h2>第一部分——即使拥有全部需求和最佳设计，你的架构仍然很可能失败，原因在于&#8230;&#8230;</h2>
<p><strong>目前的管理学校，教育培养的是公司经营者。设计公司几乎没有引起重视&#8230;&#8230;几乎从来没有任何人为了取得计划的增长和稳定性，有意识和有思想地设计一个组织。</strong></p>
<p><strong>——&nbsp;&nbsp;Jay W. Forrester，设计未来（1998）</strong></p>
<h3>介绍</h3>
<p>在一篇名为《动态业务应用势在必行（The Dynamic Business Applications Imperative）》的论文中，Forrester的高级分析师John R. Rymer指出了当今应用的一个致命缺陷：</p>
<p style="margin-left: 40px; font-weight: bold;">当今应用迫使人们去寻找一种将孤立的信息和功能组映射到他们任务和过程的方法，它们强迫IT人员花高额预算来跟踪不断变化的市场、策略、规章制度和业务模型。</p>
<p style="margin-left: 40px; font-weight: bold;">在下一个5年内，IT的主要目标应该是发明新一代企业软件，适应业务和业务工作，同时能随业务演变而演变。</p>
<p style="margin-left: 40px; font-weight: bold;">Forrester称这个新生代为动态业务应用，
强调了和业务过程及工作（为人而设计）的紧密配合，对业务变化的自适应（为变化而构建）。在这个阶段，动态业务应用的需求比创建它们所需的设计实践更清
晰。工具都是现成的：面向服务架构（SOA）、业务过程管理（BPM）和业务规则领域中的先驱——包括独立软件开发商（ISV）——已经开始向我们展示了
这种方法。现在就是开始这段旅程的时候。</p>
<p>在这篇由两部分组成的文章中，我们会从架构和方法论的角度，采用历史的观点来看待这些动态业务应用（DBA）的发展。我们的目标是获得一种能使应用容易适应业务变化和其他必要修改的构建方法。随着企业在21世纪关注灵活性，DBA是使业务和IT在未来几十年内成功的关键。</p>
<img src="http://www.infoq.com/resource/articles/dynamic-business-applications/en/resources/Fig1.jpg" alt="" />
<p><strong>图 1. 灵活性和效率——21世纪企业的两个主要驱动力</strong></p>
<h3>动态性对我们意味着什么？</h3>
<p>在软件工程领域，许多框架或产品都声称具有自适应性。在我们设法理解一个解决方案在适应变化方面究竟有多好之前，需要给系统是如何变化的——它们的动态性——下一个可靠的定义。</p>
<p>早期的面向对象方法论认识到<a href="http://www.infoq.com/cn/articles/dynamic-business-applications#ednref1">[1]</a>：为了使系统分析中立，它必须基于两类现实世界的需求：</p>
<ul>
    <li>现实世界的实体 —— 收集现实世界实体的信息和它们间的关系，有助于分析师开始以一种系统的、结构的、客观的观点来看待需求，而非一种技术的、主观的观点  </li>
    <li>现实世界的事件 —— 系统行为只由改变现实世界实体状态的事件的出现来驱动</li>
</ul>
<p>在这样的背景下，对于每一个被分析的系统，我们总能识别一个或多个最重要的实体。每个实体都又包含3个关联元素：事件、状态和生命周期。每个事件代
表状态中的一个变化，所有普通实体状态的有序和代表了一个生命周期。但是，那些触发状态变化且是正常流程一部分的事件与那些触发状态变化但不是正常流程一
部分的事件之间有明显的差异。例如，当一个产品订单被提交之后，一组可能发生的事件包括付费处理和订单交付。当一个用户变更订单或当企业改变价格时，我们
不能认为这些动作是正常流程的一部分，因此它们与实体（如订单）的生命周期无关。核心实体实例的生命周期单独定义了在正常操作中系统最有可能处理的东西。
所有其他事件类型，如变化或中间步骤，被区别对待。</p>
<p>这个场景对很多工程师都不陌生：一个系统模型包含一个核心实体结构，该实体具有一组事件，这些事件组成了实体的生命周期。这个系统模型对分析师和设
计者都很清晰且易于理解。建模工具，如有限状态机、实体关系图、实体状态转换图和数据流图，为了帮助这种方法已经经过了快20年的完善。那些为复杂系统
（如空客380或F-22，后者是世界上最高级的战斗机）服务、拥有数十亿行代码的软件就是这样被编写出来的。使用对象流图（它是捕获事件和状态转换的基
础模型）虚拟化实体生命周期是这个模型的关键。在这个情况下，架构可以被认为是静态的，因为整个系统状态在时间轴上的任意一点都是确定的。</p>
<img src="http://www.infoq.com/resource/articles/dynamic-business-applications/en/resources/Fig2.jpg" alt="" />
<p><strong>图 2. 事件模型、状态变化和生命周期是正常操作的核心</strong></p>
<p>普通事件、状态、生命周期间的关系，以及从其他事件类型中分出的普通事件是理解所建议的动态操作框架的基础。正如James Martin
和James
Odell很久以前在《面向对象分析设计》中所写的，分析师、设计师和实现者都应该使用同一系统模型。分析师使用数据流图思考，设计师使用结构图思考，程
序员使用Java和SQL思考。在数据流上下文中，分析师识别对象类型，并思考改变对象状态的事件。最终用户也理解这个相同的认识。他们也应该按照对象类
型、事件、对象状态的变化，以及触发和控制事件的业务规则进行思考。Martin和Odell强调了对象流图对系统设计师的重要性：&#8220;事件模式适合按照事
件、触发器、条件和操作来描述过程。但是这种方式不适合描述大型复杂过程。一个系统领域常常太大或太复杂，无法表示成事件和触发器。此外，可能只有一个高
级别的认识才是必要的。这对战略级别的规划尤其正确。在这样的情况下，一个对象流图是有用的。对象流图（OFD）与数据流图（DFD）类似，因为它们描述
了活动和其他活动间的接口。在DFD中，这个接口传递数据。在对象技术中，我们不再限于数据传递。相反，图应该表示从一个活动传递到另一个活动的任何类型
事物：不论它是报表、零部件、已完货物、设计、服务、硬件、软件——或数据。简而言之，OFD指的就是被产生的对象，以及产生和交换它们的活动。&#8221;</p>
<p>为了捕获与业务操作关联的信息流，业务分析师用价值流程图（Value Stream
Mapping）对OO方法论进行了补充。价值流程图起源于丰田，与精益制造关系紧密。美国国家环境保护局将价值流程图定义为&#8220;用来认识那些产生产品或交
付服务的活动序列与信息流程的精益过程映射方法。&#8221;此处的关键词是&#8220;产品&#8221;和&#8220;服务&#8221;。它们显现了合适的信息流程在整个企业中扮演的统一角色。</p>
<p>把过程流图和价值流程图两个概念结合在一起后，它产生了一个完全代表整个企业经营范围、可被方便翻译成OO（图2）概念的框架基础。</p>
<p>但是，许多系统并不是静态的，它们变化无常的行为无法被一组关系和事件捕获。事实上，它们发生在不可知的<a href="http://www.infoq.com/cn/articles/dynamic-business-applications#ednref2">[2]</a>未来，传统用来捕获它们动态特点的工具不起作用。所有的业务应用和绝大多数现实世界的系统都归于此类。这些系统，基于它们和其他外部系统的交互方式，处理3类变化：</p>
<ul>
    <li>正常工作 ——
    组成主实体或实体们生命周期的正常事件序列。通过每个事件——实体改变其状态——通常可以方便地定义一个过程。在正常工作行为内部，有些操作上下文元素不
    期望被改变。例如，当一个客户订购一个产品时，在整个提取订单、准备订单和交付订单的过程中，诸如价格、组成和交付方式等是不期望被改变的。 </li>
    <li>内部变化 —— 如上所述，在整个核心实体生命周期内，某些上下文元素不期望被改变。在现实世界中，这并不总是真理，因为管理决策或其他因素会迫使上下文元素变化。我们称内部系统属性的变化是内部变化。  </li>
    <li>外
    部或环境变化 ——
    不管一个企业如何相信他们&#8220;拥有&#8221;一个客户，但是这个客户总有保留改变他或她意志的自由。一个系统不太可能与外部系统（如客户或供应商）总是有一个&#8220;固定
    的&#8221;合同。然而，正常工作很可能围绕这个&#8220;固定的&#8221;规则集合进行设计。我们称系统外部引起的变化为外部变化。</li>
</ul>
<p>要对现实世界系统建模，就必须处理好这所有3种变化类型。这种模型与静态架构模型相比，在管理复杂性上有了极大的提高。从正常工作的观点来看，内部
和外部系统完全独立于主信息流运行。内部和外部系统甚至有它们自己的操作——管理有其自身的决策周期，客户有其自己的操作环境——由各自的信息流描述。就
信息流而言，这3种系统分别运行在3个平行宇宙中。解决这3种非同步信息流的唯一办法就是为每个信息流实现一个独立全面的变更管理。这种复杂交互在图
3（动态操作图）中表示。</p>
<p>邮轮公司给客户提供的服务可以作为解释动态操作的例子。在订购时，一个客户会决定在游览期间他计划参与的服务。但是，不仅客户可能在游览前和游览中
改变主意，而且邮轮公司也可能会为了利用新机会或应对未知事件改变服务。按照当前方法设计的系统，大部分变更都以极高的运营成本人工处理。使用基于动态业
务应用架构原则设计出的系统，来自客户和内部管理决策的变更由两个与正常工作完全集成的变更管理子系统负责。这不仅能降低成本，而且还提高了服务质量，甚
至可以最优化运营来提高利润。因为是完全通用的，它还可以重用标准组件。最终结果对于参与的每个人、业务、IT和客户来说是多赢的。</p>
<img src="http://www.infoq.com/resource/articles/dynamic-business-applications/en/resources/Fig3.jpg" alt="" />
<p><strong>图 3. 动态操作有3个维度——正常事件、内部控制和外部反馈</strong></p>
<p>动态业务应用的目标之一就是使设计和软件实现变得简单，以支持对所有业务来说司空见惯的动态系统。以我们的经验，与一个框架优先的工程学相结合是构建一个DBA的最有效的技术方法。</p>
<h3>设计企业系统要求框架先行</h3>
<p>构建动态业务应用说起来简单，做起来难。工程，包括软件工程，都采用了有百年历史的框架优先方法。设计一座桥梁、一架飞机或者甚至是一个软件应用都
使用相同的方法：一个设计团队先收集需求，然后使用一组定义良好的框架步骤来设计和构建系统。在设计桥梁和其他工程系统时，现有框架已被证明非常成功。但
在使用它来为业务系统开发软件时，却碰了壁。这两类系统之间有一个根本区别。在设计桥梁和飞机时，最终结果总是一个拥有静态架构的系统：当变更发生时，如
增加桥梁负重或飞机速度，整个系统可能就要重头重新设计。不幸的是，软件也常常使用一个静态架构进行设计：每当一个非预期的变更被引入到运营中时，很可能
所有事情都停了下来，使用包含新增功能的系统替代现有系统。因为业务运营在一个不断变化的环境中，而且比以往更依赖IT系统，这种停——走式的解决方案是
不可接受的。持续升级和在企业基础设施中集成系统的成本已经达到了无法支撑的地步。</p>
<p>依赖业务涉众作为我们全部需求的输入首先就是个问题。考虑到需求，目前还没有真正适合动态操作的&#8220;框架优先&#8221;软件设计方法。甚至卡内基梅隆软件工程
学院也表示架构是由场景驱动的，场景以涉众输入为基础被创建出来：&#8220;诱导一个软件密集型系统的业务目标是标准架构设计和分析方法的一个组成部分。业务目标
是驱动方法的引擎，通过将它们的实现作为场景&#8230;&#8230;一个理想的设计方法或过程必须考虑众多涉众和众多影响。&#8221;</p>
<p>作为工程师，当我们收集系统需求时，我们怎能知道我们得到了正确的场景或是否遇上了正确的涉众？我们又如何能说明业务未来的变化，而这些变化通常连参与的涉众都不知道？</p>
<p>&#8220;企业经营者和企业设计师之间存在着根本区别。为了说明这点，考虑一下在一架飞机成功操作背后的两种最重要的人。一个是飞机设计师，另一个是这架飞
机的飞行员。设计师创造的飞机连平庸的飞行员都可成功驾驶。一般情况下，经理更像是飞行员而非一个设计师。一个经理管理一个组织，这和一个飞行员驾驶飞机
没什么两样。飞行员的成功依赖于那些创造了一架成功飞机的飞机设计师。另一方面，是谁来设计一家由管理者管理的公司呢？几乎从没有任何人有意识和有思想的
去设计一个组织，以取得有计划的增长和稳定性。在当前的管理学校中，教育培养的是企业的经营者，而如何设计企业几乎不受重视。&#8221;</p>
<p>在几年前完成的报告&#8220;设计未来&#8221;中，MIT的教授和系统动态之父Jay Forrester，指出这个问题是我们为企业设计系统的基本限制：</p>
<p>Forrester的观察进一步使当前的企业架构方法失效。在我们需要设计一个企业系统架构时，作为知识主要来源的涉众甚至是错误的分类。他们是企
业的&#8220;用户&#8221;，不是&#8220;设计师&#8221;。在设计飞机时，飞机设计师决不可能去询问飞行员或乘客关于飞机制造方面的事情。但是，在学校、工程或MBA课程中却没有企
业设计这门课。</p>
<p>那么回到企业架构，其中有一个根本的断档。企业架构的&#8220;用户&#8221;是企业涉众，很可能是熟悉企业动态性的企业毕业生，但是他们不熟悉工程方法。企业系统
的设计者和构建者——软件工程师——熟悉静态框架，但是对动态框架却很陌生。事实上，还没有说明业务动态的框架。根据企业架构框架，这是一个需要填补的缺
口。这个框架只描述企业是如何&#8220;被设计的&#8221;，但是也会定义开发路线图和主要组件，使用它们来构建企业的支持系统。</p>
<img src="http://www.infoq.com/resource/articles/dynamic-business-applications/en/resources/Fig4.jpg" alt="" />
<p><strong>图 4. 企业架构的业务和工程方法</strong></p>
<p>我们建议根本改变我们架构和设计信息系统的方式，以一种不要求业务涉众作为主要输入的方式。我们推荐利用一个以业务实体生命周期和事件模型为中心的框架作为架构的主要输入来源。业务场景只被用来微调一个已完架构，而不是作为主要驱动力。</p>
<p>这种框架优先方法从一开始就说明了业务动态，而不是事后诸葛亮。它暗示被设计的企业应用是动态适应的，而不是像由今天的方法论所实现的那样是静态适应的。这种方法成数量级的减小了开发和维护软件的成本，并砍掉了与改变和维护现有系统直接相关的超过70%的IT开销。</p>
<img src="http://www.infoq.com/resource/articles/dynamic-business-applications/en/resources/Fig5.jpg" alt="" />
<p><strong>Fig 5. 基于框架的软件解决方案开发方法</strong></p>
<p>在我们建议的方法中，业务场景只被作为一个已完架构的微调，而不是主要驱动力。我们将我们的直觉、经验和技巧输入到设计过程中越晚，产生导致巨大损失的错误的可能性就越少。由涉众输入引起的需求变更会在已经建好的现有解决方案框架中处理，减少了风险和延迟。</p>
<p>一份Standish报告研究表明，超过1千万美元的项目，成功率只有3%。行业咨询和哈佛商学院教授Andrew
McAfee表示，部署如此高成本技术（如ERP、CRM、供应链管理、电子商务和其他企业应用）组织的成功率在25% ~
70%之间。McAfee总结说：&#8220;这些面临的问题并非是单独的，它们都是同一事情的不同例子，基本上都是使用IT改变业务过程的结果。&#8221;。最近，这些百
分比有所提高，但是对于复杂系统IT仍缺乏清晰的路线。框架优先的方法能使业务变化集成到IT实现中，并提供了业务和技术之间更清晰的转换，可以将成功率
提高接近100%。建构复杂系统的时间由几个月或几年缩短至几天。</p>
<h3>动态操作的服务器架构 —— 忘记SOA，迎接信息装配线</h3>
<p>90年代早期，事件几乎是每本面向对象方法论书籍中的核心角色。随着象Windows这样基于GUI操作系统的出现，GUI开发平台依靠复杂事件模型来设计和构建单个应用。但是，在客户机-服务器环境中，服务器端的事件处理总是基于一个简单得多的模型。</p>
<p>当基于Web的技术（如J2EE和.NET）开始替代传统的客户机-服务器应用，客户机和服务器都经历了根本的转变。客户端的富OS事件模型由
Web浏览器和原始的脚本语言代替。在服务器端，事件处理由无状态、扁平的、静态架构所替代。其方式非常类似将网页传给Web浏览器的方式。</p>
<p>为了模拟现实世界的需求，需要一个有状态的、层次的、动态的和分布式的架构，设计必须严重依赖数据库来存储范围广泛的各种动态信息。但是根据其定
义，关系数据库非常适合存储不常变化的数据间关系。保存动态、分布式、层次的和有状态信息要求一个不同的基础设施，它不是以关系数据库为中心的。</p>
<p>基于Web的技术为支持现实世界系统引入了其他挑战。当J2EE应用服务器在一个分布式环境被使用时，使用Java作为编程语言的一个最大优势完全
没有了。Java虚拟机的垃圾回收从来没有被设计成能自动清除在多实例间交换的内存对象。在这种情况下，架构师和设计师必须编排整个对象生命周期，不考虑
编程语言的能力。甚至在数据保存在数据库中时，这种相同的数据清除问题也变得非常困难。</p>
<p>正如我们已经看到的，一旦我们能从正常工作中分离变化，架构就能只依赖事件和生命周期进行设计和实现。围绕生命周期进行系统设计已经经历了一个世纪——它被称为装配线。</p>
<p>在装配线于20世纪早期引入之前，制造业的工作方式多多少少和今天面向服务架构（SOA）处理信息的方式一样。每个对于SOA服务的调用一般都被视
为一个无状态调用。为了说明以前调用的历史，每个服务必须完全实现如何处理系统内部状态。一旦需求改变，几乎所有服务也需要以成本极高的方式重新编码来改
变它们各自的实现。</p>
<img src="http://www.infoq.com/resource/articles/dynamic-business-applications/en/resources/Fig6.jpg" alt="" />
<p><strong>图 6. 服务器架构是以事件模型为基础的</strong></p>
<p>我们建议使用以事件模型和生命周期为中心的信息架构作为业务需求和系统架构的双向翻译平台。事件模型在下一级被扩展成四个基本模型：状态、分布式、层次和动态。所有这5个模型可被基础需求和架构模型中的业务或技术人员方便地解释：</p>
<ul>
    <li><strong>事件模型/生命周期</strong>——
    它是构建其他模型的基础核心。对业务用户来说，它是价值流，反映产品/服务生命周期和为客户创造价值的过程序列。对技术人员来说，同一事件序列反映了代表
    业务实体对象的状态变化。最终结果是，事件模型扮演了解耦元素，大大简化了设计和实现。事件模型还扮演了另一个重要角色。因为其他四个模型是围绕事件模型
    而构建的，它还扮演一个集成平台。事实上，事件模型是创造实现变更、层次和分布式组件的唯一办法。 </li>
    <li><strong>状态模型</strong>—— 对业务用户来说，这个模型扮演了企业的面板，捕获当前经营的整体状况。对技术人员来说，它是系统的整体状态，它是全部生命周期实例的当前状态，以及它们的变化之和。  </li>
    <li><strong>分布式模型</strong> —— 对业务用户来说，这个模型捕获了其生命周期内控制产品/服务的各种组织。对技术人员来说，主实体只能基于分布式模型来控制。  </li>
    <li><strong>层次模型</strong>—— 所有业务都有代表管理层级的层次结构。所有系统设计应该在架构上反映这种控制层次。正如销售VP不能给CEO下命令一样，低层级的组件不能给高层级的组件发送执行&#8220;命令&#8221;。  </li>
    <li><strong>动态模型</strong>—— 继事件模型之后最重要的模型。业务用户使用它来捕获平时必须被处理的全部变更。如前所述，有两种变化类型：外部，如客户输入；内部，如管理决策。对技术人员来说，动态模型被翻译成一个匹配各种事件、生命周期和变化类型的插件架构。</li>
</ul>
<p>这5个模型不仅可以被用在初始设计，对贯穿整个系统生命周期的需求变更亦有裨益。它们一起形成了自适应系统设计所缺失的框架步骤。这5个模型排除了用例作为企业架构的主输入的必要性。它们可以被翻译成一个清晰和全面的工程问题集合，与在桥梁或飞机设计中使用的方法类似。</p>
<img src="http://www.infoq.com/resource/articles/dynamic-business-applications/en/resources/Fig7.jpg" alt="" />
<p><strong>图 7. 自适应架构是以5个模型为基础的信息架构结果</strong></p>
<p>这5个模型定义了以信息变化和装配线为中心的动态业务应用通用架构。最重要的子系统是：静态模型、变更管理、虚拟装配对象和事件处理。在下一个细化层级，还有两个子系统：系统命令和控制与持久化。</p>
<p>这个架构还解决了在寻求一个适用于事务型工作流隐喻的通用解决方案过程中长期存在的问题，它是由Jim Gray<a href="http://www.infoq.com/cn/articles/dynamic-business-applications#ednref3">[3]</a>在
几十年前提出的。因为整个设计以单个事件的执行为中心，不仅可以实现&#8220;移动到下一个装配步骤&#8221;，而且也可实现&#8220;移动到前一个装配步骤&#8221;。实现需要根据用户
的输入决定前往哪个&#8220;方向&#8221;。通过将多个步骤&#8220;链接&#8221;在一起，可以使用相同的架构实现一个事务型工作流的&#8220;撤销（Undo）&#8221;操作。</p>
<p>动态业务应用的一个关键元素是事件处理。使用新的自适应系统信息理论，可以使用一个通用组件结构来&#8220;执行&#8221;每个事件。这个组件使用声明性编程来内嵌
业务逻辑、调用工作流引擎、调度器和业务规则引擎。这个实现不仅可以极大加速自适应系统开发，而且可以使后期改变非常容易处理，也减少了维护复杂集成的需
要。</p>
<p>我们建议围绕事件（操作）和事件生命周期创建一个供给控制、运营和环境的物理模型。生命周期控制器为离散事件管理装配信息。变更管理功能指导标准事件模型和个体事件内外部变更的执行。</p>
<h3>结论</h3>
<p>我们已经讨论了扁平、无状态、静态、客户端——服务器、基于Web的解决方案的演变方式所带来的IT架构和层次、有状态、动态、分布式业务的现实世
界之间的脱节。我们还讨论了传统工程方法为什么不能支撑能支持动态业务的自适应系统的开发。我们展示这两个问题的可能解决方案可以用一种新的模型驱动架构
方法来找到。</p>
<p>本文的第二部分将描述动态业务应用的可能架构，并给出一个案例研究，介绍我们概念的实际实现。</p>
<h3>参考文献</h3>
<p><a href="http://www.infoq.com/cn/articles/dynamic-business-applications#ednref1" id="ednref1">[1]</a> Yourdon Systems Method —— Model Driven Systems Development —— Yourdon Press, 1993</p>
<p><a href="http://www.infoq.com/cn/articles/dynamic-business-applications#ednref2" id="ednref2">[2]</a>
Eric D. Beinhocker —— "The Origin of Wealth", HBS Press Book,2006 ——
在他的新书&#8220;The Origin of Wealth&#8221;中，麦肯锡公司高级顾问Eric D.
Beinhocker声称，将经济视为一种静态、平衡的系统的传统观点正在经受一场彻底的反思，包括为数众多的原则。新的中心是：&#8220;复杂经济学&#8221;，其中经
济被视为一种高度动态的、不断演变、几乎无法预测的系统。这个摘录涉及在未来未知时公司如何来制定战略。</p>
<p><a href="http://www.infoq.com/cn/articles/dynamic-business-applications#ednref3" id="ednref3">[3]</a> Mark Whitehorn ,The Register, Interview with Jim Gray —— http://www.regdeveloper.co.uk/2006/05/30/jim_gray/</p>
<p><strong>查看英文原文</strong>：<a href="http://www.infoq.com/articles/dynamic-business-applications" title="Beyond SOA: A New Enterprise Architecture Framework for Dynamic Business Applications">Beyond SOA: A New Enterprise Architecture Framework for Dynamic Business Applications</a></p>
<p><br />
</p>
<p><br />
</p>
<p>转自：http://www.infoq.com/cn/articles/dynamic-business-applications<a href="http://www.infoq.com/articles/dynamic-business-applications" title="Beyond SOA: A New Enterprise Architecture Framework for Dynamic Business Applications"><br />
</a></p>
<img src ="http://www.blogjava.net/jhyan/aggbug/232641.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-10-06 13:05 <a href="http://www.blogjava.net/jhyan/archive/2008/10/06/232641.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>判断js函数是否存在，如果存在则执行</title><link>http://www.blogjava.net/jhyan/archive/2008/09/25/231060.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Thu, 25 Sep 2008 03:00:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/09/25/231060.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/231060.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/09/25/231060.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/231060.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/231060.html</trackback:ping><description><![CDATA[假设funcName为函数名字，用如下方法就可以达到目标<br />
<br />
一定要添加try catch块，否则不起作用。<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(</span><span style="color: #0000ff;">typeof</span><span style="color: #000000;">(eval(funcName))</span><span style="color: #000000;">==</span><span style="color: #000000;">"</span><span style="color: #000000;">function</span><span style="color: #000000;">"</span><span style="color: #000000;">)&nbsp;&nbsp;<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;funcName();<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">(e)<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">alert("not&nbsp;function");&nbsp;</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp; <br />
</span></div>
<img src ="http://www.blogjava.net/jhyan/aggbug/231060.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-09-25 11:00 <a href="http://www.blogjava.net/jhyan/archive/2008/09/25/231060.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>document.body.scrollTop 值总为0的解决方法（转载）</title><link>http://www.blogjava.net/jhyan/archive/2008/08/29/225618.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Fri, 29 Aug 2008 09:00:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/08/29/225618.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/225618.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/08/29/225618.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/225618.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/225618.html</trackback:ping><description><![CDATA[<div id="articleBody">
<p>做页面的时候可能会用到位置固定的层，读取 document.body.scrollTop 来设置层的位置，像这样：</p>
<pre class="code">window.onscroll = function ()<br />
{<br />
var oFix = document.getElementById("divfix");<br />
oFix.style.top = document.body.scrollTop + "px";<br />
}</pre>
<p>可是怎么没有达到预期效果呢，输出 document.body.scrollTop 的值一看，一直都是 0。原来是 DTD
的问题,要是页面直接用 开头的话就没有问题了。但是要符合 web 标准，DTD 当然是不能少的。具有 DTD 时用
document.documentElement.scrollTop 代替 document.body.scrollTop 就可以了。</p>
<pre class="code">window.onscroll = function ()<br />
{<br />
var oFix = document.getElementById("divfix");<br />
oFix.style.top = document.<span class="caution">documentElement</span>.scrollTop + "px";<br />
}<br />
</pre>
<p>编者注：</p>
<ul>
    <li>页面具有 DTD（或者说指定了 DOCTYPE）时，使用 document.documentElement。</li>
    <li>页面不具有 DTD（或者说没有指定了 DOCTYPE）时，使用 document.body。</li>
    <li>在 IE 和 Firefox 中均是如此。</li>
    <li>为了兼容，可以使用如下代码：
    <div class="code">var scrollTop = window.pageYOffset&nbsp; <br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; || document.documentElement.scrollTop&nbsp; <br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; || document.body.scrollTop&nbsp; <br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; || 0;</div>
    </li>
</ul>
<br />
转自：http://www.cftea.com/c/2008/06/U1FSRIC247DWTK2M.asp<br />
</div>
<img src ="http://www.blogjava.net/jhyan/aggbug/225618.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-08-29 17:00 <a href="http://www.blogjava.net/jhyan/archive/2008/08/29/225618.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>