﻿<?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-欢迎来到davy的java世界</title><link>http://www.blogjava.net/happydavy/</link><description>爱生活,爱java</description><language>zh-cn</language><lastBuildDate>Tue, 28 Apr 2026 19:01:57 GMT</lastBuildDate><pubDate>Tue, 28 Apr 2026 19:01:57 GMT</pubDate><ttl>60</ttl><item><title>tapestry中的各种link组件</title><link>http://www.blogjava.net/happydavy/archive/2005/12/27/25613.html</link><dc:creator> 我的java天地</dc:creator><author> 我的java天地</author><pubDate>Tue, 27 Dec 2005 09:51:00 GMT</pubDate><guid>http://www.blogjava.net/happydavy/archive/2005/12/27/25613.html</guid><wfw:comment>http://www.blogjava.net/happydavy/comments/25613.html</wfw:comment><comments>http://www.blogjava.net/happydavy/archive/2005/12/27/25613.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/happydavy/comments/commentRss/25613.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/happydavy/services/trackbacks/25613.html</trackback:ping><description><![CDATA[<P>一、 contrib:PopupLink 组件： </P>
<P>Html 模板代码： </P>
<P>&lt;h1&gt; PopopLink组件： &lt;/h1&gt;&lt;p&gt; </P>
<P>作用：弹出一个自定义的窗口，相当于一个 Script语名： </P>
<P>&lt;br&gt; window.open(URL, windowName, windowFeatures) &lt;br&gt; </P>
<P>1.必须在Body组件内使用。 &lt;br&gt; </P>
<P>2.注意href参数它会产生一个地址“/context/href参数值” </P>
<P>&lt;p&gt; &lt;span jwcid = "@contrib:PopupLink" href = "/WEB-INF/Home.html" features = 'ognl:"resizable,scrollbars,top=100,left=100,height=400,width=300"' &gt; PopupLink到主页 &lt;/span&gt; </P>
<P>&nbsp;</P>
<P>&nbsp;</P>
<P>二、 GenericLinkLink 组件 </P>
<P>Html 模板代码： </P>
<P>1.GenericLink：一般作用是用来链接跳转到应用程序范围以外的链接。注意OGNL用法： &lt;br&gt; </P>
<P>&lt;a jwcid = "@GenericLink" href = "ognl:'http://'+url" &gt; </P>
<P>&lt;span jwcid = "@Image" image = "ognl:assets.ms" /&gt; 163主页 &lt;/a&gt;&lt;p&gt; </P>
<P>url参数： </P>
<P>private String url="http://www.blogjava.net/happydavy/"; </P>
<P>ms参数： </P>
<P>&lt;context-asset name="ms" path="//MS.JPG"/&gt; </P>
<P>作用：点击后就会到 163页面。 </P>
<P>三、 .ExternalLink 组件 </P>
<P>Html 模板代码： </P>
<P>&lt;span jwcid = "@ExternalLink" page = "LinkResult" parameters = 'ognl:new java.lang.Object[]{new java.lang.Integer("5"),new java.lang.String("rjzjh")}' &gt; </P>
<P>ExternalLink使用 &lt;/span&gt;&lt;p&gt; </P>
<P>ExternalLink ：这组件比 GenericLink 组件复杂，使用 Tapestry 的 9 种 Service 的 “external service” ，它的用法关注 LinkResult 页。 </P>
<P>链接传递参数 parameters ，多个参数用逗号隔开。链接的页面 “LinkResult” 必须实现 IExternalPage 接口，必须重写 activateExternalPage 方法 <BR>在这个方法中我们可以把传递过来的参数取出来实现我们的逻辑。参数因为单引号内有双引号，所以不能用双引号，也可以调回来用了，链接页的地址为： <A href="http://localhost:8080/context/app?service=external/LinkResult&amp;sp=5&amp;sp=Srjzjh">http://localhost:8080/context/app?service=external/LinkResult&amp;sp=5&amp;sp=Srjzjh</A> </P>
<P>接收参数的页面要： </P>
<P>?&nbsp; 实现 IexternalPage 接口。 </P>
<P>?&nbsp; 覆盖 public void activateExternalPage(Object[] parameters, IRequestCycle cycle) 方法。 </P>
<P>如下 Java 文件为： </P>
<P>public void activateExternalPage(Object[] parameters, IRequestCycle cycle) { </P>
<P>this.setPar1((Integer)parameters[0]); </P>
<P>if(parameters.length==2){ </P>
<P>this.setPar2((String)parameters[1]); </P>
<P>} </P>
<P>} </P>
<P>三、 DirectLink 组件 </P>
<P>Html 模板为： </P>
<P>&lt;p&gt;&lt;span jwcid = "@DirectLink" listener = "ognl:listeners.directlistener" parameters = 'ognl:new java.lang.Object[]{new java.lang.Integer("8"),new java.lang.String("zjh")}' &gt; </P>
<P>这是一个DirectLink链接 </P>
<P>&lt;/span&gt;&lt;br&gt; </P>
<P>&lt;span jwcid = "@DirectLink" listener = "ognl:listeners.DirectResult" parameters = 'ognl:new java.lang.Object[]{new java.lang.Integer("8"),new java.lang.String("zjh")}' &gt; </P>
<P>第二个DirectLink，跳转到LinkResult页面 </P>
<P>&lt;/span&gt; </P>
<P>&lt;br&gt; DirectLink要传的参数是： </P>
<P>&lt;span jwcid = "@Insert" value = "ognl:Directpar1" /&gt; 和 &lt;span jwcid = "@Insert" value = "ognl:Directpar2" /&gt;&lt;p&gt; </P>
<P>第一个组件接收参数方法（监听事件）： </P>
<P>public void directlistener(IRequestCycle cycle){ </P>
<P>Object[] par=cycle.getServiceParameters(); </P>
<P>this.setDirectpar1((Integer)par[0]); </P>
<P>this.setDirectpar2((String)par[1]); </P>
<P>} </P>
<P>第二个组件接收参数方法（在跳转的页面中写监听事件）： </P>
<P>1 ．先跳转到另一个页面： </P>
<P>public void DirectResult(IRequestCycle cycle){ </P>
<P>IPage result=cycle.getPage("LinkResult"); </P>
<P>cycle.activate(result); </P>
<P>} </P>
<P>2 ．这时参数也会随 Session 传到 LinkResult 页面，在 LinkResult 页面中写监听事件。 </P>
<P>public void getpar(IRequestCycle cycle) { </P>
<P>Object[] par=cycle.getServiceParameters(); </P>
<P>this.setDirectpar2((String)par[1]); </P>
<P>this.setDirectpar1((Integer)par[0]); </P>
<P>} </P><img src ="http://www.blogjava.net/happydavy/aggbug/25613.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/happydavy/" target="_blank"> 我的java天地</a> 2005-12-27 17:51 <a href="http://www.blogjava.net/happydavy/archive/2005/12/27/25613.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tappestry网站的翻译(原创) (二)</title><link>http://www.blogjava.net/happydavy/archive/2005/12/19/24562.html</link><dc:creator> 我的java天地</dc:creator><author> 我的java天地</author><pubDate>Mon, 19 Dec 2005 01:39:00 GMT</pubDate><guid>http://www.blogjava.net/happydavy/archive/2005/12/19/24562.html</guid><wfw:comment>http://www.blogjava.net/happydavy/comments/24562.html</wfw:comment><comments>http://www.blogjava.net/happydavy/archive/2005/12/19/24562.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/happydavy/comments/commentRss/24562.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/happydavy/services/trackbacks/24562.html</trackback:ping><description><![CDATA[<P>注意<BR>Tapestry中的Listener方法和C＃中的delegate十分相象。一个特殊对象的实例中的方法被当作一个对象。调用这个listener或者listener方法有点命名的混淆。它应该被叫做delegate和delegate方法，但是已经存在的命名方式已经被广泛接受，在短时间内不容易被改变。</P>
<P>你只需要构造这listrner方法，而不是整个servlet。Tapestry会在正确的时候和正确的条件下调用listener的方法。你不需要考虑如何构造URL，以及通过URL传递什么数据，或者如何结合到你的应用程序中去。这些工作框架都替你做好了。</P>
<P>页面和组件</P>
<P>Tapestry把一个应用程序分成一系列的页面。每一个页面由Tapestry的组件组成。组件本身也许是由组件构成。这里没有人为的深度。<BR>tapestry页面本身就是组件，只是有些特殊用处的组件。<BR>所有的tapestry的组件可以成为其他组件的容器。Tapestry页面，和许多用户定义的组件一样，有一个模板，由一个特殊的html定义了一些静态的和动态的组件位置，同时有标签表明那些内嵌的组件是活跃的。组件不需要有标签。Tapestry组件参数也许是双向的，一个组件可以读取一个参数来获得一个值，或者写一个参数来设置一个值。</P>
<P>其他的组件。如form和form控制组件（TextField, PropertySelection, Checkbox等等）使得html中的form的实现变得容易。当这样的组件被显示的时候，他们从程序对象中读取属性值来提供默认值。当form被提交的时候，form中的组件读取http的查询参数，转换数值为合适的类型并且更新程序对象的属性。</P>
<P>引擎，服务和<BR>随着时间的过去，Tapestry已经发展了它自己的方言。<BR>Tapestry的引擎是一个一对象为中心的，它的作用和Httpsession在Servlet API的作用。 引擎的最终职责是存储应用程序的持久状态（从一个请求到下一个请求时存在的属性），这个任务已经通过把引擎存贮在httpsession的方式被完成了。本文档将主要讨论默认的实现，同时标注如何在适当的时候扩展，重写这些实现。</P><img src ="http://www.blogjava.net/happydavy/aggbug/24562.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/happydavy/" target="_blank"> 我的java天地</a> 2005-12-19 09:39 <a href="http://www.blogjava.net/happydavy/archive/2005/12/19/24562.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tappestry网站的翻译(原创)</title><link>http://www.blogjava.net/happydavy/archive/2005/12/16/24233.html</link><dc:creator> 我的java天地</dc:creator><author> 我的java天地</author><pubDate>Fri, 16 Dec 2005 08:02:00 GMT</pubDate><guid>http://www.blogjava.net/happydavy/archive/2005/12/16/24233.html</guid><wfw:comment>http://www.blogjava.net/happydavy/comments/24233.html</wfw:comment><comments>http://www.blogjava.net/happydavy/archive/2005/12/16/24233.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/happydavy/comments/commentRss/24233.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/happydavy/services/trackbacks/24233.html</trackback:ping><description><![CDATA[<P>Tapestry 是一个用java写成的，基于组件的网络程序框架。Tapestry不仅仅是一个简单的模板化的系统。Tapestry在Java Servlet基础上的建立的一个平台，在平台上可以建立一个动态的，交互的网站。它不仅仅是一个模板语言，而且是一个真正的框架，利用一些简单的，可以重用的组件来建立复杂的应用程序。Tapestry在建立网络程序的时候简化了很多易错的工作，例如接受各种任务，比如分发接受到的请求，建立和解释URL,处理本地化和国际化的问题以及更多。</P>
<P>对Tapestry的高度评价是"对象，方法和属性"，也就是说，不仅仅使开发者关注Servlet的API：requests, responses, sessions, attributes, parameters, URLs等等，Tapestry使得开发者更关注于对象（包括Tapestry的页面和组件，而且包括程序的对象），对象的方法以及那些对象的javaBean的属性。也就是说，在一个tapestry的程序中，用户的动作（点击链接，提交表单）会导致对象的属性的变化，这些属性和用户支持的方法（包括程序逻辑）组合在一起。</P>
<P>在Tapestry中，你不需要写servlet，你只要写一些Listener方法，你同样不需要为servlet建立URL，你可以利用一个存在的组件（例如DirectLink）并配置他的listener的参数来调用方法。那么Listener的方法到底做了什么呢？它和后台系统进行交互（通常是无状态的session EJB）或者是做一些其他的和request相关的记录，同时提供给用户一个新的页面。基本上是这个servlet的核心代码。在tapestry中，你不需要写那些重复的，机械的代码（例如建立url，分发请求，管理服务器段的状态等等），因为那些都被tapestry这个框架完成了。</P>
<P>但是这并不表示Servlet API是不可访问的，它仅仅是不跟一个典型的tapestry用户相关。</P>
<P>本文档描述了很多tapestry的一些内在的情况。本文不是教程（教程是另外一个单独的文档）。事实上，本文档是给一些tapestry的用户的指南，目的是给那些想使用tapestry的开发者。</P>
<P>tapestry目前的版本是 4.0，在过去的十几年里已经过了长足的发展。Tapestry始终关注于生成动态的html代码，尽管有大量的软件支持XHTML XML 和 WML。</P>
<P>几乎所有的Tapestry的API都是一接口的形式出现，同时有默认的实现。只要用新的对象取代现有的接口，框架的行为可以被很容易的取代。最平常的例子就是重载一个存贮的页面和它的组件（也许存贮在数据库中）。</P>
<P>最后，Tapestry有值得自豪的完整的JavaDoc的文档。本文档是用来支持那份文档的，来填补那分文档的一些不明显的不足。当然JavaDoc是最好的文档。</P>
<P>也许理解Tapestry最难的部分就是它是一个以基于组件的，而不是以基于操作的。大多数的技术（Struts，servlets, PHP等等）都是基于操作的。当你建立一个servlet以后，当用户点击一个链接或者提交一个form的时候机会调用它。你必须选定一个适当的链接，和要传递参数的名字和类型，这样你才能在URL中传递你所需要的信息。</P>
<P>对于那些操作（点击链接或提交表单），你同样必须负责去连接你的外部页面（不管他们是JSP，servlets, PHP,或者其他形式的模板技术）。这需要你建立URL并且把他们放到一个&lt;a&gt;的标签中，或者是放在一个&lt;form&gt;标签的action属性中。</P>
<P>tapestry中所有的东西都是不同的。Tapestry程序由页面组成，页面是由小的组件构成，组件本身也有可能由其他组件构成。每一个页面都由一个唯一的名字，页面中的每个组件都有它唯一的ID...这就是组件模型。同时，每一个组件都有一个地址，可以快速的和URL进行绑定。</P>
<P>事实上，在“向购物车添加物品”的操作中，你不需要写servlet，甚至也不用写组件。你只需要拿一个已有的组件，例如（DirectLink）,然后配置它。当这个组件被显示的时候，它会建立一个回调的链接，当你点击这个链接的时候，这个回调链接（包括了页面名称和页面内的组件的ID）将会调用组件上的方法，然后这个方法就会调用你的程序制定的Listener方法</P>
<P></P><img src ="http://www.blogjava.net/happydavy/aggbug/24233.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/happydavy/" target="_blank"> 我的java天地</a> 2005-12-16 16:02 <a href="http://www.blogjava.net/happydavy/archive/2005/12/16/24233.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>什么是Tapestry?</title><link>http://www.blogjava.net/happydavy/archive/2005/12/15/24051.html</link><dc:creator> 我的java天地</dc:creator><author> 我的java天地</author><pubDate>Thu, 15 Dec 2005 07:12:00 GMT</pubDate><guid>http://www.blogjava.net/happydavy/archive/2005/12/15/24051.html</guid><wfw:comment>http://www.blogjava.net/happydavy/comments/24051.html</wfw:comment><comments>http://www.blogjava.net/happydavy/archive/2005/12/15/24051.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/happydavy/comments/commentRss/24051.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/happydavy/services/trackbacks/24051.html</trackback:ping><description><![CDATA[<H2>&nbsp;</H2>
<P>Tapestry是一个使用Java语言编写的开源框架，用于创建动态的、健壮的、高灵活性的web应用程序。Tapestry框架构筑在标准的Java Servlet API之上，因此它能够很好地兼容任何servlet容器或者应用服务。</P>
<P>Tapestry将一个web应用程序分离为一组页面，而每个页面又由多个组件组成。这就提供了一个协调一致的结构，使得Tapestry框架能够专注于任何一个关键细节，例如：URL解析和派遣、持久化状态储存在客户端还是储存在服务器端、用户输入效验、本地化或国际化、和异常报告。对 Tapestry应用程序的开发包括：使用普通的HTML标签创建HTML模板，然后使用XML描述文件（可选）将这些模板与少量的java代码结合在一起。在Tapestry中，创建你的应用程序是通过使用对象、方法以及对象的属性－－－而并非由URLs和查询参数。Tapestry带来了真正的 Java Web应用程序OOP编程。</P>
<P>Tapestry能够非常容易地创建新组件，就如同以常规的步骤来构建应用程序一样。而官方提供了超过五十种组件，这些组件包括各种各样简单的输出组件，以及非常复杂的表格组件和树型目录组件。</P>
<P>Tapestry能够构建，从小型的应用程序到各种大型团队开发的几百个独立页面的大型应用程序。Tapestry能够非常容易地与各种底层框架结合，包括J2EE、Hivemind和Spring。</P>
<P>Tapestry发布于Apache Software Licence 2.0。</P>
<H2><A name=Tapestry框架介绍-Tapestry的哲理></A>Tapestry的哲理</H2>
<P>Tapestry由以下四种关键原则组成：</P>
<UL>
<LI>简单 － 应用程序并非像火箭科学那么复杂。</LI>
<LI>一致性 － 怎样操作页面，怎样操作组件。在小应用程序中怎样操作，那么在大型应用程序中就怎样操作。不同的开发者会在相识问题上找到相似的解决方案。</LI>
<LI>效率 － 应用程序是可以被升级的。</LI>
<LI>良好的反馈信息 － 当发生错误或者异常的时候，Tapestry框架本身的运作并不会发生异常；实际上，Tapestry框架会提供非常有用的错误诊断信息。</LI></UL>
<P>这四种原则共同组成了一个宗旨：最简单的选择，就是最正确的选择。越早选择Tapestry框架，那么就越早避免许多麻烦。</P>
<P>我们发现面向组件式web开发是实现这些原则的最好途径。围绕着组件来组织框架和你的应用程序，让框架来替你实现那些令人厌烦的底层代码。你只需要写少量的代码，写一些简单的代码，有时候你甚至不需要写代码。Tapestry让你轻松。</P>
<H2><A name=Tapestry框架介绍-Tapestry4.0></A>Tapestry 4.0</H2>
<P>Tapestry4.0增加了许多新特性以便提高你的工作效率：</P>
<UL>
<LI>&nbsp;4.0中新的DTDs配置更加简化。</LI>
<LI>在HTML中与在XML配置文件中绑定参数的方式被协调一致，都使用相同的绑定前缀。</LI>
<LI>"Friendly"URLs（就是说，URLs中携带更多路径信息和更少的查询参数信息）已经被集成。这使得你可以将应用程序分别放在多个文件夹中而减少混乱，并且可以通过这种方式提高J2EE项目发布的安全性。</LI>
<LI>监听方法更加简单和灵活；URL中的监听参数会自动映射到监听方法的参数，并且监听方法可以返回页面名称或者页面实例来激活页面。</LI>
<LI>组件参数不必在担心"direction"设置。</LI>
<LI>除了每个页面和每个组件的消息策略之外，应用程序现在拥有一个全局的消息策略。消息不再从组件消息策略中寻找，而是从应用程序策略中查询。</LI>
<LI>完全支持对JSR-168 Portlets的开发。</LI>
<LI>Tapestry 4.0比Tapestry3.0减少了对反射和OGNL的使用；一部分原因是使用了许多新绑定前缀，大部分原因是改变了参数的实现方式。</LI>
<LI>Hivemind的services和Spring的beans能够直接被页面和组件类注入。</LI>
<LI>Tapestry 4.0提供了对JDK 1.5 annotation的支持（但是Tapestry本身是运作于JDK 1.3）。</LI>
<LI>Tapestry 4.0引进了一个全新的更健壮的用户输入效验子系统。感谢Paul！</LI>
<LI>现在能够在错误报告里面，用横线精确地标明文件中发生错误的代码行。</LI>
<LI>Forms现在能够被取消，避过客户端效验逻辑，并触发指定的服务器端监听方法。</LI>
<LI>你不再局限于Global对象和Visit对象；只要你愿意，可以使用任意多的application状态对象。</LI>
<LI>由于Hivemind构筑与Tapestry底层，意味着你可以容易地按照自己的需要修改Tapestry的实现。</LI>
<LI>页面属性现在能够被持久化于客户端中，就如同在session中一样。</LI>
<LI>组件和组件参数现在可以被标识为"deprecated"。组件参数可以拥有别名（当重新命名一个参数时使用）。</LI></UL>
<P>可以列举出无数Tapestry 4.0的变化。总之，所有的变化都是令人震撼的，减少了开发者的java代码，减少了模板的复杂性，简化（或者除去）了XML文件。</P>
<H2><A name=Tapestry框架介绍-现状></A>现状</H2>
<P>Tapestry 4.0的开发工作仍在全力进行中。文档从以前旧的DocBook形式转变到新的Forrest形式，剔除了许多临时性间隔。指南中新的Quick Start章节已经被撰写。</P>
<P>Tapestry 4.0已经接近最终的beta周期；新特性将会被延续到Tapestry 4.1，并会继续逐步完善文档和修正bug。最终版本的Tapestry 4.0预计（不保证）会在2005年十月推出。</P>
<H2><A name=Tapestry框架介绍-从4.0beta12升级></A>从4.0-beta-12升级</H2>
<P>作为<SPAN class=nobr><A title="Visit page outside Confluence" href="http://issues.apache.org/jira/browse/TAPESTRY-620" rel=nofollow>TAPESTRY-620<SUP><IMG class=rendericon height=7 alt="" src="http://www.javaeye.com/images/icons/linkext7.gif" width=7 align=absMiddle border=0></SUP></A></SPAN>修正的一部分：将当前的IRquestCycle作为可注入的service，简化Tapestry中的一些接口，取消IRequestCycle参数。这可能要求对一些地方的代码实现作适当调整。</P>
<H2><A name=Tapestry框架介绍-从4.0beta10升级></A>从4.0-beta-10升级</H2>
<P>在beta-10和之后的版本中，对于asset service，friendly URLs的配置改变了。在你的hivemind.xml中，将&lt;asset-encoder id="asset" path="/assets/"/&gt; 改为&lt;asset-encoder id="asset" path="/assets"/&gt;（注意斜杠已经被去掉）。</P>
<H2><A name=Tapestry框架介绍-从Tapestry3.0升级></A>从Tapestry 3.0升级</H2>
<P>Tapestry 4.0具有很多新特性，考虑到向后兼容性，有些地方做了限制。具体细节以后会发布，但是至少：</P>
<UL>
<LI>Tapestry3.0 页面和组件规范仍然保留。</LI>
<LI>页面和组件的模板没有改变。</LI></UL>
<P>升级的时候，你将遇到下列问题：</P>
<UL>
<LI>引擎service的定义已经完全改变，可以参看IEngineService API。</LI>
<LI>BaseEngine的子类通过override来操作异常的方式已经改变。现在可以通过新的Hivemind services来重构默认的配置。</LI>
<LI>direction参数的"custom"已经不再使用。定义一个参数总是会生成对应的property。</LI>
<LI>参数都不会再通过<EM>parameterName</EM>绑定property，取而代之的是你必须使用getBinding()方法。</LI>
<LI>page loader和specification delegate的关系已经改变，现在delegate提供的specifications会被loader缓存（在3.0中，由delegate来负责缓存）。</LI>
<LI>Tapestry不再需要Jakarta commons-lang library支持，这意味着不能再使用EnumPropertySelectionModel类（然而，你可以很容易地从Tapestry 3.0中拷贝到源代码）。</LI></UL><img src ="http://www.blogjava.net/happydavy/aggbug/24051.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/happydavy/" target="_blank"> 我的java天地</a> 2005-12-15 15:12 <a href="http://www.blogjava.net/happydavy/archive/2005/12/15/24051.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring简介 </title><link>http://www.blogjava.net/happydavy/archive/2005/10/28/17282.html</link><dc:creator> 我的java天地</dc:creator><author> 我的java天地</author><pubDate>Fri, 28 Oct 2005 14:23:00 GMT</pubDate><guid>http://www.blogjava.net/happydavy/archive/2005/10/28/17282.html</guid><wfw:comment>http://www.blogjava.net/happydavy/comments/17282.html</wfw:comment><comments>http://www.blogjava.net/happydavy/archive/2005/10/28/17282.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/happydavy/comments/commentRss/17282.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/happydavy/services/trackbacks/17282.html</trackback:ping><description><![CDATA[<P><STRONG>Spring简介</STRONG>&nbsp;<BR>关于Spring&nbsp;Framework，今年夏天你可能已经听见很多的议论。在本文中,我将试图解释Spring能完成什么，和我怎么会认为它能帮助你开发J2EE应用程序。&nbsp;<BR><BR><STRONG>另一framework？&nbsp;<BR></STRONG>你可能正在想“不过是另外一个的framework”。当已经有许多开放源代码(和专有)&nbsp;J2EE&nbsp;framework时，为什么你应该费心读这篇文章,或下载Spring&nbsp;Framework？&nbsp;<BR><BR><STRONG>我相信Spring是独特的</STRONG>,因为若干个原因:&nbsp;<BR>.&nbsp;它定位的领域是许多其他流行的framework没有的。Spring关注提供一种方法管理你的业务对象。&nbsp;<BR>.&nbsp;Spring是全面的和模块化的。Spring有分层的体系结构,这意味着你能选择使用它孤立的任何部分,它的架构仍然是内在稳定的。因此从你的学习中，你可得到最大的价值。例如,你可能选择仅仅使用Spring来简单化JDBC的使用,或用来管理所有的业务对象。&nbsp;<BR>.&nbsp;它的设计从底部帮助你编写易于测试的代码。Spring是用于测试驱动工程的理想的framework。&nbsp;<BR><BR>Spring对你的工程来说，它不需要一个以上的framework。<STRONG>Spring是潜在地一站式解决方案,定位于与典型应用相关的大部分基础结构</STRONG>。它也涉及到其他framework没有考虑到的内容。&nbsp;<BR><BR>尽管<STRONG>它仅仅是一个从2003年2月才开始的开源工程，但Spring有较长的历史根基</STRONG>。这个开源工程是起源自我在2002年后期出版的<STRONG>《Expert&nbsp;One-on-One&nbsp;J2EE设计与开发》</STRONG>书中的基础代码。这本书展示了Spring背后的基础架构。然而,这个基础架构的概念要追溯到2000年的早些时候,并且反映了我为一系列成功的商业工程开发基础结构的经验。&nbsp;<BR><BR>从2003年1月，Spring已经落户于SourceForge上。现在有10个开发人员,其中6是高度投入的积极分子。&nbsp;<BR><BR><STRONG>Spring的架构性的好处&nbsp;<BR></STRONG><BR>在我们进入细节以前，让我们看一下Spring可以给一个工程带来的一些好处:&nbsp;<BR><BR>.&nbsp;Spring能有效地组织你的中间层对象,无论你是否选择使用了EJB。如果你仅仅使用了Struts或其他的包含了J2EE特有APIs的framework，你会发现Spring关注了遗留下的问题，。&nbsp;<BR><BR>.&nbsp;<U>Spring能消除在许多工程上对Singleton的过多使用</U>。根据我的经验，这是一个主要的问题，它减少了系统的可测试性和面向对象特性。&nbsp;<BR><BR>.&nbsp;Spring能消除使用各种各样格式的属性定制文件的需要,在整个应用和工程中，可通过一种一致的方法来进行配置。曾经感到迷惑，一个特定类要查找迷幻般的属性关键字或系统属性,为此不得不读Javadoc乃至源编码吗？有了Spring，你可很简单地看到类的JavaBean属性。倒置控制的使用(在下面讨论)帮助完成这种简化。&nbsp;<BR><BR>.&nbsp;Spring能通过接口而不是类促进好的编程习惯，减少编程代价到几乎为零。&nbsp;<BR>.&nbsp;Spring被设计为让使用它创建的应用尽可能少的依赖于他的APIs。在Spring应用中的大多数业务对象没有依赖于Spring。&nbsp;<BR>.&nbsp;<U>使用Spring构建的应用程序易于单元测试</U>。&nbsp;<BR>.&nbsp;<U>Spring能使EJB的使用成为一个实现选择,而不是应用架构的必然选择</U>。你能选择用POJOs或local&nbsp;EJBs来实现业务接口，却不会影响调用代码。&nbsp;<BR>.&nbsp;<U>Spring帮助你解决许多问题而无需使用EJB。Spring能提供一种EJB的替换物</U>，它们适于许多web应用。例如,Spring能使用AOP提供声明性事务而不通过使用EJB容器，如果你仅仅需要与单个的数据库打交道，甚至不需要JTA实现。&nbsp;<BR>.&nbsp;Spring为数据存取提供了一致的框架,不论是使用JDBC或O/R&nbsp;mapping产品（如Hibernate）。&nbsp;<BR>Spring确实使你能通过最简单可行的解决办法解决你的问题。这些特性是有很大价值的。&nbsp;<BR><BR><STRONG>Spring能做什么？</STRONG>&nbsp;<BR><BR>Spring提供许多功能,在此我将快速地依次展示其各个主要方面。&nbsp;<BR><BR>任务描述：&nbsp;<BR>首先,让我们明确Spring范围。尽管Spring覆盖了许多方面，但我们已经有清楚的概念，它什么应该涉及和什么不应该涉及。&nbsp;<BR><BR><STRONG>Spring的主要目的是使J2EE易用和促进好编程习惯</STRONG>。&nbsp;<BR>Spring不重新开发已有的东西。因此，在Spring中你将发现没有日志记录的包,没有连接池,没有分布事务调度。这些均有开源项目提供(例如Commons&nbsp;Logging&nbsp;用来做所有的日志输出，或Commons&nbsp;DBCP用来作数据连接池),或由你的应用程序服务器提供。因为同样的的原因，我们没有提供O/R&nbsp;mapping层，对此，已有有好的解决办法如Hibernate和JDO。&nbsp;<BR><BR><U>Spring的目标是使已存在的技术更加易用</U>。例如,尽管我们没有底层事务协调处理，但我们提供了一个抽象层覆盖了JTA或任何其他的事务策略。&nbsp;<BR><BR><U>Spring没有直接和其他的开源项目竞争，除非我们感到我们能提供新的一些东西。</U>例如，象许多开发人员，我们从来没有为Struts高兴过，并且感到在MVC&nbsp;web&nbsp;framework中还有改进的余地。在某些领域，例如轻量级的IoC容器和AOP框架，Spring有直接的竞争，但是在这些领域还没有已经较为流行的解决方案。(Spring在这些区域是开路先锋。)&nbsp;<BR><BR><U>Spring也得益于内在的一致性</U>。&nbsp;<BR>所有的开发者都在唱同样的的赞歌,基础想法依然是Expert&nbsp;One-on-One&nbsp;J2EE设计与开发的那些。&nbsp;<BR>并且我们已经能够使用一些主要的概念,例如倒置控制，来处理多个领域。&nbsp;<BR><BR><U>Spring在应用服务器之间是可移植的</U>。&nbsp;<BR>当然保证可移植性总是一次挑战，但是我们避免任何特定平台或非标准化,并且支持在WebLogic，Tomcat，Resin，JBoss，WebSphere和其他的应用服务器上的用户。&nbsp;<BR><BR><STRONG>倒置控制容器</STRONG>&nbsp;<BR>Spring的设计核心是&nbsp;org.springframework.beans&nbsp;包,&nbsp;为与JavaBeans一起工作而设计。&nbsp;这个包一般不直接被用户使用,&nbsp;但作为基础为更多的其他功能服务.&nbsp;下一个较高层面的抽象是"Bean&nbsp;Factory"。&nbsp;Spring&nbsp;bean&nbsp;factory&nbsp;是一个普通的Factory，它使对象能够按名称获取，并且能管理对象之间的关系。&nbsp;<BR><BR>Bean&nbsp;factories&nbsp;支持两种对象模式:&nbsp;<BR>.&nbsp;Singleton：在此模式中，有一个具有特定名称的共享对象实例，它在查找时被获取。这是默认的，而且是最为经常使用的。它对于无状态对象是一种理想的模式。&nbsp;<BR>.Prototype：在此模式中，每次获取将创建一个独立的对象。例如，这可以被用于允许用户拥有他们自己的对象。&nbsp;<BR><BR>由于&nbsp;org.springframwork.beans.factory.BeanFactory是一个简单的接口，它能被为了底层存储方法而实现。你能够方便地实现你自己的BeanFactory，尽管很少用户需要。最为常用的定义是：&nbsp;<BR>.<STRONG>XmlBeanFactory</STRONG>：&nbsp;可解析简单直观的定义类和命名对象属性的XML结构。&nbsp;我们提供了一个DTD来使编写更容易。&nbsp;<BR>.<STRONG>ListableBeanFactoryImpl</STRONG>：可提供解析存放在属性文件中的bean定义，和可通过编程创建BeanFactories。&nbsp;<BR><BR>每个bean定义可能是一个POJO(通过类名和JavaBean初始属性定义)，或是一个FactoryBean。FactoryBean接口添加了一个间接层。通常，这用于使用AOP或其他方法来创建代理对象：例如，添加了声明性事务管理的代理。(这在概念上和EJB侦听相似，但在实践中实现更简单。)&nbsp;<BR><BR>BeanFactories能在一个层次结构中可选择性的参与，根据来自祖先的继承定义。这使在整个应用中公共配置的共享成为可能，虽然个别资源，如controller&nbsp;servlets，也拥有他们自己的独立的对象集合。&nbsp;<BR><BR>这种使用JavaBeans的动机在<FONT color=#ff0000>&lt;Expert&nbsp;One-on-One&nbsp;J2EE&nbsp;Design&nbsp;and&nbsp;Development&gt;的第四章</FONT>中有描述，在TheServerSide网站上的有免费的PDF(<IMG alt=::URL:: hspace=2 src="http://www.blogcn.com/images/aurl.gif" align=absBottom border=0><A href="http://www.theserverside.com/resources/article.jsp?l=RodJohnsonInterview)." target=_blank>http://www.theserverside.com/resources/article.jsp?l=RodJohnsonInterview).</A> &nbsp;<BR><BR>通过BeanFactory概念，Spring成为一个倒置控制的容器。(我非常不喜欢container这个术语，因为它使人联想到重量级容器，如EJB容器。Spring的BeanFactory是一个可通过一行代码创建的容器，并且不需要特殊的部署步骤。)&nbsp;<BR><BR>位于倒置控制背后的概念是在<FONT color=#ff0000>Hollywood原则</FONT>中经常表述："Don’t&nbsp;call&nbsp;me,&nbsp;I’ll&nbsp;call&nbsp;you."&nbsp;IoC将控制职责搬进了框架中，并脱离应用代码。涉及到配置的地方，意思是说在传统的容器体系结构中，如EJB，一个组件可以调用容器并问“我需要它给我做工作的对象X在哪里?”；使用IoC容器则只需指出组件需要X对象，在运行时容器会提供给它。容器基于方法名作出这种说明，或可能根据配置数据如XML。&nbsp;<BR><BR><STRONG>倒置控制的几个重要好处</STRONG>。如：&nbsp;<BR>.&nbsp;因为组件不需要在运行时间寻找合作者，所以他们可以更简单的编写和维护。在Spring的IoC版本里，组件通过暴露JavaBean的setter方法表达他们依赖的其他组件。这相当于EJB通过JNDI来查找，EJB查找需要开发人员编写代码。&nbsp;<BR>.&nbsp;同样原因，应用代码更容易测试。JavaBean属性是简单的，Java核心的，并且容易测试：仅编写一个包含自身的Junit测试方法用来创建对象和设置相关属性即可。&nbsp;<BR>.&nbsp;一个好的IoC实现隐藏了强类型。如果你使用一个普通的factory来寻找合作者，你必须通过类型转换将返回结果转变为想要的类型。这不是一个主要问题，但是不雅观。使用IoC，你在你的代码中表达强类型依赖，框架将负责类型转换。这意味着在框架配置应用时，类型不匹配将导致错误；在你的代码中，你无需担心类型转换异常。&nbsp;<BR>.&nbsp;大部分业务对象不依赖于IoC容器的APIs。这使得很容易使用遗留下来的代码，且很容易的使用对象无论在容器内或不在容器内。例如，Spring用户经常配置Jakarta&nbsp;Commons&nbsp;DBCP数据源为一个Spring&nbsp;bean：不需要些任何定制代码去做这件事。我们说一个IoC容器不是侵入性的：使用它并不会使你的代码依赖于它的APIs。任何JavaBena在Spring&nbsp;bean&nbsp;factory中都能成为一个组件。&nbsp;<BR><BR>最后应该强调的是，IoC&nbsp;不同于传统的容器的体系结构(&nbsp;如EJB),&nbsp;应用代码最小程度的依靠于容器。这意味着你的业务对象可以潜在的被运行在不同的IoC&nbsp;框架上-或者在任何框架之外-不需要任何代码改。&nbsp;<BR><BR>以我的经验和作为Spring用户，过分强调IoC给应用代码带来的好处是不容易的。&nbsp;<BR><BR><U>IoC不是一个新概念，但是它在J2EE团体里面刚刚到达黄金时间</U>。&nbsp;有一些可供选择的IoC&nbsp;容器:&nbsp;notably,&nbsp;Apache&nbsp;Avalon,&nbsp;PicoContainer&nbsp;和&nbsp;HiveMind.&nbsp;Avalon&nbsp;不会成为特别流行的，尽管它很强大而且有很长的历史。<U>Avalon是相当的重量级和复杂的，并且看起来比新的IoC解决方案更具侵入性</U>。&nbsp;PicoContainer是一个轻量级而且更强调通过构造器表达依赖性而不是JavaBean&nbsp;属性。&nbsp;与Spring不同，它的设计允许每个类型一个对象的定义(可能局限性结果来自它对Java代码外的元数据的拒绝)。作为和Spring&nbsp;and&nbsp;PicoContainer&nbsp;and&nbsp;other&nbsp;IoC&nbsp;frameworks的比较，可参看文章<IMG alt=::URL:: hspace=2 src="http://www.blogcn.com/images/aurl.gif" align=absBottom border=0><A href="http://www.springframework.org/docs/lightweight_container.html." target=_blank>http://www.springframework.org/docs/lightweight_container.html.</A> &nbsp;这个业面包含了PicoContainer站点链接&nbsp;。&nbsp;<BR><BR>Spring&nbsp;BeanFactories&nbsp;是非常轻量级的。用户已经成功地将他们应用在applets中和单独的Swing应用中。(它们也很好地工作在EJB容器中。)&nbsp;没有特殊的部署步骤和可察觉的启动时间。这个能力表明一个容器在应用的任何层面差不多立即可以发挥非常大的价值。&nbsp;<BR><BR>Spring&nbsp;BeanFactory&nbsp;概念应用贯穿于Spring整体，&nbsp;而且是Spring如此内在一致的关键原因。在IoC容器中，Spring也是唯一的，它使用IoC作为基础概念贯穿于整个框架。&nbsp;<BR><BR>对应用开发人员，最重要的是，一个或多个BeanFactory提供一个定义明确的业务对象层。这是类似的，但比local&nbsp;session&nbsp;bean层更简单。与EJBs不同，在这个层中的对象可能是相关的，并且他们的关系被自己的factory管理。有一个定义明确的业务对象层对于一个成功的体系结构是非常重要的。&nbsp;<BR><BR>Spring&nbsp;ApplicationContext&nbsp;是BeanFactory的子接口,为下列提供支持:&nbsp;<BR><U>.消息寻找，国际化支持&nbsp;<BR>.事件机制，允许应用对象发布和随意地注册为事件监听&nbsp;<BR>.便携文件和资源访问</U>&nbsp;<BR><BR>XmlBeanFactory示例&nbsp;<BR>Spring用户通常在XML“bean定义”文件中配置他们的应用。Spring的XML&nbsp;bean定义文档的根是一个&lt;beans&gt;&nbsp;元素。该元素包含一个或多个&nbsp;&lt;bean&gt;定义。我们一般指定一个bean定义的类和属性。我们也必须指定ID作为标识，我们将在代码中使用该标志。&nbsp;<BR>让我们来看一个简单的例子，在J2EE应用中常看到用来配置三个应用对象：&nbsp;<BR>.&nbsp;J2EE&nbsp;DataSource&nbsp;<BR>.&nbsp;使用DataSource的DAO&nbsp;<BR>.&nbsp;在处理过程中使用DAO的业务对象&nbsp;<BR><BR>在下面的例子中，我们使用一个来自Jakarta&nbsp;Commons&nbsp;DBCP项目的BasicDataSource。这个class(和其他存在的class一样)可以简单地被应用在Spring&nbsp;bean&nbsp;factory中，因为它提供了JavaBean格式的配置。需要在shutdown时被调用的Close方法可通过Spring的"destroy-method"属性被注册，来避免BasicDataSource需要实现任何Spring&nbsp;接口。&nbsp;<BR><BR>代码:&nbsp;&lt;textarea&gt;<BR>&lt;beans&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id="myDataSource"&nbsp;class="org.apache.commons.dbcp.BasicDataSource"&nbsp;destroy-method="close"&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="driverClassName"&gt;&lt;value&gt;com.mysql.jdbc.Driver&lt;/value&gt;&lt;/property&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="url"&gt;&lt;value&gt;jdbc:mysql://localhost:3306/mydb&lt;/value&gt;&lt;/property&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="username"&gt;&lt;value&gt;root&lt;/value&gt;&lt;/property&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt;&nbsp;&lt;/textarea&gt;<BR><BR><BR>我们感兴趣的BasicDataSource的所有属性都是String型的，因此，我们用&lt;value&gt;元素来指定他们的值。如果必要的话，Spring使用标准的&nbsp;JavaBean属性编辑器机制来转换String以表示其他的类型。&nbsp;<BR><BR>现在，我们定义了DAO，它有一个对DataSource的bean引用。Bean间关系通过&lt;ref&gt;元素来指定:&nbsp;<BR>代码:&nbsp;&lt;textarea&gt;<BR>&lt;bean&nbsp;id="exampleDataAccessObject"&nbsp;class="example.ExampleDataAccessObject"&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="dataSource"&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref&nbsp;bean="myDataSource"/&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt;&nbsp;&lt;/textarea&gt;<BR><BR>业务对象有一个DAO的引用和一个int型属性(exampleParam):&nbsp;<BR>代码:&nbsp;<BR>&lt;textarea&gt;&lt;bean&nbsp;id="exampleBusinessObject"&nbsp;class="example.ExampleBusinessObject"&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="dataAccessObject"&gt;&lt;ref&nbsp;bean="exampleDataAccessObject"/&gt;&lt;/property&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="exampleParam"&gt;&lt;value&gt;10&lt;/value&gt;&lt;/property&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt;&lt;/beans&gt;&nbsp;&lt;/textarea&gt;&nbsp;<BR><BR><BR>对象间的关系一般在配置中明确地设置，象此例子一样。我们认为这样做是件好事情。无论如何，Spring也提供了我们叫做"<STRONG>autowire</STRONG>"的支持，&nbsp;一个la&nbsp;PicoContainer，在那里，它可以指出bean间的依赖关系。这样做的局限性－如使用PicoContainer－是如果有一个特殊类型的多个Bean，要作出一个类型应该与哪个实例相关的判断将是不可能的。好的方面，在factory初始化后，不理想的依赖可能会被捕获到。(Spring&nbsp;也为清楚的配置提供一种可选的依赖检查，它可以完成这个目的)&nbsp;<BR><BR>如果我们不想明确的编写他们的关系，在上面的例子中，我们可如下使用autowire特性：&nbsp;<BR>&lt;textarea&gt;&nbsp;<BR>&lt;bean&nbsp;id="exampleBusinessObject"&nbsp;class="example.ExampleBusinessObject"&nbsp;autowire="byType"&gt;&nbsp;<BR>&lt;property&nbsp;name="exampleParam"&gt;&lt;value&gt;10&lt;/value&gt;&lt;/property&gt;&nbsp;<BR>&lt;/bean&gt;&nbsp;&lt;/textarea&gt;&nbsp;<BR><BR>使用这用用法，Spring将找出exampleBusinessObject的dataSource属性应该被设置为在当前BeanFactory中找到的DataSource实现。在当前的BeanFactory中，如果所需要类型的bean不存在或多于一个，将产生一个错误。我们依然要设置exampleParam属性，因为它不是一个引用。&nbsp;<BR><BR>Autowire支持和依赖检查刚刚加入CVS并将在Spring&nbsp;1.0&nbsp;M2(到10/20,2003)中提供。本文中所讨论的所有其他特性都包含在当前1.0&nbsp;M1版本中。&nbsp;<BR><BR><U>来自Java代码的外在关系比硬编码有极大的好处，因为改变XML文件而无需改变一行Java代码是可能的。</U>例如，我们可以简单地改变myDataSource的bean定义来提供不同的bean&nbsp;class以使用一个可供选择的连接池，或者一个测试数据源。&nbsp;在一个单独可选的XML片断中，我们可以用Spring的JNDI&nbsp;定位FactoryBean来从application&nbsp;server获取一个数据源。&nbsp;<BR><BR>现在让我们来看例子中业务对象的java&nbsp;代码。注意下面列出的代码中没有对Spring的依赖。不像EJB容器，Spring&nbsp;BeanFactory不是侵入性的：在应用对象里面你通常不需要对他们编码。&nbsp;<BR>代码:&nbsp;<BR>public&nbsp;class&nbsp;ExampleBusinessObject&nbsp;implements&nbsp;MyBusinessObject&nbsp;{&nbsp;<BR><BR>&nbsp;&nbsp;&nbsp;private&nbsp;ExampleDataAccessObject&nbsp;dao;&nbsp;<BR>&nbsp;&nbsp;&nbsp;private&nbsp;int&nbsp;exampleParam;&nbsp;<BR><BR>&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setDataAccessObject(ExampleDataAccessObject&nbsp;dao)&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.dao&nbsp;=&nbsp;dao;&nbsp;<BR>&nbsp;&nbsp;&nbsp;}&nbsp;<BR><BR>&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setExampleParam(int&nbsp;exampleParam)&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.exampleParam&nbsp;=&nbsp;exampleParam;&nbsp;<BR>&nbsp;&nbsp;&nbsp;}&nbsp;<BR><BR>&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;myBusinessMethod()&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;do&nbsp;stuff&nbsp;using&nbsp;dao&nbsp;<BR>&nbsp;&nbsp;&nbsp;}&nbsp;<BR>}&nbsp;<BR><BR><BR><U>注意属性设置器</U>，在bean定义文档中，它对应与XML引用。这些将在对象使用之前被Spring调用.&nbsp;<BR><BR>这些应用bean不需要依赖于Spring。他们不需要实现任何Spring接口或者继承Spring的类：他们只需要遵守JavaBeans命名习惯。在Spring&nbsp;应用环境之外重用它们是非常简单的，例如，一个测试环境。只是例示它有默认的构造器，并且通过setDataSource()和setExampleParam()的调用来手工设置它的属性。<U>只要你有一个没有参数的构造器，如果你想在单行代码支持程序化的创建，你可以自由定义其他的带有多个属性构建的器。</U>&nbsp;<BR><BR>注意，在业务接口中没有声明的JavaBean属性将会一起工作。&nbsp;他们是一个实现细节。我们可以插入带有不同bean属性的不同的实现类而不影响连接对象或者调用代码。&nbsp;<BR><BR>当然，Spring&nbsp;XML&nbsp;bean&nbsp;factories&nbsp;有更多的功能没有在这里描述，但是，这将给你一种基本使用的感觉。同时，简单的属性和有JavaBean属性编辑器的属性，Spring可以自动处理lists,maps和java.util.Properties.<BR></P><img src ="http://www.blogjava.net/happydavy/aggbug/17282.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/happydavy/" target="_blank"> 我的java天地</a> 2005-10-28 22:23 <a href="http://www.blogjava.net/happydavy/archive/2005/10/28/17282.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> String 这个特殊的对象</title><link>http://www.blogjava.net/happydavy/archive/2005/09/16/13138.html</link><dc:creator> 我的java天地</dc:creator><author> 我的java天地</author><pubDate>Fri, 16 Sep 2005 02:44:00 GMT</pubDate><guid>http://www.blogjava.net/happydavy/archive/2005/09/16/13138.html</guid><wfw:comment>http://www.blogjava.net/happydavy/comments/13138.html</wfw:comment><comments>http://www.blogjava.net/happydavy/archive/2005/09/16/13138.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/happydavy/comments/commentRss/13138.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/happydavy/services/trackbacks/13138.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 大家先来看看一段奇怪的程序： public class TestString { public static void main(String[] args) { String s1 = "Monday"; String s2 = "Monday"; } } 这个程序真是简单啊！可是有什么问题呢？ 1. 来自 String 的忧虑 上面这段程序中，到底有几个...&nbsp;&nbsp;<a href='http://www.blogjava.net/happydavy/archive/2005/09/16/13138.html'>阅读全文</a><img src ="http://www.blogjava.net/happydavy/aggbug/13138.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/happydavy/" target="_blank"> 我的java天地</a> 2005-09-16 10:44 <a href="http://www.blogjava.net/happydavy/archive/2005/09/16/13138.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>上海面试的总结</title><link>http://www.blogjava.net/happydavy/archive/2005/08/25/11046.html</link><dc:creator> 我的java天地</dc:creator><author> 我的java天地</author><pubDate>Thu, 25 Aug 2005 06:00:00 GMT</pubDate><guid>http://www.blogjava.net/happydavy/archive/2005/08/25/11046.html</guid><wfw:comment>http://www.blogjava.net/happydavy/comments/11046.html</wfw:comment><comments>http://www.blogjava.net/happydavy/archive/2005/08/25/11046.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/happydavy/comments/commentRss/11046.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/happydavy/services/trackbacks/11046.html</trackback:ping><description><![CDATA[<P>单位有事把我召回来了，真郁闷，已经收到两家公司的录用函了，最可惜的是一家做外包的公司已经准备发录用函了，在IBM上班，上下班都有班车，面试用英语聊了一个多小时，终于通过了，薪水肯定不会低，太可惜了555555<BR>回来好几天了，为了总结这次去上海成功应聘两家的经验，特将面试的试题总结如下，以备下次找到更好的公司而努力，也请hotmanx指点一下<BR>1&nbsp; HashMap和HashTable有什么区别</P>
<P>2&nbsp; 数据库中有以下数据<BR>&nbsp;ID(pri)(Auto)&nbsp;name&nbsp;pass<BR>&nbsp;1&nbsp;&nbsp;aaa&nbsp;111<BR>&nbsp;2&nbsp;&nbsp;bbb&nbsp;222<BR>&nbsp;3&nbsp;&nbsp;ccc&nbsp;333<BR>请用一条SQL语句将现有的三条记录复制一下，达到以下的效果<BR>&nbsp;ID(pri)&nbsp;(Auto)&nbsp;name&nbsp;pass<BR>&nbsp;1&nbsp;&nbsp;aaa&nbsp;111<BR>&nbsp;2&nbsp;&nbsp;bbb&nbsp;222<BR>&nbsp;3&nbsp;&nbsp;ccc&nbsp;333<BR>&nbsp;4&nbsp;&nbsp;aaa&nbsp;111<BR>&nbsp;5&nbsp;&nbsp;bbb&nbsp;222<BR>&nbsp;6&nbsp;&nbsp;ccc&nbsp;333<BR>再用一条sql删除重复记录<BR>这个要hotman_x这个sqlA来回答了，呵呵</P>
<P>3&nbsp; 在服务器端，从一个jsp页面中跳到另外一个jsp页面中有几种方法？</P>
<P>4&nbsp; 数据库中表结构如下，<BR>&nbsp;ID（Pri）&nbsp; int<BR>&nbsp;no&nbsp;&nbsp;&nbsp; int<BR>&nbsp;name&nbsp;&nbsp;&nbsp; varchar<BR>&nbsp;birthDay&nbsp;&nbsp; Date<BR>&nbsp;用java写一个函数,返回所有符合条件 no = int a&nbsp; &amp; name = str $ birthdavy = date 的结果集合</P>
<P>5 jsp和Servlet的区别和联系</P>
<P>6&nbsp; 设计一个权限管理模型，分为a＆b两组 a组的一般用户只能读取a的table，a组中的管理员可以对a的table进行CRUD<BR>同样，b组的一般用户只能读取b的table，b组中的管理员可以对b的table进行CRUD<BR>超级管理员可以对a＆b的table进行CRUD<BR>写出部分实现代码</P>
<P>7 居然还有一家公司让我用30分钟的时间作了50道脑筋急转弯，我得了96分，呵呵</P>
<P>上面的题目除了那个sql的题目我没做出来，别的题目还是让公司比较满意的 呵呵<BR></P><img src ="http://www.blogjava.net/happydavy/aggbug/11046.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/happydavy/" target="_blank"> 我的java天地</a> 2005-08-25 14:00 <a href="http://www.blogjava.net/happydavy/archive/2005/08/25/11046.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Learn Spring in spring（转载）</title><link>http://www.blogjava.net/happydavy/archive/2005/08/25/11043.html</link><dc:creator> 我的java天地</dc:creator><author> 我的java天地</author><pubDate>Thu, 25 Aug 2005 05:52:00 GMT</pubDate><guid>http://www.blogjava.net/happydavy/archive/2005/08/25/11043.html</guid><wfw:comment>http://www.blogjava.net/happydavy/comments/11043.html</wfw:comment><comments>http://www.blogjava.net/happydavy/archive/2005/08/25/11043.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/happydavy/comments/commentRss/11043.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/happydavy/services/trackbacks/11043.html</trackback:ping><description><![CDATA[<P><BR>当前的形势是，非常多的Java程序员言必称Spring，如此大面积的程序员集体叫”春”，体现了Spring框架的威力。 <BR>　Spring的设计目的是简化J2EE开发，所以如果我们学习、使用它的时候还需要抓破头皮口吐白沫的话，岂不是个笑话？就我的经验来说，Spring在这方面做得很好，的确是一个很牛叉易用的框架。<BR>　一、IoC与DI <BR>　首先想说说IoC（Inversion of Control，控制倒转）。这是spring的核心，贯穿始终。所谓IoC，对于spring框架来说，就是由spring来负责控制对象的生命周期和对象间的关系。这是什么意思呢，举个简单的例子，我们是如何找女朋友的？常见的情况是，我们到处去看哪里有长得漂亮身材又好的mm，然后打听她们的兴趣爱好、qq号、电话号、ip号、iq号………，想办法认识她们，投其所好送其所要，然后嘿嘿……这个过程是复杂深奥的，我们必须自己设计和面对每个环节。传统的程序开发也是如此，在一个对象中，如果要使用另外的对象，就必须得到它（自己new一个，或者从JNDI中查询一个），使用完之后还要将对象销毁（比如Connection等），对象始终会和其他的接口或类藕合起来。<BR>　那么IoC是如何做的呢？有点像通过婚介找女朋友，在我和女朋友之间引入了一个第三者：婚姻介绍所。婚介管理了很多男男女女的资料，我可以向婚介提出一个列表，告诉它我想找个什么样的女朋友，比如长得像李嘉欣，身材像林熙雷，唱歌像周杰伦，速度像卡洛斯，技术像齐达内之类的，然后婚介就会按照我们的要求，提供一个mm，我们只需要去和她谈恋爱、结婚就行了。简单明了，如果婚介给我们的人选不符合要求，我们就会抛出异常。整个过程不再由我自己控制，而是有婚介这样一个类似容器的机构来控制。Spring所倡导的开发方式就是如此，所有的类都会在spring容器中登记，告诉spring你是个什么东西，你需要什么东西，然后spring会在系统运行到适当的时候，把你要的东西主动给你，同时也把你交给其他需要你的东西。所有的类的创建、销毁都由spring来控制，也就是说控制对象生存周期的不再是引用它的对象，而是spring。对于某个具体的对象而言，以前是它控制其他对象，现在是所有对象都被spring控制，所以这叫控制反转。如果你还不明白的话，我决定放弃。<BR>　IoC的一个重点是在系统运行中，动态的向某个对象提供它所需要的其他对象。这一点是通过DI（Dependency Injection，依赖注入）来实现的。比如对象A需要操作数据库，以前我们总是要在A中自己编写代码来获得一个Connection对象，有了spring我们就只需要告诉spring，A中需要一个Connection，至于这个Connection怎么构造，何时构造，A不需要知道。在系统运行时，spring会在适当的时候制造一个Connection，然后像打针一样，注射到A当中，这样就完成了对各个对象之间关系的控制。A需要依赖Connection才能正常运行，而这个Connection是由spring注入到A中的，依赖注入的名字就这么来的。那么DI是如何实现的呢？Java 1.3之后一个重要特征是反射（reflection），它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性，spring就是通过反射来实现注入的。关于反射的相关资料请查阅java doc。<BR>　理解了IoC和DI的概念后，一切都将变得简单明了，剩下的工作只是在spring的框架中堆积木而已。<BR>二、spring管理对象的简单例子 <BR>　任何需要交给spring管理的对象，都必须在配置文件中注册，这个过程被称为wiring，下面做一个最简单的Hello world演示，我们将要注册的类如下：<BR>/* <BR>* 创建日期 2005-3-22 <BR>*/ <BR>package org.bromon.spring.test; <BR>/** <BR>* @author Bromon <BR>*/ <BR>public class HelloTalker <BR>{ <BR>public String greeting() <BR>{ <BR>return "hello world"; <BR>} <BR>} <BR>　然后我们来编写一个spring配置文件，文件名任意，在我这里它是springConfig.xml，需要注意的是这个文件应该存放在classpath所包含的路径中：<BR>&lt;?xml version="1.0" encoding="UTF-8"?&gt; <BR>&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "<A href="http://www.springframework.org/dtd/spring-beans.dtd">http://www.springframework.org/dtd/spring-beans.dtd</A>"&gt; <BR>&lt;beans&gt; <BR>　&lt;bean id=”helloTalker” class=” org.bromon.spring.test.HelloTalker”&gt; <BR>　&lt;/bean&gt; <BR>&lt;/beans&gt; <BR>　通过使用bean标签，注册了一个HelloTalker对象，它的名字叫做helloTalker。然后我们编写一个测试类，它的工作是利用spring框架提供的接口，加载配置文件，通过指定对象的id，获得一个对象。它的代码如下：<BR>/* <BR>* 创建日期 2005-3-17 <BR>*/ <BR>package org.bromon.spring.test.junit; <BR>import java.io.FileInputStream; <BR>import org.springframework.beans.factory.xml.XmlBeanFactory; <BR>import org.springframework.context.ApplicationContext; <BR>import org.springframework.context.support.ClassPathXmlApplicationContext; <BR>import org.bromon.spring.test; <BR>/** <BR>* @author Bromon <BR>*/ <BR>public class TestStudentManager extends TestCase { <BR>public void testHelloTalker() <BR>{ <BR>try <BR>{ <BR>ApplicationContext context =new ClassPathXmlApplicationContext("springConfig.xml"); </P>
<P>HelloTalker ht=(HelloTalker)context.getBean(“helloTalker”); <BR>System.out.println(ht.greeting()); <BR>}catch(Exception e) <BR>{ <BR>e.printStackTrace(); <BR>} <BR>} <BR>} <BR>　这个程序就完成了，因为只有一个对象HelloTalker被注册到了spring中，所以不存在对象间的依赖，当然也就不涉及依赖注入。下面演示一个简单的依赖注入：<BR>　第一步是修改HelloTalker，增加一个String name属性：<BR>public String name; </P>
<P>　为该属性编写set方法，该方法必须严格遵守javabean的命名规则：<BR>public void setName(String name) <BR>{ <BR>　　this.name=name; <BR>} <BR>　　修改greeting方法：</P>
<P>public String greeting() <BR>{ <BR>　　return "hello "+name; <BR>} <BR>　如你所见，name属性没有初试化，因为它的值将在运行过程中被spring动态注射入。<BR>　第二步，修改springConfig.xml中唯一的这个bean配置：</P>
<P>&lt;bean id=”helloTalker” class=” org.bromon.spring.test.HelloTalker”&gt; <BR>　&lt;property name=”name”&gt; <BR>　　&lt;value&gt;bromon&lt;/value&gt; <BR>　&lt;/property&gt; <BR>&lt;/bean&gt; </P>
<P>　修改完成。我们将一个名字”bromon”写死在springConfig.xml中，它会被动态的注入到HelloTalker的name属性中，greeting方法将会把它打印出来。重新运行刚才的junit类，可以看到结果。<BR>　我们只演示了如何注入一个最简单的String，实际上我们可以注入任何值类型，也可以注入任何类的实例，也可以注入List、Map、Properties。配置文件管理了所有的对象和对象间的关系，而对象则只负责执行自己的功能，他们的职责越少，藕合度越低，系统就越容易测试，管理维护也更容易。<BR>　&lt;bean&gt;标签还有很多属性，用于指定对象如何被实例化，它也有很多子标签用于配置对象的属性，请大家参考相关的DTD和文档，能够很快的掌握。本系列文章不是spring手册，spring的基础知识请参考spring in action，足够详细准确。后面的章节更多的讨论系统设计、开发的一些细节和高级特性。<BR>三、spring中的hibernate开发 <BR>　spring中对hibernate的支持是非常强大的，从一个简单的例子就看得出来，从这个例子中我们还将对所谓的轻量级容器做一些讨论。<BR>　首先需要配置数据源，通常我们有两种方式获得Connection，一是自己编写代码获得连接，二是从JNDI环境中得到DataSource，然后产生一个Connection。无论怎样，既然是spring下面的对象，就应该注册到配置文件中。假设我们需要一个连接mysql下面一个叫做examer的数据库，手动方式的配置是：</P>
<P>&lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt; <BR>　　&lt;property name="driverClassName"&gt; <BR>　　　　&lt;value&gt;com.mysql.jdbc.Driver&lt;/value&gt; <BR>　　&lt;/property&gt; <BR>　　&lt;property name="url"&gt; <BR>　　　　&lt;value&gt;jdbc:mysql://localhost/examer&lt;/value&gt; <BR>　　&lt;/property&gt; <BR>　　&lt;property name="username"&gt; <BR>　　　　&lt;value&gt;root&lt;/value&gt; <BR>　　&lt;/property&gt; <BR>　　&lt;property name="password"&gt; <BR>　　　　&lt;value&gt;&lt;/value&gt; <BR>　　&lt;/property&gt; <BR>&lt;/bean&gt; </P>
<P>　很好读是不是？假如我们使用JNDI数据源，那么dataSource的声明就应该是：</P>
<P>&lt;bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"&gt; <BR>　　&lt;property name="jndiName"&gt; <BR>　　　　&lt;value&gt;java:compenvjdbcspringExamer&lt;/value&gt; <BR>　　&lt;/property&gt; <BR>&lt;/bean&gt; <BR>　你需要在JNDI环境中绑定一个名为jdbc/springExamer的东西，这段代码才有实际意义。另外需要提醒的是，所有的bean声明，它的id必须是唯一的。<BR>　在本系统中，数据库操作是被hibernate封装起来的，所以dataSource是不需要注入到具体的逻辑类中，它只会被注给hibernate的sessionFactory。<BR>　按照常规思路，我们需要在spring中注册hibernate的sessionFactory，它应该是我们自己编写的一个类，获得dataSource，返回sessionFactory，其他的逻辑类通过这个sessionFactory获得session进行数据库操作。<BR>　但是我们有另外一种选择，spring直接提供了对sessionFactory的封装，你只需要注册一个spring自己的类，给它提供必须的属性，它会返回一个org.springframework.orm.hibernate.HibernateTemplate，这个类封装了add、del等操作，它的封装程度相当高，通过它来编写hibernate应用非常简单。但是问题出来了，我们该如何选择？<BR>　表面上看，使用spring自己的库无疑更加简单，但是请注意，spring是一个轻量级的框架，所谓轻量级，一个重要特征就是无侵入性，也就是你使用这套框架，不会被它绑定，被spring管理的类，应该不需要使用它的接口和抽象类，这样你的系统不会对spring产生依赖。但是如果你使用了spring封装的方式去操作hibernate，就必须继承org.springframework.orm.hibernate.support.HibernateDaoSupport类，这导致了绑定。所以做这样的选择是有点痛苦的，如果有一天spring框架不存在了，你的代码怎么升级维护？具体问题只能具体分析，在我们的应用中，完全使用了spring封装的HibernateTemplate，它太好用了，所以容易上瘾。<BR>　假设我们有一张student表，结构很简单：<BR>　　<BR>id　　　　　　自动增长 <BR>　　name　　　　　varchar(40) <BR>　　password　　　varchar(32) <BR>　　grade 　　　　int(4)　　　　　　年级 <BR>　　sex　　　　　Boolean　　　　　　性别(true为男，false为女) <BR>　设计一个Student类来映射这张表：</P>
<P>/* <BR>* 创建日期 2005-3-17 <BR>*/ <BR>package net.bromon.spring.examer.pojo; <BR>/** <BR>* @author Bromon <BR>*/ <BR>public class Student <BR>{ <BR>private int id; <BR>private String name; <BR>private String password; <BR>private int grade;//年级 <BR>private boolean sex; </P>
<P>getset方法………. <BR>} <BR>　编写Student.hbm.xml，让hibernate知道如何去关联student表和Student类，该文件和Student.java在同一目录：</P>
<P>&lt;hibernate-mapping&gt; <BR>　　&lt;class name="net.bromon.spring.examer.pojo.Student" table="student"&gt; <BR>　　　　&lt;id name="id" column="id"&gt; <BR>　　　　　　&lt;generator class="identity"/&gt; <BR>　　　　&lt;/id&gt; </P>
<P>　　　　&lt;property name="name" column="name" /&gt; <BR>　　　　&lt;property name="password" column="password" /&gt; <BR>　　　　&lt;property name="grade" column="grade" /&gt; <BR>　　　　&lt;property name="sex" column="sex" /&gt; <BR>　　&lt;/class&gt; <BR>&lt;/hibernate-mapping&gt; <BR>　然后我们可以在spring中配置sessionFactory：</P>
<P>&lt;bean id="sessionFactory"　class="org.springframework.orm.hibernate.LocalSessionFactoryBean"&gt; <BR>　　&lt;property name="dataSource"&gt; <BR>　　　　&lt;ref bean="dataSource"/&gt; <BR>　　&lt;/property&gt; </P>
<P>　　&lt;property name="hibernateProperties"&gt; <BR>　　　　&lt;props&gt; <BR>　　　　　　&lt;prop key="hibernate.dialect"&gt;net.sf.hibernate.dialect.MySQLDialect&lt;/prop&gt; <BR>　　　　&lt;/props&gt; <BR>　　&lt;/property&gt; </P>
<P>　　&lt;property name="mappingDirectoryLocations"&gt; <BR>　　　　&lt;list&gt; <BR>　　　　　　&lt;value&gt;classpath:/netbromonspringexamerpojo&lt;/value&gt; <BR>　　　　&lt;/list&gt; <BR>　　&lt;/property&gt; <BR>&lt;/bean&gt; <BR>　其中引用了我们之前注册过的dataSource，mappingDirectoryLocations属性指明了.hbm.xml文件在哪里路径，该文件夹下面的.hbm.xml文件会被全部加载。<BR>　一切都准备就绪，现在我们要加入一个StudentManager类，来进行增删查改的操作：<BR>/* <BR>* 创建日期 2005-3-17 <BR>*/ <BR>package net.bromon.spring.examer.student; <BR>import net.bromon.spring.examer.pojo.Student; <BR>import org.springframework.orm.hibernate.HibernateTemplate; <BR>import org.springframework.orm.hibernate.LocalSessionFactoryBean; <BR>import org.springframework.orm.hibernate.support.HibernateDaoSupport; <BR>/** <BR>* @author Bromon <BR>*/ <BR>public class StudentManager extends HibernateDaoSupport <BR>{ <BR>private LocalSessionFactoryBean sessionFactory; <BR>private HibernateTemplate ht; <BR>public StudentManager() <BR>{ <BR>this.ht=super.getHibernateTemplate(); <BR>} </P>
<P>public void add(Student s) <BR>{ <BR>ht.save(s);//插入一条数据只需要这一行代码 <BR>} <BR>} <BR>　该类只演示了如何增加一个Student，HibernateTemplate还封装了很多有用的方法，请查阅spring文档。StudentManager中的sessionFactory是由spring注入的，但是StudentManager并没有对sessionFactory做任何的处理，这是因为所有的处理都被HibernateDaoSupport.getHibernateTemplate()封装。整个StudentManager中也看不到任何的异常处理，他们也都被基类封装了。<BR>　最后一个步骤就是在spring中注册StudentManger，然后向它注入sessionFactory：</P>
<P>&lt;bean id="studentManager" class="net.bromon.spring.examer.student.StudentManager"&gt; <BR>　　&lt;property name="sessionFactory"&gt; <BR>　　　　&lt;ref bean="sessionFactory"/&gt; <BR>　　&lt;/property&gt; <BR>&lt;/bean&gt; </P>
<P>　所有的配置都完成了，下面做单元测试：</P>
<P>/* <BR>* 创建日期 2005-3-17 <BR>*/ <BR>package net.bromon.spring.examer.student.test; <BR>import java.io.FileInputStream; <BR>import org.springframework.beans.factory.xml.XmlBeanFactory; <BR>import org.springframework.context.ApplicationContext; <BR>import org.springframework.context.support.ClassPathXmlApplicationContext; <BR>import net.bromon.spring.examer.pojo.Student; <BR>import net.bromon.spring.examer.student.StudentManager; <BR>import junit.framework.TestCase; <BR>/** <BR>* @author Bromon <BR>*/ <BR>public class TestStudentManager extends TestCase { <BR>public void testAdd() <BR>{ <BR>try <BR>{ <BR>ApplicationContext context =new ClassPathXmlApplicationContext("springConfig.xml"); </P>
<P>Student s=new Student(); <BR>s.setName("bromon"); <BR>s.setPassword("123"); <BR>s.setGrade(3); <BR>s.setSex(true); </P>
<P>((StudentManager)context.getBean("studentManager")).add(s); <BR>}catch(Exception e) <BR>{ <BR>e.printStackTrace(); <BR>} <BR>} <BR>} <BR>　Spring已经将hibernate的操作简化到了非常高的程度，最关键的是整个开发可以由设计来驱动，如果一个团队对spring有足够的熟悉，那么完全可以由设计师规划所有的类，整理清楚类之间的关系，写成配置文件，然后编写hibernate映射文件，将数据表与pojo关联，成员就可以完全在设计方案内工作，利用spring封装好的hibernate模版，开发起来速度非常快，调试也很容易。它能够解决如何在团队内贯彻设计方案的问题。<BR>　由于本文不讲解hibernate的使用，所以相关内容请查阅hibernate文档。<BR>四、Spring中的事务控制 <BR>　Spring和EJB一样，提供了两种事务管理方式：编程式和声明式。在考试系统中我们将使用声明式的事务管理，这是spring推荐的做法。使用这种方式可以体验到spring的强大便捷，而且我们无须在Dao类中编写任何特殊的代码，只需要通过配置文件就可以让普通的java类加载到事务管理中，这个意义是很重大的。<BR>　Spring中进行事务管理的通常方式是利用AOP（面向切片编程）的方式，为普通java类封装事务控制，它是通过动态代理实现的，由于接口是延迟实例化的，spring在这段时间内通过拦截器，加载事务切片。原理就是这样，具体细节请参考jdk中有关动态代理的文档。本文主要讲解如何在spring中进行事务控制。<BR>　动态代理的一个重要特征是，它是针对接口的，所以我们的dao要通过动态代理来让spring接管事务，就必须在dao前面抽象出一个接口，当然如果没有这样的接口，那么spring会使用CGLIB来解决问题，但这不是spring推荐的方式，我们也不做讨论。<BR>　参照前面的例子，我们为StudentManager.java定义一个接口，它的内容如下：</P>
<P>/* <BR>* 创建日期 2005-3-25 <BR>*/ <BR>package org.bromon.spring.examer.student; <BR>import java.util.List; <BR>import org.bromon.spring.examer.pojo.Student; <BR>/** <BR>* @author Bromon <BR>*/ <BR>public interface StudentManagerInterface <BR>{ <BR>public void add(Student s); <BR>public void del(Student s); <BR>public void update(Student s); </P>
<P>public List loadAll(); <BR>public Student loadById(int id); <BR>} </P>
<P>　StudentManager也应该做出修改，实现该接口：</P>
<P>public class StudentManager extends HibernateDaoSupport implements StudentManagerInterface <BR>　现在需要修改配置文件，用于定义Hibrenate适用的事务管理器，并且把sessionFactory注入进去，同时还需要通过注册一个DefaultTransactionAttribute对象，来指出事务策略。其中sessionFactory的定义已经在本文的第三章中说明。<BR>　首先定义一个Hibernate的事务管理器，让它来管理sessionFactory：<BR>&lt;bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager"&gt; <BR>　&lt;property name="sessionFactory"&gt; <BR>　　&lt;ref bean="sessionFactory"/&gt; <BR>　&lt;/property&gt; <BR>&lt;/bean&gt; </P>
<P>　下面定义事务管理策略，我们希望把策略定义在方法这个级别上，提供最大的灵活性，本例中将add方法定义为：PROPAGATION_REQUIRES_NEW，这可以保证它将始终运行在一个事务中。</P>
<P>&lt;bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource"&gt; <BR>　&lt;property name="properties"&gt; <BR>　　&lt;props&gt; <BR>　　　&lt;prop key="add"&gt; <BR>　　　　PROPAGATION_REQUIRES_NEW <BR>　　　&lt;/prop&gt; <BR>　　&lt;/props&gt; <BR>　&lt;/property&gt; <BR>&lt;/bean&gt; </P>
<P>　我们不仅可以为add方法定义事务策略,还可以定义事务隔离程度和回滚策略,他们以逗号隔开,比如我们的add事务可以定义为:</P>
<P>&lt;prop key="add"&gt; <BR>PROPAGATION_REQUIRES_NEW,-ExamerException <BR>&lt;/prop&gt; </P>
<P>　这个事务策略表示add方法将会独占一个事务，当事务过程中产生ExamerException异常，事务会回滚。<BR>　Add/update/del都是写入方法，对于select（读取）方法，我们可以指定较为复杂的事务策略，比如对于loadAll()方法：<BR>　<BR>&lt;prop key=”loadAll”&gt; <BR>　PROPAGATION_SUPPORTS,ISOLATION_READ_COMMITED,readOnly <BR>　&lt;/prop&gt; </P>
<P>　该事务的含义为，loadAll方法支持事务，不会读取未提交的数据，它的数据为只读（可提高执行速度）。<BR>　如你所见，我们的StudentManagerInterface接口中还有一个loadById(int id)方法，也许我们将来还会有很多的loadByXXXX的方法，难道要一一为他们指定事务策略？太烦人了，他们应该和loadAll()一样，所以我们可以使用通配符，定义所有的loadXXXX方法：</P>
<P>&lt;prop key=”load*”&gt; <BR>PROPAGATION_SUPPORTS,ISOLATION_READ_COMMITED,readOnly <BR>&lt;/prop&gt; </P>
<P>　现在可以定义事务管理器：<BR>&lt;bean id="studentManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt; <BR>　&lt;property name="target"&gt; <BR>　　&lt;ref bean="studentManager"/&gt; <BR>　&lt;/property&gt; <BR>　&lt;property name="transactionManager"&gt; <BR>　　&lt;ref bean="transactionManager"/&gt; <BR>　&lt;/property&gt; <BR>　&lt;property name="transactionAttributeSource"&gt; <BR>　　&lt;ref bean="transactionAttributeSource"/&gt; <BR>　&lt;/property&gt; <BR>&lt;/bean&gt; <BR>　这个bean的外观是一个接口(StudentManagerInterface)，我们指出了它的具体实现(studentManager)，而且为它绑定了事务策略。在客户端使用的时候，获得对象是StudentManagerInterface，所有的操作都是针对这个接口的。测试代码并没有改变，我们虽然修改了很多地方，加入了事务控制，但是客户端并没有受到影响，这也体现了spring的一些优势。测试代码如下：<BR>　　<BR>public void testAdd() <BR>{ <BR>ApplicationContext ctx=new ClassPathXmlApplicationContext("springConfig.xml"); <BR>StudentManager sm=(StudentManager)ctx.getBean("studentManager"); </P>
<P>Student s=new Student(); <BR>s.setId(1); <BR>s.setName("bromon"); <BR>s.setPassword("123"); <BR>s.setGrade(1); <BR>s.setSex(0); </P>
<P>sm.add(s); <BR>} <BR>通过以上的代码可以看出，spring可以简单的把普通的java class纳入事务管理，声明性的事务操作起来也很容易。有了spring之后，声明性事务不再是EJB独有，我们不必为了获得声明性事务的功能而去忍受EJB带来的种种不便。<BR>我所使用的mysql是不支持事务的，你可以更换使用PostgreSQL，有了spring+hibernate，更换db并不像以前那样恐怖了，步骤很简单：<BR>1、 添加PostgreSQL的jdbc驱动<BR>2、 修改dataSource配置，包括驱动名称、url、帐号、密码<BR>3、 修改sessionFactory的数据库dailet为net.sf.hibernate.dialect.PostgreSQLDialect<BR>4、 修改hbm.xml中的主键生成策略为increment<BR>所有的修改都在配置文件中完成，业务代码不需要任何修改，我很满意，How about u?<BR>附A　　pring中的所有事务策略<BR>　　　　PROPAGATION_MANDATORY<BR>　　　　PROPAGATION_NESTED <BR>　　　　PROPAGATION_NEVER <BR>　　　　PROPAGATION_NOT_SUPPORTED<BR>　　　　PROPAGATION_REQUIRED<BR>　　　　PROPAGATION_REQUIRED_NEW<BR>　　　　PROPAGATION_SUPPORTS<BR>附B　　Spring中所有的隔离策略：<BR>　　　　ISOLATION_DEFAULT<BR>　　　ISOLATION_READ_UNCOMMITED<BR>　　　　ISOLATION_COMMITED<BR>　　　　ISOLATION_REPEATABLE_READ<BR>　　　　ISOLATION_SERIALIZABLE</P><img src ="http://www.blogjava.net/happydavy/aggbug/11043.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/happydavy/" target="_blank"> 我的java天地</a> 2005-08-25 13:52 <a href="http://www.blogjava.net/happydavy/archive/2005/08/25/11043.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>