﻿<?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-Jelver'Sky-文章分类-Spring</title><link>http://www.blogjava.net/jelver/category/7672.html</link><description>“一直很多人说我是天才，但我却相信这个世界没有天才。如果没有卓越的努力和娴熟的球性，你永远不会踢出精彩的足球。我从3岁开始踢球，7岁进入格雷米奥少年队开始接受系统训练，至今为止已经踢了20年的球。如果你认为这纯粹是天才，那为什么我14岁时没有现在这种天才呢？我从来不会低估努力的重要性，而这正是我对自己的要求。”
---------罗纳尔迪尼奥(Ronaldinho)</description><language>zh-cn</language><lastBuildDate>Sun, 01 Apr 2007 09:08:04 GMT</lastBuildDate><pubDate>Sun, 01 Apr 2007 09:08:04 GMT</pubDate><ttl>60</ttl><item><title>Spring中WebApplicationContext的研究 </title><link>http://www.blogjava.net/jelver/articles/107770.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Sun, 01 Apr 2007 08:28:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/107770.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/107770.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/107770.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/107770.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/107770.html</trackback:ping><description><![CDATA[
		<div style="MARGIN-TOP: 1px; MARGIN-LEFT: 15px">
				<h2>
						<a title="永久链接：[转]Spring中WebApplicationContext的研究" href="http://wiley.javaeye.com/blog/30976">[转]Spring中WebApplicationContext的研究</a>
				</h2>
		</div>
		<div style="MARGIN-TOP: 5px; MARGIN-LEFT: 15px">
				<b>关键字:</b>   spring     </div>
		<div style="MARGIN-TOP: 10px; MARGIN-LEFT: 15px; OVERFLOW: auto">
				<table width="100%">
						<tbody>
								<tr>
										<td>
												<p>作者:laoer 引自:http://bbscs.laoer.com/read.bbscs?bid=5&amp;id=14419</p>
												<p>全文如下: <br />ApplicationContext是Spring的核心，Context我们通常解释为上下文环境，我想用“容器”来表述它更容易理解一些，ApplicationContext则是“应用的容器”了:P，Spring把Bean放在这个容器中，在需要的时候，用getBean方法取出，虽然我没有看过这一部分的源代码，但我想它应该是一个类似Map的结构。 <br />在Web应用中，我们会用到WebApplicationContext，WebApplicationContext继承自ApplicationContext，先让我们看看在Web应用中，怎么初始化WebApplicationContext，在web.xml中定义: <br /></p>
												<div class="code_title">代码</div>
												<div class="code_div">
														<div class="dp-highlighter">
																<div class="bar">
																</div>
																<ol class="dp-xml">
																		<li class="alt">
																				<span>
																						<span class="tag">&lt;</span>
																						<span class="tag-name">context-param</span>
																						<span class="tag">&gt;</span>
																						<span>    </span>
																				</span>
																		</li>
																		<li class="">
																				<span>
																				</span>
																				<span class="tag">&lt;</span>
																				<span class="tag-name">param-name</span>
																				<span class="tag">&gt;</span>
																				<span>contextConfigLocation</span>
																				<span class="tag">&lt;/</span>
																				<span class="tag-name">param-name</span>
																				<span class="tag">&gt;</span>
																				<span>    </span>
																		</li>
																		<li class="alt">
																				<span>
																				</span>
																				<span class="tag">&lt;</span>
																				<span class="tag-name">param-value</span>
																				<span class="tag">&gt;</span>
																				<span>/WEB-INF/applicationContext.xml</span>
																				<span class="tag">&lt;/</span>
																				<span class="tag-name">param-value</span>
																				<span class="tag">&gt;</span>
																				<span>    </span>
																		</li>
																		<li class="">
																				<span>
																				</span>
																				<span class="tag">&lt;/</span>
																				<span class="tag-name">context-param</span>
																				<span class="tag">&gt;</span>
																				<span>    </span>
																		</li>
																		<li class="alt">
																				<span>  </span>
																		</li>
																		<li class="">
																				<span>
																				</span>
																				<span class="tag">&lt;</span>
																				<span class="tag-name">listener</span>
																				<span class="tag">&gt;</span>
																				<span>    </span>
																		</li>
																		<li class="alt">
																				<span>
																				</span>
																				<span class="tag">&lt;</span>
																				<span class="tag-name">listener-class</span>
																				<span class="tag">&gt;</span>
																				<span>org.springframework.web.context.ContextLoaderListener</span>
																				<span class="tag">&lt;/</span>
																				<span class="tag-name">listener-class</span>
																				<span class="tag">&gt;</span>
																				<span>    </span>
																		</li>
																		<li class="">
																				<span>
																				</span>
																				<span class="tag">&lt;/</span>
																				<span class="tag-name">listener</span>
																				<span class="tag">&gt;</span>
																				<span>    </span>
																		</li>
																		<li class="alt">
																				<span>  </span>
																		</li>
																		<li class="">
																				<span>&lt;!-- OR USE THE CONTEXTLOADERSERVLET INSTEAD OF THE LISTENER    </span>
																		</li>
																		<li class="alt">
																				<span>
																				</span>
																				<span class="tag">&lt;</span>
																				<span class="tag-name">servlet</span>
																				<span class="tag">&gt;</span>
																				<span>    </span>
																		</li>
																		<li class="">
																				<span>
																				</span>
																				<span class="tag">&lt;</span>
																				<span class="tag-name">servlet-name</span>
																				<span class="tag">&gt;</span>
																				<span>context</span>
																				<span class="tag">&lt;/</span>
																				<span class="tag-name">servlet-name</span>
																				<span class="tag">&gt;</span>
																				<span>    </span>
																		</li>
																		<li class="alt">
																				<span>
																				</span>
																				<span class="tag">&lt;</span>
																				<span class="tag-name">servlet-class</span>
																				<span class="tag">&gt;</span>
																				<span>org.springframework.web.context.ContextLoaderServlet</span>
																				<span class="tag">&lt;/</span>
																				<span class="tag-name">servlet-class</span>
																				<span class="tag">&gt;</span>
																				<span>    </span>
																		</li>
																		<li class="">
																				<span>
																				</span>
																				<span class="tag">&lt;</span>
																				<span class="tag-name">load-on-startup</span>
																				<span class="tag">&gt;</span>
																				<span>1</span>
																				<span class="tag">&lt;/</span>
																				<span class="tag-name">load-on-startup</span>
																				<span class="tag">&gt;</span>
																				<span>    </span>
																		</li>
																		<li class="alt">
																				<span>
																				</span>
																				<span class="tag">&lt;/</span>
																				<span class="tag-name">servlet</span>
																				<span class="tag">&gt;</span>
																				<span>    </span>
																		</li>
																		<li class="">
																				<span>--</span>
																				<span class="tag">&gt;</span>
																				<span>   </span>
																		</li>
																</ol>
														</div>
												</div>
												<script><![CDATA[ender_code();]]&gt;</script>
												<p>
												</p>
												<p>可以看出，有两种方法，一个是用ContextLoaderListener这个Listerner，另一个是ContextLoaderServlet这个Servlet，这两个方法都是在web应用启动的时候来初始化WebApplicationContext，我个人认为Listerner要比Servlet更好一些，因为Listerner监听应用的启动和结束，而Servlet得启动要稍微延迟一些，如果在这时要做一些业务的操作，启动的前后顺序是有影响的。 </p>
												<p>那么在ContextLoaderListener和ContextLoaderServlet中到底做了什么呢？ <br />以ContextLoaderListener为例，我们可以看到 <br /></p>
												<div class="code_title">代码</div>
												<div class="code_div">
														<div class="dp-highlighter">
																<div class="bar">
																</div>
																<ol class="dp-j">
																		<li class="alt">
																				<span>
																						<span class="keyword">public</span>
																						<span> </span>
																						<span class="keyword">void</span>
																						<span> contextInitialized(ServletContextEvent event) {    </span>
																				</span>
																		</li>
																		<li class="">
																				<span>
																				</span>
																				<span class="keyword">this</span>
																				<span>.contextLoader = createContextLoader();    </span>
																		</li>
																		<li class="alt">
																				<span>
																				</span>
																				<span class="keyword">this</span>
																				<span>.contextLoader.initWebApplicationContext(event.getServletContext());    </span>
																		</li>
																		<li class="">
																				<span>}    </span>
																		</li>
																		<li class="alt">
																				<span>
																				</span>
																				<span class="keyword">protected</span>
																				<span> ContextLoader createContextLoader() {    </span>
																		</li>
																		<li class="">
																				<span>
																				</span>
																				<span class="keyword">return</span>
																				<span> </span>
																				<span class="keyword">new</span>
																				<span> ContextLoader();    </span>
																		</li>
																		<li class="alt">
																				<span>}   </span>
																		</li>
																</ol>
														</div>
												</div>
												<script><![CDATA[ender_code();]]&gt;</script>
												<br />ContextLoader是一个工具类，用来初始化WebApplicationContext，其主要方法就是initWebApplicationContext，我们继续追踪initWebApplicationContext这个方法（具体代码我不贴出，大家可以看Spring中的源码），我们发现，原来ContextLoader是把WebApplicationContext（XmlWebApplicationContext是默认实现类）放在了ServletContext中，ServletContext也是一个“容器”，也是一个类似Map的结构，而WebApplicationContext在ServletContext中的KEY就是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE，我们如果要使用WebApplicationContext则需要从ServletContext取出，Spring提供了一个WebApplicationContextUtils类，可以方便的取出WebApplicationContext，只要把ServletContext传入就可以了。 
<p></p><p>上面我们介绍了WebApplicationContext在Servlet容器中初始化的原理，一般的Web应用就可以轻松的使用了，但是，随着Struts的广泛应用，把Struts和Spring整个起来，是一个需要面对的问题，Spring本身也提供了Struts的相关类，主要使用的有org.springframework.web.struts.ActionSupport，我们只要把自己的Action继承自ActionSupport，就是可以调用ActionSupport中getWebApplicationContext()的方法取出WebApplicationContext，但这样一来在Action中，需要取得业务逻辑的地方都要getBean，看上去不够简洁，所以Spring又提供了另一个方法，用org.springframework.web.struts.ContextLoaderPlugIn，这是一个Struts的Plug，在Struts启动时加载，对于Action，可以像管理Bean一样来管理，在struts-config.xml中Action的配置变成类似下面的样子 <br /></p><div class="code_title">代码</div><div class="code_div"><div class="dp-highlighter"><div class="bar"></div><ol class="dp-xml"><li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">action</span><span> </span><span class="attribute">attribute</span><span>=</span><span class="attribute-value">"aForm"</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"aForm"</span><span> </span><span class="attribute">path</span><span>=</span><span class="attribute-value">"/aAction"</span><span> </span><span class="attribute">scope</span><span>=</span><span class="attribute-value">"request"</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"org.springframework.web.struts.DelegatingActionProxy"</span><span class="tag">&gt;</span><span>    </span></span></li><li class=""><span></span><span class="tag">&lt;</span><span class="tag-name">forward</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"forward"</span><span> </span><span class="attribute">path</span><span>=</span><span class="attribute-value">"forward.jsp"</span><span> </span><span class="tag">/&gt;</span><span>    </span></li><li class="alt"><span></span><span class="tag">&lt;/</span><span class="tag-name">action</span><span class="tag">&gt;</span><span>   </span></li></ol></div></div><script><![CDATA[ender_code();]]&gt;</script>
注意type变成了org.springframework.web.struts.DelegatingActionProxy，之后我们需要建立action-servlet.xml这样的文件，action-servlet.xml符合Spring的spring-beans.dtd标准，在里面定义类似下面的 <br /><div class="code_title">代码</div><div class="code_div"><div class="dp-highlighter"><div class="bar"></div><ol class="dp-xml"><li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">bean</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"/aAction"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"com.web.action.Aaction"</span><span> </span><span class="attribute">singleton</span><span>=</span><span class="attribute-value">"false"</span><span class="tag">&gt;</span><span>    </span></span></li><li class=""><span></span><span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"businessService"</span><span class="tag">&gt;</span><span>    </span></li><li class="alt"><span></span><span class="tag">&lt;</span><span class="tag-name">ref</span><span> </span><span class="attribute">bean</span><span>=</span><span class="attribute-value">"businessService"</span><span class="tag">/&gt;</span><span>    </span></li><li class=""><span></span><span class="tag">&lt;/</span><span class="tag-name">property</span><span class="tag">&gt;</span><span>    </span></li><li class="alt"><span></span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>   </span></li></ol></div></div><script><![CDATA[ender_code();]]&gt;</script><p></p><p>com.web.action.Aaction是Action的实现类，businessService是需要的业务逻辑，Spring会把businessService注入到Action中，在Action中只要写businessService的get和set方法就可以了，还有一点，action的bean是singleton="false"，即每次新建一个实例，这也解决了Struts中Action的线程同步问题，具体过程是当用户做“/aAction”的HTTP请求（当然应该是“/aAction.do”），Struts会找到这个Action的对应类org.springframework.web.struts.DelegatingActionProxy，DelegatingActionProxy是个代理类，它会去找action-servlet.xml文件中“/aAction”对应的真正实现类，然后把它实例化，同时把需要的业务对象注入，然后执行Action的execute方法。 </p><p>使用了ContextLoaderPlugIn，在struts-config.xml中变成类似这样配置 <br /></p><div class="code_title">代码</div><div class="code_div"><div class="dp-highlighter"><div class="bar"></div><ol class="dp-xml"><li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">plug-in</span><span> </span><span class="attribute">className</span><span>=</span><span class="attribute-value">"org.springframework.web.struts.ContextLoaderPlugIn"</span><span class="tag">&gt;</span><span>    </span></span></li><li class=""><span></span><span class="tag">&lt;</span><span class="tag-name">set-property</span><span> </span><span class="attribute">property</span><span>=</span><span class="attribute-value">"contextConfigLocation"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"/WEB-INF/applicationContext.xml,/WEB-INF/action-servlet.xml"</span><span> </span><span class="tag">/&gt;</span><span>    </span></li><li class="alt"><span></span><span class="tag">&lt;/</span><span class="tag-name">plug-in</span><span class="tag">&gt;</span><span>   </span></li></ol></div></div><script><![CDATA[ender_code();]]&gt;</script>
而在web.xml中不再需要ContextLoaderListener或是ContextLoaderServlet。 
<p></p><p>说到这里不知道大家会不会有这样的问题，如果使用ContextLoaderPlugIn，如果我们有些程序是脱离Struts的Action环境，我们怎么处理，比如我们要自定义标记库，在标记库中，我们需要调用Spring管理的业务层逻辑对象，这时候我们就很麻烦，因为只有在action中动态注入业务逻辑，其他我们似乎不能取得Spring的WebApplicationContext。 </p><p>别急，我们还是来看一下ContextLoaderPlugIn的源码（源码不再贴出），我们可以发现，原来ContextLoaderPlugIn仍然是把WebApplicationContext放在ServletContext中，只是这个KEY不太一样了，这个KEY值为ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX+ModuleConfig.getPrefix()（具体请查看源代码），这下好了，我们知道了WebApplicationContext放在哪里，只要我们在Web应用中能够取到ServletContext也就能取到WebApplicationContext了:) </p><p>Spring是一个很强大的框架，希望大家在使用过程中不断的深入，了解其更多的特性，我在这里抛砖引玉，有什么不对的地方，请大家指出。 </p></td>
								</tr>
						</tbody>
				</table>
		</div>
<img src ="http://www.blogjava.net/jelver/aggbug/107770.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2007-04-01 16:28 <a href="http://www.blogjava.net/jelver/articles/107770.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>学习Spring常见问题（整理）</title><link>http://www.blogjava.net/jelver/articles/107761.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Sun, 01 Apr 2007 07:19:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/107761.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/107761.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/107761.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/107761.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/107761.html</trackback:ping><description><![CDATA[
		<table class="overflow">
				<tbody>
						<tr>
								<td valign="top" height="150">1、如何学习Spring？<br />你可以通过下列途径学习spring：<br />(1) spring下载包中doc目录下的MVC-step-by-step和sample目录下的例子都是比较好的spring开发的例子。<br /><br />(2) AppFuse集成了目前最流行的几个开源轻量级框架或者工具Ant,XDoclet,Spring,Hibernate(iBATIS),JUnit,Cactus,StrutsTestCase,Canoo's WebTest,Struts Menu,Display Tag Library,OSCache,JSTL,Struts 。<br />你可以通过AppFuse源代码来学习spring。<br />AppFuse网站：http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuse<br /><br />(3)Spring 开发指南(夏昕)（http://www.xiaxin.net/Spring_Dev_Guide.rar）<br />一本spring的入门书籍,里面介绍了反转控制和依赖注射的概念，以及spring的bean管理，spring的MVC，spring和hibernte，iBatis的结合。<br /><br />(4) spring学习的中文论坛<br />SpringFramework中文论坛(http://spring.jactiongroup.net)<br />Java视线论坛(http://forum.javaeye.com)的spring栏目<br /><br />2、利用Spring框架编程，console打印出log4j:WARN Please initialize the log4j system properly？<br />说明你的log4j.properties没有配置。请把log4j.properties放到工程的classpath中，eclipse的classpath为bin目录，由于编译后src目录下的文件会拷贝到bin目录下，所以你可以把log4j.properties放到src目录下。<br />这里给出一个log4j.properties的例子：<br /><br />log4j.rootLogger=DEBUG,stdout<br />log4j.appender.stdout=org.apache.log4j.ConsoleAppender<br />log4j.appender.stdout.layout=org.apache.log4j.PatternLayout<br />log4j.appender.stdout.layout.ConversionPattern=%d %5p (%F:%L) - %m%n<br /><br /><br />3、出现 java.lang.NoClassDefFoundError?<br />一般情况下是由于你没有把必要的jar包放到lib中。<br /><br />比如你要采用spring和hibernate（带事务支持的话），你除了spring.jar外还需要hibernat.jar、aopalliance.jar、cglig.jar、jakarta-commons下的几个jar包。<br /><br />http://www.springframework.org/download.html下载spring开发包，提供两种zip包<br />spring-framework-1.1.3-with-dependencies.zip和spring-framework-1.1.3.zip，我建议你下载spring-framework-1.1.3-with-dependencies.zip。这个zip解压缩后比后者多一个lib目录，其中有hibernate、j2ee、dom4j、aopalliance、jakarta-commons等常用包。<br /><br /><br />4、java.io.FileNotFoundException: Could not open class path resource [....hbm.xml],提示找不到xml文件？<br />原因一般有两个：<br />(1)该xml文件没有在classpath中。<br />(2)applicationContext-hibernate.xml中的xml名字没有带包名。比如：<br />&lt;bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"&gt;<br />        &lt;property name="dataSource"&gt;&lt;ref bean="dataSource"/&gt;&lt;/property&gt;<br />        &lt;property name="mappingResources"&gt;<br />            &lt;list&gt;<br />                &lt;value&gt;User.hbm.xml&lt;/value&gt;         错，改为： &lt;value&gt;com/yz/spring/domain/User.hbm.xml&lt;/value&gt;<br />            &lt;/list&gt;<br />        &lt;/property&gt;<br />        &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;prop key="hibernate.show_sql"&gt;true&lt;/prop&gt; <br />        &lt;/props&gt; <br />        &lt;/property&gt;<br />&lt;/bean&gt;<br /><br /><br />5、org.springframework.beans.NotWritablePropertyException: Invalid property 'postDao' of bean class？<br />出现异常的原因是在application-xxx.xml中property name的错误。<br />&lt;property name="...."&gt; 中name的名字是与bean的set方法相关的，而且要注意大小写。<br />比如<br />public class PostManageImpl extends BaseManage implements PostManage {<br />    private PostDAO dao = null;<br />    public void setPostDAO(PostDAO postDAO){<br />        this.dao = postDAO;<br />    }<br />}<br />那么xml的定义应该是：<br />&lt;bean id="postManage" parent="txProxyTemplate"&gt;<br />        &lt;property name="target"&gt;<br />            &lt;bean class="com.yz.spring.service.implement.PostManageImpl"&gt;<br />                &lt;property name="postDAO"&gt;&lt;ref bean="postDAO"/&gt;&lt;/property&gt;    对<br />                &lt;property name="dao"&gt;&lt;ref bean="postDAO"/&gt;&lt;/property&gt;             错<br />            &lt;/bean&gt;<br />        &lt;/property&gt;<br />&lt;/bean&gt;<br /><br /><br />6、Spring中如何实现事务管理？<br />        首先，如果使用mysql，确定mysql为InnoDB类型。<br />        事务管理的控制应该放到商业逻辑层。你可以写个处理商业逻辑的JavaBean，在该JavaBean中调用DAO，然后把该Bean的方法纳入spring的事务管理。<br /><br />比如：xml文件定义如下：<br />&lt;bean id="txProxyTemplate" abstract="true"<br />        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;<br />        &lt;property name="transactionManager"&gt;&lt;ref bean="transactionManager"/&gt;&lt;/property&gt;<br />        &lt;property name="transactionAttributes"&gt;<br />            &lt;props&gt;<br />                &lt;prop key="save*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;<br />                &lt;prop key="remove*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;<br />                &lt;prop key="*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;<br />            &lt;/props&gt;<br />        &lt;/property&gt;<br />&lt;/bean&gt;<br /><br />&lt;bean id="userManage" parent="txProxyTemplate"&gt;<br />      &lt;property name="target"&gt;<br />          &lt;bean class="com.yz.spring.service.implement.UserManageImpl"&gt;<br />              &lt;property name="userDAO"&gt;&lt;ref bean="userDAO"/&gt;&lt;/property&gt;<br />          &lt;/bean&gt;<br />      &lt;/property&gt;<br />&lt;/bean&gt;<br /><br />com.yz.spring.service.implement.UserManageImpl就是我们的实现商业逻辑的JavaBean。我们通过parent元素&lt;/span&gt; </td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />7、如何管理Spring框架下更多的JavaBean？<br /><br />　　JavaBean越多，spring配置文件就越大，这样不易维护。为了使配置清晰，我们可以将JavaBean分类管理，放在不同的配置文件中。 应用启动时将所有的xml同时加载。<br /><br />　　比如：<br /><br />　　DAO层的JavaBean放到applicationContext-hibernate.xml中，商业逻辑层的JavaBean放到applicationContext-service.xml中。然后启动类中调用以下代码载入所有的ApplicationContext。<br /><br />String[] paths = {"com/yz/spring/dao/hibernate/applicationContext-hibernate.xml",<br />"com/yz/spring/service/applicationContext-service.xml"};<br />ctx = new ClassPathXmlApplicationContext(paths); <br /><br />　　8、web应用中如何加载ApplicationContext？<br /><br />　　可以通过定义web.xml，由web容器自动加载。<br /><br />＜servlet＞<br />＜servlet-name＞context＜/servlet-name＞<br />＜servlet-class＞org.springframework.web.context.ContextLoaderServlet＜/servlet-class＞<br />＜load-on-startup＞1＜/load-on-startup＞<br />＜/servlet＞<br /><br />＜context-param＞<br />＜param-name＞contextConfigLocation＜/param-name＞<br />＜param-value＞/WEB-INF/applicationContext-hibernate.xml＜/param-value＞<br />＜param-value＞/WEB-INF/applicationContext-service.xml＜/param-value＞<br />＜/context-param＞ <br /><br />　　9、在spring中如何配置的log4j?<br /><br />　　在web.xml中加入以下代码即可。<br /><br />＜context-param＞<br />＜param-name＞log4jConfigLocation＜/param-name＞<br />＜param-value＞/WEB-INF/log4j.properties＜/param-value＞<br />＜/context-param＞ <br /><br />　　10、Spring框架入门的编程问题解决了，我该如何更深地领会Spring框架呢？<br /><br />　　这两本书你该去看看。这两本书是由Spring的作者Rod Johnson编写的。<br /><br />Expert One on one J2EE Design and Development<br />Expert One on one J2EE Development Without EJB <br /><br />　　你也该看看martinfowler的Inversion of Control Containers and the Dependency Injection pattern。<br /><br />http://www.martinfowler.com/articles/injection.html <br />　<br />　　再好好研读一下spring的文档。<br /><br />http://www.jactiongroup.net/reference/html/index.html（中文版，未全部翻译） <br /><br />　　还有就是多实践吧。<br /><img src ="http://www.blogjava.net/jelver/aggbug/107761.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2007-04-01 15:19 <a href="http://www.blogjava.net/jelver/articles/107761.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SPRING数据访问对象(DAO)框架入门</title><link>http://www.blogjava.net/jelver/articles/106616.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Tue, 27 Mar 2007 02:48:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/106616.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/106616.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/106616.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/106616.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/106616.html</trackback:ping><description><![CDATA[(转贴 地址不祥)<br />J2EE应用程序中的业务组件通常使用JDBC API访问和更改关系数据库中的持久数据。这经常导致持久性代码与业务逻辑发生混合，这是一种不好的习惯。数据访问对象（DAO）设计模式通过把持久性逻辑分成若干数据访问类来解决这一问题。 
<p>　　本文是一篇关于DAO设计模式的入门文章，突出讲述了它的优点和不足之处。另外，本文还介绍了Spring 2.0 JDBC/DAO框架并示范了它如何妥善地解决传统DAO设计中的缺陷。</p><p>　　<strong>传统的DAO设计</strong></p><p>　　数据访问对象（DAO）是一个集成层设计模式，如Core J2EE Design Pattern 图书所归纳。它将持久性存储访问和操作代码封装到一个单独的层中。本文的上下文中所提到的持久存储器是一个RDBMS.</p><p>　　这一模式在业务逻辑层和持久存储层之间引入了一个抽象层，如图1所示。业务对象通过数据访问对象来访问RDBMS（数据源）。抽象层改善了应用程序代码并引入了灵活性。理论上，当数据源改变时，比如更换数据库供应商或是数据库的类型时，仅需改变数据访问对象，从而把对业务对象的影响降到最低。</p><p align="center"><img alt="SPRING数据访问对象(DAO)框架入门图-1" src="http://java.chinaitlab.com/UploadFiles_8734/200703/20070310152441452.gif" /></p><p align="center">　　图1. 应用程序结构，包括DAO之前和之后的部分</p><p align="left">　　讲解了DAO设计模式的基础知识，下面将编写一些代码。下面的例子来自于一个公司域模型。简而言之，这家公司有几位员工工作在不同的部门，如销售部、市场部以及人力资源部。为了简单起见，我们将集中讨论一个称作“雇员”的实体。</p><p align="left">　　<strong>针对接口编程</strong></p><p align="left">　　DAO设计模式带来的灵活性首先要归功于一个对象设计的最佳实践：针对接口编程（P2I）。这一原则规定实体必须实现一个供调用程序而不是实体自身使用的接口。因此，可以轻松替换成不同的实现而对客户端代码只产生很小的影响。</p><p align="left">　　我们将据此使用findBySalaryRange（）行为定义Employee DAO接口，IEmployeeDAO.业务组件将通过这个接口与DAO交互：</p><p align="left"></p><table style="WIDTH: 80%; BORDER-TOP-STYLE: solid; BORDER-RIGHT-STYLE: solid; BORDER-LEFT-STYLE: solid; BORDER-BOTTOM-STYLE: solid" bordercolor="#ffffff" cellspacing="0" cellpadding="0" width="80%" align="center" bgcolor="#cccccc" border="0" heihgt=""><tbody><tr><td style="PADDING-LEFT: 5px"><p> import java.util.Map;<br />public interface IEmployeeDAO {<br />  //SQL String that will be executed<br />  public String FIND_BY_SAL_RNG = "SELECT EMP_NO, EMP_NAME, "<br />  + "SALARY FROM EMP WHERE SALARY &gt;= ? AND SALARY &lt;= ?";</p><p>  //Returns the list of employees who fall into the given salary <br />  //range. The input parameter is the immutable map object <br />  //obtained from the HttpServletRequest. This is an early <br />  //refactoring based on "Introduce Parameter Object"</p><p>  public List findBySalaryRange(Map salaryMap);<br />}<br /></p></td></tr></tbody></table><p align="left">　　<strong>提供DAO实现类</strong></p><p align="left">　　接口已经定义，现在必须提供Employee DAO的具体实现，EmployeeDAOImpl：</p><p align="left"></p><table style="WIDTH: 80%; BORDER-TOP-STYLE: solid; BORDER-RIGHT-STYLE: solid; BORDER-LEFT-STYLE: solid; BORDER-BOTTOM-STYLE: solid" bordercolor="#ffffff" cellspacing="0" cellpadding="0" width="80%" align="center" bgcolor="#cccccc" border="0" heihgt=""><tbody><tr><td style="PADDING-LEFT: 5px"><p> import java.sql.Connection;<br />import java.sql.PreparedStatement;<br />import java.sql.ResultSet;<br />import java.util.List;<br />import java.util.ArrayList;<br />import java.util.Map;<br />import com.bea.dev2dev.to.EmployeeTO;</p><p>public class EmployeeDAOImpl implements IEmployeeDAO{</p><p>  public List findBySalaryRange(Map salaryMap)<br />  {<br />    Connection conn = null;<br />    PreparedStatement pstmt = null;<br />    ResultSet rs = null;<br />    List empList = new ArrayList();<br />    //Transfer Object for inter-tier data transfer<br />    EmployeeTO tempEmpTO = null;<br />    try{<br />    //DBUtil - helper classes that retrieve connection from pool<br />      conn = DBUtil.getConnection();<br />      pstmt = conn.prepareStatement(FIND_BY_SAL_RNG);<br />      pstmt.setDouble(1, Double.valueOf( (String)<br />          salaryMap.get("MIN_SALARY") );<br />      pstmt.setDouble(2, Double.valueOf( (String)<br />          salaryMap.get("MIN_SALARY") );<br />      rs = pstmt.executeQuery();<br />      int tmpEmpNo = 0;<br />      String tmpEmpName = "";<br />      double tmpSalary = 0.0D;<br />      while (rs.next()){<br />        tmpEmpNo = rs.getInt("EMP_NO");<br />        tmpEmpName = rs.getString("EMP_NAME");<br />        tmpSalary = rs.getDouble("SALARY");<br />        tempEmpTO = new EmployeeTO(tmpEmpNo,<br />              tmpEmpName,<br />              tmpSalary);<br />        empList.add(tempEmpTO);<br />      }//end while<br />    }//end try<br />    catch (SQLException sqle){<br />      throw new DBException(sqle);<br />    }//end catch<br />    finally{<br />      try{<br />        if (rs != null){<br />          rs.close();<br />        }<br />      }<br />      catch (SQLException sqle){<br />        throw new DBException(sqle);<br />      }<br />      try{<br />        if (pstmt != null){<br />          pstmt.close();<br />        }<br />      }<br />      catch (SQLException sqle){<br />        throw new DBException(sqle);<br />      }<br />      try{<br />        if (conn != null){<br />          conn.close();<br />        }<br />      }<br />      catch (SQLException sqle){<br />        throw new DBException(sqle);<br />      }<br />    }//end of finally block<br />    return empList;<br />  }//end method findBySalaryRange<br />}<br /></p></td></tr></tbody></table><br />上面的清单说明了DAO方法的一些要点： 
<p>　　它们封装了所有与JDBC API的交互。如果使用像Kodo或者Hibernate的O/R映射方案，则DAO类可以将这些产品的私有API打包。</p><p>　　它们将检索到的数据打包到一个与JDBC API无关的传输对象中，然后将其返回给业务层作进一步处理。</p><p>　　它们实质上是无状态的。唯一的目的是访问并更改业务对象的持久数据。</p><p>　　在这个过程中，它们像SQLException一样捕获任何底层JDBC API或数据库报告的错误（例如，数据库不可用、错误的SQL句法）。DAO对象再次使用一个与JDBC无关的自定义运行时异常类DBException，通知业务对象这些错误。</p><p>　　它们像Connection和PreparedStatement对象那样，将数据库资源释放回池中，并在使用完ResultSet游标之后，将其所占用的内存释放。</p><p>　　因此，DAO层将底层的数据访问API抽象化，为业务层提供了一致的数据访问API.</p><p>　　<strong>构建DAO工厂</strong></p><p>　　DAO工厂是典型的工厂设计模式实现，用于为业务对象创建和提供具体的DAO实现。业务对象使用DAO接口，而不用了解实现类的具体情况。DAO工厂带来的依赖反转（dependency inversion）提供了极大的灵活性。只要DAO接口建立的约定未改变，那么很容易改变DAO实现（例如，从straight JDBC实现到基于Kodo的O/R映射），同时又不影响客户的业务对象：</p><p align="left"></p><table style="WIDTH: 80%; BORDER-TOP-STYLE: solid; BORDER-RIGHT-STYLE: solid; BORDER-LEFT-STYLE: solid; BORDER-BOTTOM-STYLE: solid" bordercolor="#ffffff" cellspacing="0" cellpadding="0" width="80%" align="center" bgcolor="#cccccc" border="0" heihgt=""><tbody><tr><td style="PADDING-LEFT: 5px"> public class DAOFactory {<br />  private static DAOFactory daoFac;<br /><br />  static{<br />    daoFac = new DAOFactory();<br />  }<br /><br />  private DAOFactory(){}<br /><br />  public DAOFactory getInstance(){<br />    return daoFac;<br />  }<br /><br />  public IEmployeeDAO getEmployeeDAO(){<br />    return new EmployeeDAOImpl();<br />  }<br />}<br /></td></tr></tbody></table><p align="left">　　<strong>与业务组件的协作</strong></p><p align="left">　　现在该了解DAO怎样适应更复杂的情形。如前几节所述，DAO与业务层组件协作获取和更改持久业务数据。下面的清单展示了业务服务组件及其与DAO层的交互：</p><p align="left"></p><table style="WIDTH: 80%; BORDER-TOP-STYLE: solid; BORDER-RIGHT-STYLE: solid; BORDER-LEFT-STYLE: solid; BORDER-BOTTOM-STYLE: solid" bordercolor="#ffffff" cellspacing="0" cellpadding="0" width="80%" align="center" bgcolor="#cccccc" border="0" heihgt=""><tbody><tr><td style="PADDING-LEFT: 5px"><p> public class EmployeeBusinessServiceImpl implements<br />                                       IEmployeeBusinessService {</p><p>  public List getEmployeesWithinSalaryRange(Map salaryMap){</p><p>    IEmployeeDAO empDAO = DAOFactory.getInstance()<br />                                    .getEmployeeDAO();<br />    List empList = empDAO.findBySalaryRange(salaryMap);<br />    return empList;<br />  }<br />}<br /></p></td></tr></tbody></table><p align="left">　　交互过程十分简洁，完全不依赖于任何持久性接口（包括JDBC）。<br /><br /><strong>问题</strong></p><p align="left"><strong>　　DAO设计模式也有缺点：</strong></p><p align="left">　　代码重复：从EmployeeDAOImpl清单可以清楚地看到，对于基于JDBC的传统数据库访问，代码重复（如上面的粗体字所示）是一个主要的问题。一遍又一遍地写着同样的代码，明显违背了基本的面向对象设计的代码重用原则。它将对项目成本、时间安排和工作产生明显的副面影响。</p><p align="left">　　耦合：DAO代码与JDBC接口和核心collection耦合得非常紧密。从每个DAO类的导入声明的数量可以明显地看出这种耦合。</p><p align="left">　　资源耗损：依据EmployeeDAOImpl类的设计，所有DAO方法必须释放对所获得的连接、声明、结果集等数据库资源的控制。这是危险的主张，因为一个编程新手可能很容易漏掉那些约束。结果造成资源耗尽，导致系统停机。</p><p align="left">　　错误处理：JDBC驱动程序通过抛出SQLException来报告所有的错误情况。SQLException是检查到的异常，所以开发人员被迫去处理它，即使不可能从这类导致代码混乱的大多数异常中恢复过来。而且，从SQLException对象获得的错误代码和消息特定于数据库厂商，所以不可能写出可移植的DAO错误发送代码。</p><p align="left">　　脆弱的代码：在基于JDBC的DAO中，两个常用的任务是设置声明对象的绑定变量和使用结果集检索数据。如果SQL where子句中的列数目或者位置更改了，就不得不对代码执行更改、测试、重新部署这个严格的循环过程。</p><p align="left">　　让我们看看如何能够减少这些问题并保留DAO的大多数优点。</p><p align="left">　<strong>　进入Spring DAO</strong></p><p align="left">　　先识别代码中发生变化的部分，然后将这一部分代码分离出来或者封装起来，就能解决以上所列出的问题。Spring的设计者们已经完全做到了这一点，他们发布了一个超级简洁、健壮的、高度可伸缩的JDBC框架。固定部分（像检索连接、准备声明对象、执行查询和释放数据库资源）已经被一次性地写好，所以该框架的一部分内容有助于消除在传统的基于JDBC的DAO中出现的缺点。</p><p align="left">　　图2显示的是Spring JDBC框架的主要组成部分。业务服务对象通过适当的接口继续使用DAO实现类。JdbcDaoSupport是JDBC数据访问对象的超类。它与特定的数据源相关联。Spring Inversion of Control （IOC）容器或BeanFactory负责获得相应数据源的配置详细信息，并将其与JdbcDaoSupport相关联。这个类最重要的功能就是使子类可以使用JdbcTemplate对象。</p><p align="center"><img alt="SPRING数据访问对象(DAO)框架入门图-2" src="http://java.chinaitlab.com/UploadFiles_8734/200703/20070310152441672.gif" /></p><p align="center">　　图2. Spring JDBC框架的主要组件</p><p align="left">　　JdbcTemplate是Spring JDBC框架中最重要的类。引用文献中的话：“它简化了JDBC的使用，有助于避免常见的错误。它执行核心JDBC工作流，保留应用代码以提供SQL和提取结果。”这个类通过执行下面的样板任务来帮助分离JDBC DAO代码的静态部分：</p><p align="left">　　从数据源检索连接。</p><p align="left">　　准备合适的声明对象。</p><p align="left">　　执行SQL CRUD操作。</p><p align="left">　　遍历结果集，然后将结果填入标准的collection对象。</p><p align="left">　　处理SQLException异常并将其转换成更加特定于错误的异常层次结构。</p><p align="left">　　<strong>利用Spring DAO重新编写</strong></p><p align="left">　　既然已基本理解了Spring JDBC框架，现在要重新编写已有的代码。下面将逐步讲述如何解决前几节中提到的问题。</p><p align="left">　　第一步：修改DAO实现类- 现在从JdbcDaoSupport扩展出EmployeeDAOImpl以获得JdbcTemplate.</p><p align="left"></p><table style="WIDTH: 80%; BORDER-TOP-STYLE: solid; BORDER-RIGHT-STYLE: solid; BORDER-LEFT-STYLE: solid; BORDER-BOTTOM-STYLE: solid" bordercolor="#ffffff" cellspacing="0" cellpadding="0" width="80%" align="center" bgcolor="#cccccc" border="0" heihgt=""><tbody><tr><td style="PADDING-LEFT: 5px"><p> import org.springframework.jdbc.core.support.JdbcDaoSupport;<br />import org.springframework.jdbc.core.JdbcTemplate;</p><p>public class EmployeeDAOImpl extends JdbcDaoSupport<br />                                     implements IEmployeeDAO{</p><p>  public List findBySalaryRange(Map salaryMap){</p><p>    Double dblParams [] = {Double.valueOf((String)<br />            salaryMap.get("MIN_SALARY"))<br />              ,Double.valueOf((String)<br />            salaryMap.get("MAX_SALARY"))<br />          };<br />    //The getJdbcTemplate method of JdbcDaoSupport returns an<br />    //instance of JdbcTemplate initialized with a datasource by the<br />    //Spring Bean Factory<br />    JdbcTemplate daoTmplt = this.getJdbcTemplate();<br />    return daoTmplt.queryForList(FIND_BY_SAL_RNG,dblParams);<br />  }<br />}<br /></p></td></tr></tbody></table><p align="left">　　在上面的清单中，传入参数映射中的值存储在双字节数组中，顺序与SQL字符串中的位置参数相同。queryForList（）方法以包含Map（用列名作为键，一项对应一列）的List（一项对应一行）的方式返回查询结果。稍后我会说明如何返回传输对象列表。</p><p align="left">　　从简化的代码可以明显看出，JdbcTemplate鼓励重用，这大大削减了DAO实现中的代码。JDBC和collection包之间的紧密耦合已经消除。由于JdbcTemplate方法可确保在使用数据库资源后将其按正确的次序释放，所以JDBC的资源耗损不再是一个问题。</p><p align="left">　　另外，使用Spring DAO时，不必处理异常。JdbcTemplate类会处理SQLException，并根据SQL错误代码或错误状态将其转换成特定于Spring异常的层次结构。例如，试图向主键列插入重复值时，将引发DataIntegrityViolationException.然而，如果无法从这一错误中恢复，就无需处理该异常。因为Spring DAO的根异常类DataAccessException是运行时异常类，所以可以这样做。值得注意的是Spring DAO异常独立于数据访问实现。如果实现是由O/R映射解决方案提供，就会抛出同样的异常。<br /><br /><strong>第二步：修改业务服务-</strong> 现在业务服务实现了一个新方法setDao（），Spring容器使用该方法传递DAO实现类的引用。该过程称为“设置方法注入（setter injection）”，通过第三步中的配置文件告知Spring容器该过程。注意，不再需要使用DAOFactory，因为Spring BeanFactory提供了这项功能：</p><p align="left"></p><table style="WIDTH: 80%; BORDER-TOP-STYLE: solid; BORDER-RIGHT-STYLE: solid; BORDER-LEFT-STYLE: solid; BORDER-BOTTOM-STYLE: solid" bordercolor="#ffffff" cellspacing="0" cellpadding="0" width="80%" align="center" bgcolor="#cccccc" border="0" heihgt=""><tbody><tr><td style="PADDING-LEFT: 5px"> public class EmployeeBusinessServiceImpl <br />                         implements IEmployeeBusinessService {<br /><br />  IEmployeeDAO empDAO;<br /><br />  public List getEmployeesWithinSalaryRange(Map salaryMap){<br /><br />    List empList = empDAO.findBySalaryRange(salaryMap);<br />    return empList;<br />  } <br />  public void setDao(IEmployeeDAO empDAO){<br />    this.empDAO = empDAO;<br />  }<br />}<br /></td></tr></tbody></table><p align="left">　　请注意P2I的灵活性；即使极大地改动DAO实现，业务服务实现也只需少量更改。这是由于业务服务现在由Spring容器进行管理。</p><p align="left">　　第三步：配置Bean Factory- Spring bean factory需要一个配置文件进行初始化并启动Spring框架。这个配置文件包含所有业务服务和带Spring bean容器的DAO实现类。除此之外，它还包含用于初始化数据源和JdbcDaoSupport的信息：</p><p align="left"></p><table style="WIDTH: 80%; BORDER-TOP-STYLE: solid; BORDER-RIGHT-STYLE: solid; BORDER-LEFT-STYLE: solid; BORDER-BOTTOM-STYLE: solid" bordercolor="#ffffff" cellspacing="0" cellpadding="0" width="80%" align="center" bgcolor="#cccccc" border="0" heihgt=""><tbody><tr><td style="PADDING-LEFT: 5px"><p> &lt;?xml version="1.0" encoding="UTF-8"?&gt;</p><p>&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"<br />"<a href="http://www.springframework.org/dtd/spring-beans.dtd"><font color="#000000" size="2">http://www.springframework.org/dtd/spring-beans.dtd</font></a>"&gt;</p><p>&lt;beans&gt;<br />  &lt;!-- Configure Datasource --&gt;<br />  &lt;bean id="FIREBIRD_DATASOURCE"<br />    class="org.springframework.jndi.JndiObjectFactoryBean"&gt;<br />    &lt;property name="jndiEnvironment"&gt;<br />      &lt;props&gt;<br />        &lt;prop key="java.naming.factory.initial"&gt;<br />          weblogic.jndi.WLInitialContextFactory<br />        &lt;/prop&gt;<br />        &lt;prop key="java.naming.provider.url"&gt;<br />          t3://localhost:7001<br />        &lt;/prop&gt;<br />      &lt;/props&gt;<br />    &lt;/property&gt;<br />    &lt;property name="jndiName"&gt;<br />      &lt;value&gt;<br />        jdbc/DBPool<br />      &lt;/value&gt;<br />    &lt;/property&gt;<br />  &lt;/bean&gt;</p><p>  &lt;!-- Configure DAO --&gt;<br />  &lt;bean id="EMP_DAO" class="com.bea.dev2dev.dao.EmployeeDAOImpl"&gt;<br />    &lt;property name="dataSource"&gt;<br />      &lt;ref bean="FIREBIRD_DATASOURCE"&gt;&lt;/ref&gt;<br />    &lt;/property&gt;<br />  &lt;/bean&gt;</p><p>  &lt;!-- Configure Business Service --&gt;<br />  &lt;bean id="EMP_BUSINESS"<br />  class="com.bea.dev2dev.sampleapp.business.EmployeeBusinessServiceImpl"&gt;<br />    &lt;property name="dao"&gt;<br />      &lt;ref bean="EMP_DAO"&gt;&lt;/ref&gt;<br />    &lt;/property&gt;<br />  &lt;/bean&gt;<br />&lt;/beans&gt;<br /></p></td></tr></tbody></table><p align="left">　　这个Spring bean容器通过调用JdbcDaoSupport提供的setDataSource（）方法，设置包含DAO实现的数据源对象。</p><p align="left">　　<strong>第四步：测试-</strong> 最后是编写JUnit测试类。依照Spring的方式，需要在容器外部进行测试。然而，从第三步中的配置文件可以清楚地看到，我们一直在使用WebLogic Server连接池。</p><p align="left"></p><table style="WIDTH: 80%; BORDER-TOP-STYLE: solid; BORDER-RIGHT-STYLE: solid; BORDER-LEFT-STYLE: solid; BORDER-BOTTOM-STYLE: solid" bordercolor="#ffffff" cellspacing="0" cellpadding="0" width="80%" align="center" bgcolor="#cccccc" border="0" heihgt=""><tbody><tr><td style="PADDING-LEFT: 5px"><p> package com.bea.dev2dev.business;</p><p>import java.util.*;<br />import junit.framework.*;<br />import org.springframework.context.ApplicationContext;<br />import org.springframework.context.support.FileSystemXmlApplicationContext;</p><p>public class EmployeeBusinessServiceImplTest extends TestCase {<br />    private IEmployeeBusinessService empBusiness;<br />    private Map salaryMap;<br />    List expResult;</p><p>    protected void setUp() throws Exception {<br />        initSpringFramework();<br />        initSalaryMap();<br />        initExpectedResult();<br />    }<br />    private void initExpectedResult() {<br />        expResult = new ArrayList();<br />        Map tempMap = new HashMap();<br />        tempMap.put("EMP_NO",new Integer(1));<br />        tempMap.put("EMP_NAME","John");<br />        tempMap.put("SALARY",new Double(46.11));<br />        expResult.add(tempMap);<br />    }<br />    private void initSalaryMap() {<br />        salaryMap = new HashMap();<br />        salaryMap.put("MIN_SALARY","1");<br />        salaryMap.put("MAX_SALARY","50");<br />    }<br />    private void initSpringFramework() {<br />      ApplicationContext ac = new FileSystemXmlApplicationContext<br />  ("C:/SpringConfig/Spring-Config.xml");<br />      empBusiness =<br />             (IEmployeeBusinessService)ac.getBean("EMP_BUSINESS");<br />    }<br />    protected void tearDown() throws Exception {<br />    }</p><p>    /**<br />     * Test of getEmployeesWithinSalaryRange method,<br />     * of class<br />     * com.bea.dev2dev.business.EmployeeBusinessServiceImpl.<br />     */<br />    public void testGetEmployeesWithinSalaryRange() {<br />      List result = empBusiness.getEmployeesWithinSalaryRange<br />     (salaryMap);<br />      assertEquals(expResult, result);<br />    }<br />}<br /></p></td></tr></tbody></table><p align="left"><strong>使用绑定变量</strong></p><p align="left">　　到目前为止，我们搜索了工资介于最低值和最高值之间的雇员。假设在某种情形下，业务用户想要颠倒这一范围。DAO代码很脆弱，将不得不通过更改来满足要求的变化。这个问题在于使用了静态的位置绑定变量（用“？”表示）。Spring DAO通过支持命名的绑定变量来挽救这个情况。修改的IEmployeeDAO清单引入了命名的绑定变量（用“：&lt;some name&gt;”表示）。注意查询中的变化，如下所示：</p><p align="left"></p><table style="WIDTH: 80%; BORDER-TOP-STYLE: solid; BORDER-RIGHT-STYLE: solid; BORDER-LEFT-STYLE: solid; BORDER-BOTTOM-STYLE: solid" bordercolor="#ffffff" cellspacing="0" cellpadding="0" width="80%" align="center" bgcolor="#cccccc" border="0" heihgt=""><tbody><tr><td style="PADDING-LEFT: 5px"><p> import java.util.Map;<br />public interface IEmployeeDAO {</p><p>  //SQL String that will be executed<br />  public String FIND_BY_SAL_RNG = "SELECT EMP_NO, EMP_NAME, "<br />  + "SALARY FROM EMP WHERE SALARY &gt;= :max AND SALARY &lt;= :min";</p><p>  //Returns the list of employees falling into the given salary range<br />  //The input parameter is the immutable map object obtained from<br />  //the HttpServletRequest. This is an early refactoring based on<br />  //- "Introduce Parameter Object"</p><p>  public List findBySalaryRange(Map salaryMap);<br />}<br /></p></td></tr></tbody></table><p align="left">　　多数JDBC驱动程序仅支持位置绑定变量。所以，Spring DAO在运行时将这个查询转换成位置绑定、基于变量的查询，并且设置正确的绑定变量。现在，为了完成这些任务，需要使用NamedParameterJdbcDaoSupport类和NamedParameterJdbcTemplate类，以代替JdbcDaoSupport和JdbcTemplate.下面就是修改后的DAO实现类：</p><p align="left"></p><table style="WIDTH: 80%; BORDER-TOP-STYLE: solid; BORDER-RIGHT-STYLE: solid; BORDER-LEFT-STYLE: solid; BORDER-BOTTOM-STYLE: solid" bordercolor="#ffffff" cellspacing="0" cellpadding="0" width="80%" align="center" bgcolor="#cccccc" border="0" heihgt=""><tbody><tr><td style="PADDING-LEFT: 5px"><p> import org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport;<br />import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;</p><p>public class EmployeeDAOImpl extends NamedParameterJdbcDaoSupport<br />    implements IEmployeeDAO{</p><p>  public List findBySalaryRange(Map salaryMap){</p><p>    NamedParameterJdbcTemplate tmplt =<br />                             this.getNamedParameterJdbcTemplate();<br />    return tmplt.queryForList(IEmployeeDAO.FIND_BY_SAL_RNG<br />    ,salaryMap);<br />  }<br />}<br /></p></td></tr></tbody></table><p align="left">　　NamedParameterJdbcDaoSupport的getNamedParameterJdbcTemplate（）方法返回一个NamedParameterJdbcTemplate实例，该实例由数据源句柄进行了预初始化。Spring Beanfactory执行初始化任务，从配置文件获得所有的详细信息。在执行时，一旦将命名的参数替换成位置占位符，NamedParameterJdbcTemplate就将操作委托给JdbcTemplate.可见，使用命名的参数使得DAO方法不受底层SQL声明任何更改的影响。</p><p align="left">　　最后，如果数据库不支持自动类型转换，需要如下所示，对JUnit测试类中的initSalaryMap（）方法稍做修改。</p><p align="left"></p><table style="WIDTH: 80%; BORDER-TOP-STYLE: solid; BORDER-RIGHT-STYLE: solid; BORDER-LEFT-STYLE: solid; BORDER-BOTTOM-STYLE: solid" bordercolor="#ffffff" cellspacing="0" cellpadding="0" width="80%" align="center" bgcolor="#cccccc" border="0" heihgt=""><tbody><tr><td style="PADDING-LEFT: 5px"> private void initSalaryMap() {<br />        salaryMap = new HashMap();<br />        salaryMap.put("MIN_SALARY",new Double(1));<br />        salaryMap.put("MAX_SALARY",new Double(50));<br />    }<br /></td></tr></tbody></table><br /><strong>Spring DAO回调函数</strong><p align="left">　　至此，已经说明为了解决传统DAO设计中存在的问题，如何封装和概括JdbcTemplate类中JDBC代码的静态部分。现在了解一下有关变量的问题，如设置绑定变量、结果集遍历等。虽然Spring DAO已经拥有这些问题的一般化解决方案，但在某些基于SQL的情况下，可能仍需要设置绑定变量。</p><p align="left">　　在尝试向Spring DAO转换的过程中，介绍了由于业务服务及其客户机之间的约定遭到破坏而导致的隐蔽运行时错误。这个错误的来源可以追溯到原始的DAO.dbcTemplate.queryForList（）方法不再返回EmployeeTO实例列表。而是返回一个map表（每个map是结果集的一行）。</p><p align="left">　　如您目前所知，JdbcTemplate基于模板方法设计模式，该模式利用JDBC API定义SQL执行工作流。必须改变这个工作流以修复被破坏的约定。第一个选择是在子类中更改或扩展工作流。您可以遍历JdbcTemplate.queryForList（）返回的列表，用EmployeeTO实例替换map对象。然而，这会导致我们一直竭力避免的静态代码与动态代码的混合。第二个选择是将代码插入JdbcTemplate提供的各种工作流修改钩子（hook）。明智的做法是在一个不同的类中封装传输对象填充代码，然后通过钩子链接它。填充逻辑的任何修改将不会改变DAO.</p><p align="left">　　编写一个类，使其实现在Spring框架特定的接口中定义的方法，就可以实现第二个选择。这些方法称为回调函数，通过JdbcTemplate向框架注册。当发生相应的事件（例如，遍历结果集并填充独立于框架的传输对象）时，框架将调用这些方法。</p><p align="left">　　<strong>第一步：传输对象</strong></p><p align="left">　　下面是您可能感兴趣的传输对象。注意，以下所示的传输对象是固定的：</p><p align="left"></p><table style="WIDTH: 80%; BORDER-TOP-STYLE: solid; BORDER-RIGHT-STYLE: solid; BORDER-LEFT-STYLE: solid; BORDER-BOTTOM-STYLE: solid" bordercolor="#ffffff" cellspacing="0" cellpadding="0" width="80%" align="center" bgcolor="#cccccc" border="0" heihgt=""><tbody><tr><td style="PADDING-LEFT: 5px"><p> package com.bea.dev2dev.to;</p><p>public final class EmployeeTO implements Serializable{</p><p>      private int empNo;<br />      private String empName;<br />      private double salary;</p><p>      /** Creates a new instance of EmployeeTO */<br />      public EmployeeTO(int empNo,String empName,double salary) {<br />          this.empNo = empNo;<br />          this.empName = empName;<br />          this.salary = salary;<br />      }<br />      public String getEmpName() {<br />          return this.empName;<br />      }<br />      public int getEmpNo() {<br />          return this.empNo;<br />      }<br />      public double getSalary() {<br />          return this.salary;<br />      }<br />      public boolean equals(EmployeeTO empTO){<br />          return empTO.empNo == this.empNo;<br />      }<br />}<br /></p></td></tr></tbody></table><p align="left">　　<strong>第二步：实现回调接口</strong></p><p align="left">　　实现RowMapper接口，填充来自结果集的传输对象。下面是一个例子：</p><p align="left"></p><table style="WIDTH: 80%; BORDER-TOP-STYLE: solid; BORDER-RIGHT-STYLE: solid; BORDER-LEFT-STYLE: solid; BORDER-BOTTOM-STYLE: solid" bordercolor="#ffffff" cellspacing="0" cellpadding="0" width="80%" align="center" bgcolor="#cccccc" border="0" heihgt=""><tbody><tr><td style="PADDING-LEFT: 5px"><p> package com.bea.dev2dev.dao.mapper;</p><p>import com.bea.dev2dev.to.EmployeeTO;<br />import java.sql.ResultSet;<br />import java.sql.SQLException;<br />import org.springframework.jdbc.core.RowMapper;</p><p>public class EmployeeTOMapper implements RowMapper{</p><p>  public Object mapRow(ResultSet rs, int rowNum)<br />                                         throws SQLException{<br />      int empNo = rs.getInt(1);<br />      String empName = rs.getString(2);<br />      double salary = rs.getDouble(3);<br />      EmployeeTO empTo = new EmployeeTO(empNo,empName,salary);<br />      return empTo;<br />   }<br />}<br /></p></td></tr></tbody></table><p align="left">　　注意实现类不应该对提供的ResultSet对象调用next（）方法。这由框架负责，该类只要从结果集的当前行提取值就行。回调实现抛出的任何SQLException也由Spring框架处理。</p><p align="left">　　<strong>第三步：插入回调接口</strong></p><p align="left">　　执行SQL查询时，JdbcTemplate利用默认的RowMapper实现产生map列表。现在需要注册自定义回调实现来修改JdbcTemplate的这一行为。注意现在用的是NamedParameterJdbcTemplate的query（）方法，而不是queryForList（）方法：</p><p align="left"></p><table style="WIDTH: 80%; BORDER-TOP-STYLE: solid; BORDER-RIGHT-STYLE: solid; BORDER-LEFT-STYLE: solid; BORDER-BOTTOM-STYLE: solid" bordercolor="#ffffff" cellspacing="0" cellpadding="0" width="80%" align="center" bgcolor="#cccccc" border="0" heihgt=""><tbody><tr><td style="PADDING-LEFT: 5px"><p> public class EmployeeDAOImpl extends NamedParameterJdbcDaoSupport<br />    implements IEmployeeDAO{</p><p>  public List findBySalaryRange(Map salaryMap){</p><p>    NamedParameterJdbcTemplate daoTmplt =<br />          getNamedParameterJdbcTemplate();<br />    return daoTmplt.query(IEmployeeDAO.FIND_BY_SAL_RNG, salaryMap,<br />          new EmployeeTOMapper());<br />  }<br />}<br /></p></td></tr></tbody></table><p align="left">　　Spring DAO框架对执行查询后返回的结果进行遍历。它在遍历的每一步调用EmployeeTOMapper类实现的mapRow（）方法，使用EmployeeTO传输对象填充最终结果的每一行。</p><p align="left">　　<strong>第四步：修改后的JUnit类</strong></p><p align="left">　　现在要根据返回的传输对象测试这些结果。为此要对测试方法进行修改。</p><p align="left"></p><table style="WIDTH: 80%; BORDER-TOP-STYLE: solid; BORDER-RIGHT-STYLE: solid; BORDER-LEFT-STYLE: solid; BORDER-BOTTOM-STYLE: solid" bordercolor="#ffffff" cellspacing="0" cellpadding="0" width="80%" align="center" bgcolor="#cccccc" border="0" heihgt=""><tbody><tr><td style="PADDING-LEFT: 5px"><p> public class EmployeeBusinessServiceImplTest extends TestCase {</p><p>  private IEmployeeBusinessService empBusiness;<br />  private Map salaryMap;<br />      List expResult;</p><p>      // all methods not shown in the listing remain the<br />      // same as in the previous example<br />      private void initExpectedResult() {<br />          expResult = new ArrayList();<br />          EmployeeTO to = new EmployeeTO(2,"John",46.11);<br />          expResult.add(to);<br />      }</p><p>      /**<br />       * Test of getEmployeesWithinSalaryRange method, of<br />       * class com.bea.dev2dev.business.<br />       * EmployeeBusinessServiceImpl<br />       */<br />      public void testGetEmployeesWithinSalaryRange() {<br />          List result = empBusiness.<br />  getEmployeesWithinSalaryRange(salaryMap);<br />          assertEquals(expResult, result);<br />      }</p><p>      public void assertEquals(List expResult, List result){<br />          EmployeeTO expTO = (EmployeeTO) expResult.get(0);<br />          EmployeeTO actualTO = (EmployeeTO) result.get(0);<br />          if(!expTO.equals(actualTO)){<br />               throw new RuntimeException("** Test Failed **");<br />          }<br />      }<br />}<br /></p></td></tr></tbody></table><p align="left">　　<strong>优势</strong></p><p align="left">　　Spring JDBC框架的优点很清楚。我们获益很多，并将DAO方法简化到只有几行代码。代码不再脆弱，这要感谢该框架对命名的参数绑定变量的“开箱即用”支持，以及在映射程序中将传输对象填充逻辑分离。</p><p align="left">　　Spring JDBC的优点应该促使您向这一框架移植现有的代码。希望本文在这一方面能有所帮助。它会帮助您获得一些重构工具和知识。例如，如果您没有采用P2I Extract Interface，那么可以使用重构，从现有的DAO实现类创建接口。除此之外，查看本文的参考资料可以得到更多指导。</p><p align="left">　　<a title="源代码下载" href="http://java.chinaitlab.com/UploadFiles_8734/200703/20070310152359590.zip"><font color="#000000" size="2">源代码下载</font></a></p><img src ="http://www.blogjava.net/jelver/aggbug/106616.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2007-03-27 10:48 <a href="http://www.blogjava.net/jelver/articles/106616.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring AOP中文教程 (zhuan)</title><link>http://www.blogjava.net/jelver/articles/95804.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Wed, 24 Jan 2007 12:53:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/95804.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/95804.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/95804.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/95804.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/95804.html</trackback:ping><description><![CDATA[
		<strong>Spring AOP中文教程 <br /><br /></strong>
		<span class="postbody" twffan="done">这是在网上发现的一篇关于Spring AOP编程的教程，读完这篇文章后，Spring AOP不再难以理解，推荐给Spring AOP的初学者。这是译文的<a class="postlink" href="http://tools.devchannel.org/devtoolschannel/04/04/15/1457223.shtml" target="_blank"><font color="#006699">链接</font></a>。 <br /><br />AOP正在成为软件开发的下一个圣杯。使用AOP，你可以将处理aspect的代码注入主程序，通常主程序的主要目的并不在于处理这些aspect。AOP可以防止代码混乱。 <br />为了理解AOP如何做到这点，考虑一下记日志的工作。日志本身不太可能是你开发的主程序的主要任务。如果能将“不可见的”、通用的日志代码注入主程序中，那该多好啊。AOP可以帮助你做到。 <br />Spring framework是很有前途的AOP技术。作为一种非侵略性的，轻型的AOP framework，你无需使用预编译器或其他的元标签，便可以在Java程序中使用它。这意味着开发团队里只需一人要对付AOP framework，其他人还是象往常一样编程。 <br />AOP是很多直觉难以理解的术语的根源。幸运的是，你只要理解三个概念，就可以编写AOP模块。这三个概念是：advice，pointcut和advisor。advice是你想向别的程序内部不同的地方注入的代码。pointcut定义了需要注入advice的位置，通常是某个特定的类的一个public方法。advisor是pointcut和advice的装配器，是将advice注入主程序中预定义位置的代码。 <br /><br />既然我们知道了需要使用advisor向主要代码中注入“不可见的”advice，让我们实现一个Spring AOP的例子。在这个例子中，我们将实现一个before advice，这意味着advice的代码在被调用的public方法开始前被执行。以下是这个before advice的实现代码： <br /><br /></span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed" twffan="done">
												<strong>代码:</strong>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">package com.company.springaop.test; <br /><br />import java.lang.reflect.Method; <br />import org.springframework.aop.MethodBeforeAdvice; <br /><br />public class TestBeforeAdvice implements MethodBeforeAdvice { <br /><br />  public void before(Method m, Object[] args, Object target) <br />  throws Throwable { <br />    System.out.println("Hello world! (by " <br />        + this.getClass().getName() <br />        + ")"); <br />  } <br />} <br /> </td>
						</tr>
				</tbody>
		</table>
		<span class="postbody" twffan="done">
				<br />
				<br />接口MethodBeforeAdvice只有一个方法before需要实现，它定义了advice的实现。before方法共用三个参数，它们提供了相当丰富的信息。参数Method m是advice开始后执行的方法。方法名称可以用作判断是否执行代码的条件。Object[] args是传给被调用的public方法的参数数组。当需要记日志时，参数args和被执行方法的名称，都是非常有用的信息。你也可以改变传给m的参数，但要小心使用这个功能；编写最初主程序的程序员并不知道主程序可能会和传入参数的发生冲突。Object target是执行方法m对象的引用。 <br /><br />在下面的BeanImpl类中，每个public方法调用前，都会执行advice： <br /><br /></span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed" twffan="done">
												<strong>代码:</strong>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">package com.company.springaop.test; <br /><br />public class BeanImpl implements Bean { <br /><br />  public void theMethod() { <br />    System.out.println(this.getClass().getName() <br />        + "." + new Exception().getStackTrace()[0].getMethodName() <br />        + "()" <br />        + " says HELLO!"); <br />  } <br />}</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody" twffan="done">
				<br />
				<br />类BeanImpl实现了下面的接口Bean： <br /><br /></span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed" twffan="done">
												<strong>代码:</strong>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">package com.company.springaop.test; <br /><br />public interface Bean { <br />  public void theMethod(); <br />}</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody" twffan="done">
				<br />
				<br />
				<br />虽然不是必须使用接口，但面向接口而不是面向实现编程是良好的编程实践，Spring也鼓励这样做。 <br /><br />pointcut和advice通过配置文件来实现，因此，接下来你只需编写主方法的Java代码： <br /></span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed" twffan="done">
												<strong>代码:</strong>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">
										<br />
										<br />package com.company.springaop.test; <br /><br />import org.springframework.context.ApplicationContext; <br />import org.springframework.context.support.FileSystemXmlApplicationContext; <br /><br />public class Main { <br /><br />  public static void main(String[] args) { <br />    //Read the configuration file <br />    ApplicationContext ctx <br />        = new FileSystemXmlApplicationContext("springconfig.xml"); <br /><br />    //Instantiate an object <br />    Bean x = (Bean) ctx.getBean("bean"); <br /><br />    //Execute the public method of the bean (the test) <br />    x.theMethod(); <br />  } <br />}</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody" twffan="done">
				<br />
				<br />
				<br />我们从读入和处理配置文件开始，接下来马上要创建它。这个配置文件将作为粘合程序不同部分的“胶水”。读入和处理配置文件后，我们会得到一个创建工厂ctx。任何一个Spring管理的对象都必须通过这个工厂来创建。对象通过工厂创建后便可正常使用。 <br /><br />仅仅用配置文件便可把程序的每一部分组装起来。 <br /></span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed" twffan="done">
												<strong>代码:</strong>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">
										<br />&lt;?xml version="1.0" encoding="UTF-8"?&gt; <br />&lt;!DOCTYPE beans PUBLIC  "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"&gt; <br /><br />&lt;beans&gt; <br />  &lt;!--CONFIG--&gt; <br />  &lt;bean id="bean" class="org.springframework.aop.framework.ProxyFactoryBean"&gt; <br />    &lt;property name="proxyInterfaces"&gt; <br />      &lt;value&gt;com.company.springaop.test.Bean&lt;/value&gt; <br />    &lt;/property&gt; <br />    &lt;property name="target"&gt; <br />      &lt;ref local="beanTarget"/&gt; <br />    &lt;/property&gt; <br />    &lt;property name="interceptorNames"&gt; <br />      &lt;list&gt; <br />        &lt;value&gt;theAdvisor&lt;/value&gt; <br />      &lt;/list&gt; <br />    &lt;/property&gt; <br />  &lt;/bean&gt; <br /><br />  &lt;!--CLASS--&gt; <br />  &lt;bean id="beanTarget" class="com.company.springaop.test.BeanImpl"/&gt; <br /><br />  &lt;!--ADVISOR--&gt; <br />  &lt;!--Note: An advisor assembles pointcut and advice--&gt; <br />  &lt;bean id="theAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"&gt; <br />    &lt;property name="advice"&gt; <br />      &lt;ref local="theBeforeAdvice"/&gt; <br />    &lt;/property&gt; <br />    &lt;property name="pattern"&gt; <br />      &lt;value&gt;com\.company\.springaop\.test\.Bean\.theMethod&lt;/value&gt; <br />    &lt;/property&gt; <br />  &lt;/bean&gt; <br /><br />  &lt;!--ADVICE--&gt; <br />  &lt;bean id="theBeforeAdvice" class="com.company.springaop.test.TestBeforeAdvice"/&gt; <br />&lt;/beans&gt; <br /> </td>
						</tr>
				</tbody>
		</table>
		<span class="postbody" twffan="done">
				<br />
				<br />四个bean定义的次序并不重要。我们现在有了一个advice，一个包含了正则表达式pointcut的advisor，一个主程序类和一个配置好的接口，通过工厂ctx，这个接口返回自己本身实现的一个引用。 <br /><br />BeanImpl和TestBeforeAdvice都是直接配置。我们用一个唯一的ID创建一个bean元素，并指定了一个实现类。这就是全部的工作。 <br /><br />advisor通过Spring framework提供的一个RegexMethodPointcutAdvisor类来实现。我们用advisor的一个属性来指定它所需的advice-bean。第二个属性则用正则表达式定义了pointcut，确保良好的性能和易读性。 <br /><br />最后配置的是bean，它可以通过一个工厂来创建。bean的定义看起来比实际上要复杂。bean是ProxyFactoryBean的一个实现，它是Spring framework的一部分。这个bean的行为通过一下的三个属性来定义： <br /><br /><ul><br /><li>属性proxyInterface定义了接口类。 <br /></li><li>属性target指向本地配置的一个bean，这个bean返回一个接口的实现。 <br /></li><li>属性interceptorNames是唯一允许定义一个值列表的属性。这个列表包含所有需要在beanTarget上执行的advisor。注意，advisor列表的次序是非常重要的。 <br /></li></ul><br /><br /><span style="FONT-WEIGHT: bold" twffan="done">Spring工具</span><br /><br />虽然你可以手工修改Ant构建脚本，但使用SpringUI（译注：SpringUI现在是Spring framework的一部分，并改名为spring-ide），使用Spring AOP变得很简单，只要点点鼠标即可。你可以把SpringUI安装成Eclipse的一个plug-in。然后，你只需在你的project上右击鼠标，并选择“add Spring Project Nature”。在project属性中，你可以在“Spring Project”下添加Spring配置文件。在编译前把下面的类库加入project：aopalliance.jar，commons-logging.jar，jakarta-oro-2.0.7.jar和spring.jar。运行程序时你会看到下面的信息： <br /><br />... (logging information) <br />Hello world! (by com.company.springaop.test.TestBeforeAdvice) <br />com.company.springaop.test.BeanImpl.theMethod() says HELLO! <br /><br /><br /><span style="FONT-WEIGHT: bold" twffan="done">优点和缺点</span><br /><br />Spring比起其他的framework更有优势，因为除了AOP以外，它提供了更多别的功能。作为一个轻型framework，它在J2EE不同的部分都可以发挥作用。因此，即使不想使用Spring AOP，你可能还是想使用Spring。另一个优点是，Spring并不要求开发团队所有的人员都会用它。学习Spring应该从Spring reference的第一页开始。读了本文后，你应该可以更好地理解Spring reference了。Spring唯一的缺点是缺乏更多的文档，但它的mailing list是个很好的补充，而且会不断地出现更多的文档。</span>
<img src ="http://www.blogjava.net/jelver/aggbug/95804.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2007-01-24 20:53 <a href="http://www.blogjava.net/jelver/articles/95804.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>什么是Ioc（Inversion of Control） (zhuan)</title><link>http://www.blogjava.net/jelver/articles/34769.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Sat, 11 Mar 2006 00:28:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/34769.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/34769.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/34769.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/34769.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/34769.html</trackback:ping><description><![CDATA[<P class=MsoNormal style="LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这篇短文基本上是改编自Martin Fowler的Inversion of Control Containers and the Dependency Injection pattern，目的呢，是让读者能够在最短时间内了解IoC的概念。这也是我一贯的“风格”：最短的文字、最精要的内容、最清晰的说明。希望我能做到，自勉^_^</SPAN></P><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">
<P align=center>
<HR align=left color=#007100 noShade SIZE=2 width=400>

<P></P></SPAN>
<P class=MsoNormal style="LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">J2EE</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">应用开发中，经常遇到的问题就是：如何将不同的组件组装成为一个内聚的应用程序？</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">IoC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式可以解决这个问题，其目标是将组件的配置与使用分离开。</SPAN><SPAN lang=EN-US><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman">IoC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Inversion of Control</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，控制反转</SPAN><A href="http://www.blogbus.com/blogbus/blog/articlesrc.php?id=0#_ftn1" name=_ftnref1 style="mso-footnote-id: ftn1" title=""><SPAN class=MsoFootnoteReference><SPAN lang=EN-US><SPAN style="mso-special-character: footnote"><SPAN class=MsoFootnoteReference><SPAN lang=EN-US style="FONT-FAMILY: 'Times New Roman'; FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">[1]</SPAN></SPAN></SPAN></SPAN></SPAN></A><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，其原理是基于</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">OO</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设计原则的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">The Hollywood Principle</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Don't call us, we'll call you</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。也就是说，所有的组件</SPAN><A href="http://www.blogbus.com/blogbus/blog/articlesrc.php?id=0#_ftn2" name=_ftnref2 style="mso-footnote-id: ftn2" title=""><SPAN class=MsoFootnoteReference><SPAN lang=EN-US><SPAN style="mso-special-character: footnote"><SPAN class=MsoFootnoteReference><SPAN lang=EN-US style="FONT-FAMILY: 'Times New Roman'; FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">[2]</SPAN></SPAN></SPAN></SPAN></SPAN></A><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">都是被动的（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Passive</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），所有的组件初始化和调用都由容器负责。组件处在一个容器当中，由容器负责管理。</SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">要说明</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">IoC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式最好的方法是使用代码。下边是一段正常的代码。</SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman">class <SPAN style="COLOR: red">ClassA</SPAN>...</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>public String <SPAN style="COLOR: blue">aMethod</SPAN>(String arg){</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>String result = instanceOfClassB.<SPAN style="COLOR: blue">bMethod</SPAN>();</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>do something;</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>return result;</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>}</FONT></SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在上边的代码里，我们要解决的问题是：</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">ClassA</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如何获得</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">ClassB</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的实例？一个最直接的方法是在</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">aMethod</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">里声明：</SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><FONT face="Times New Roman"><SPAN lang=EN-US style="COLOR: red">IClassB</SPAN><SPAN lang=EN-US> instanceOfClassB = new ClassB();</SPAN></FONT></P>
<P class=MsoNormal style="LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这里使用了一个接口</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">IClassB</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">问题是，如果出现这样的情况：继续使用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">ClassA</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，但要求用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">IClassB</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的另一个实现</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">ClassB2</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">代替</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">ClassB</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">呢？更概括一点说：</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">ClassA</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">怎样才能找到</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">IClassB</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的具体实现？很明显，上述代码增加</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">ClassA</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">ClassB</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的耦合度，以致于无法在不修改</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">ClassA</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的情况下变更</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">IClassB</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的具体实现。</SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman">IoC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式就是用于解决这样的问题。当然，还有其他的方法，比如</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Service Locator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式，但现在我们只关注</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">IoC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。如前所述，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">IoC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">容器负责初始化组件（如</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">IClassB</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），并将实例交给使用者。使用代码或配置文件以声明的方式将接口与实例关联起来，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">IoC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">容器负责进行实际的调用处理。对于调用者，只需要关注接口就行了。</SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">根据实例传入方式的不同，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">IoC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">分为</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">type 1 IoC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（接口注入</SPAN><A href="http://www.blogbus.com/blogbus/blog/articlesrc.php?id=0#_ftn3" name=_ftnref3 style="mso-footnote-id: ftn3" title=""><SPAN class=MsoFootnoteReference><SPAN lang=EN-US><SPAN style="mso-special-character: footnote"><SPAN class=MsoFootnoteReference><SPAN lang=EN-US style="FONT-FAMILY: 'Times New Roman'; FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">[3]</SPAN></SPAN></SPAN></SPAN></SPAN></A><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）、</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">type 2 IoC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（设值方法注入）和</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">type 3 IoC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（构造子注入）。分别用代码说明如下：</SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.1pt; mso-char-indent-count: 2.0"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">type 1 IoC</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（接口注入）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman">public interface GetClassB {</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>void getClassB(IClassB instanceOfClassB);</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman">}</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman">class ClassA implements GetClassB…</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>IClassB instanceOfClassB;</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>void getClassB(IClassB instanceOfClassB) {</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 42pt; mso-char-indent-count: 4.0"><SPAN lang=EN-US><FONT face="Times New Roman">this.instanceOfClassB = instanceOfClassB;</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>}<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.1pt; mso-char-indent-count: 2.0"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">type 2 IoC</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（设值方法注入）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman">class ClassA...</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>IClassB instanceOfClassB;</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>public void setFinder(IClassB instanceOfClassB) {</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>this.instanceOfClassB = instanceOfClassB;</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>}</FONT></SPAN></P>
<P class=MsoNormal style="LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.1pt; mso-char-indent-count: 2.0"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">type 3 IoC</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（构造子注入）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman">class ClassA…</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 31.5pt; mso-char-indent-count: 3.0"><SPAN lang=EN-US><FONT face="Times New Roman">ClassB instanceOfClassB;</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>public classA(IClassB instanceOfClassB) {</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>this. instanceOfClassB = instanceOfClassB;</FONT></SPAN></P>
<P class=MsoNormal style="BACKGROUND: #e6e6e6; LINE-HEIGHT: 150%; MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>}</FONT></SPAN></P><SPAN lang=EN-US style="FONT-FAMILY: 'Times New Roman'; FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">　　Spring</SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">使用的是</SPAN><SPAN lang=EN-US style="FONT-FAMILY: 'Times New Roman'; FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">type 2 IoC</SPAN><SPAN style="FONT-FAMILY: 宋体; FONT-SIZE: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">。</SPAN><FONT face="宋体, MS Song"> </FONT>
<DIV style="mso-element: footnote-list"><BR clear=all><FONT face="宋体, MS Song">
<HR align=left SIZE=1 width="33%">
</FONT>
<DIV id=ftn1 style="mso-element: footnote">
<P class=MsoFootnoteText style="MARGIN: 0cm 0cm 0pt"><A href="http://www.blogbus.com/blogbus/blog/articlesrc.php?id=0#_ftnref1" name=_ftn1 style="mso-footnote-id: ftn1" title=""><SPAN class=MsoFootnoteReference><SPAN lang=EN-US><SPAN style="mso-special-character: footnote"><SPAN class=MsoFootnoteReference><SPAN lang=EN-US style="FONT-FAMILY: 'Times New Roman'; FONT-SIZE: 9pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">[1]</SPAN></SPAN></SPAN></SPAN></SPAN></A><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman"> </FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Martin Fowler</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</SPAN><I style="mso-bidi-font-style: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Inversion of Control Containers and the Dependency Injection pattern</FONT></SPAN></I><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一文中，作者提出本模式更准确的名称应该是</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Dependency Injection</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。考虑到使用上的习惯，在本文档中我们将继续使用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">IoC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的概念。</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></FONT></P></DIV>
<DIV id=ftn2 style="mso-element: footnote">
<P class=MsoFootnoteText style="MARGIN: 0cm 0cm 0pt"><A href="http://www.blogbus.com/blogbus/blog/articlesrc.php?id=0#_ftnref2" name=_ftn2 style="mso-footnote-id: ftn2" title=""><SPAN class=MsoFootnoteReference><SPAN lang=EN-US><SPAN style="mso-special-character: footnote"><SPAN class=MsoFootnoteReference><SPAN lang=EN-US style="FONT-FAMILY: 'Times New Roman'; FONT-SIZE: 9pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">[2]</SPAN></SPAN></SPAN></SPAN></SPAN></A><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman"> </FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">同一篇文章中，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Martin Fowler</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">还提出了</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Componet</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（组件）与</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Service</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（服务）的区别问题。我个人认为“组件”更有助于帮助我们理解</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">IoC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的概念，所以在本文档中使用“组件”来代表“组件或服务”</SPAN></FONT></P></DIV>
<DIV id=ftn3 style="mso-element: footnote">
<P class=MsoFootnoteText style="MARGIN: 0cm 0cm 0pt"><A href="http://www.blogbus.com/blogbus/blog/articlesrc.php?id=0#_ftnref3" name=_ftn3 style="mso-footnote-id: ftn3" title=""><SPAN class=MsoFootnoteReference><SPAN lang=EN-US><SPAN style="mso-special-character: footnote"><SPAN class=MsoFootnoteReference><SPAN lang=EN-US style="FONT-FAMILY: 'Times New Roman'; FONT-SIZE: 9pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">[3]</SPAN></SPAN></SPAN></SPAN></SPAN></A><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman"> </FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如上所述，注入是另一种说法，此处只用于辅助说明。</SPAN></FONT></P></DIV></DIV><BR><img src ="http://www.blogjava.net/jelver/aggbug/34769.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-03-11 08:28 <a href="http://www.blogjava.net/jelver/articles/34769.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring Framework文档资源</title><link>http://www.blogjava.net/jelver/articles/34768.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Sat, 11 Mar 2006 00:20:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/34768.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/34768.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/34768.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/34768.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/34768.html</trackback:ping><description><![CDATA[<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">最近开始研究Spring Framework，顺手整理了这份文档资源列表。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></SPAN>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">资源链接页</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">Spring Framework Documentaion</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><A href="http://www.springframework.org/documentation.html"><FONT face="Times New Roman">http://www.springframework.org/documentation.html</FONT></A></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">Spring</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中文论坛图书贴</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><A href="http://xglw.51.net/5team/springframework/viewtopic.php?t=31"><FONT face="Times New Roman">http://xglw.51.net/5team/springframework/viewtopic.php?t=31</FONT></A></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">Spring Reference Documentation</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><A href="http://www.springframework.org/docs/reference/index.html"><FONT face="Times New Roman">http://www.springframework.org/docs/reference/index.html</FONT></A></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">or </FONT><A href="http://www.springframework.org/docs/spring-reference.pdf"><FONT face="Times New Roman">http://www.springframework.org/docs/spring-reference.pdf</FONT></A></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">作者：</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Spring </FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发组</SPAN><FONT face="Times New Roman"> </FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中文版</SPAN><SPAN lang=EN-US><A href="http://xglw.51.net/5team/springframework/book/spring_referece_inchinese_m2.pdf"><FONT face="Times New Roman">http://xglw.51.net/5team/springframework/book/spring_referece_inchinese_m2.pdf</FONT></A></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">for M2</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">翻译：</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Spring</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中文论坛翻译组</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">Spring</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Document</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中还提供了：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">The Spring Framework - A Lightweight Container by Rod Johnson, Juergen Hoeller</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">Container Resources vs Local Resources(for transactional data access with the Spring Framework) by Juergen Hoeller</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">Data Access and Transaction Abstraction with the Spring Framework(featuring Hibernate examples) by Juergen Hoeller</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">Web MVC with the Spring Framework by Juergen Hoeller</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><A href="http://xglw.51.net/5team/springframework/book/webMvcSpring.pdf"><SPAN style="COLOR: windowtext; FONT-FAMILY: 宋体; TEXT-DECORATION: none; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; text-underline: none">中文版：</SPAN><FONT face="Times New Roman">http://xglw.51.net/5team/springframework/book/webMvcSpring.pdf</FONT></A></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">翻译；</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">yanger</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">more…</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">Introducing the Spring Framework</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><A href="http://www.theserverside.com/articles/article.tss?l=SpringFramework"><FONT face="Times New Roman">http://www.theserverside.com/articles/article.tss?l=SpringFramework</FONT></A></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">作者：</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Rod Johnson </FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中文版</SPAN><FONT face="Times New Roman"> <SPAN lang=EN-US><A href="http://xglw.51.net/5team/springframework/viewtopic.php?t=18">http://xglw.51.net/5team/springframework/viewtopic.php?t=18</A></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">翻译：</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">yanger</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">Developing a Spring Framework MVC application step-by-step</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><A href="http://www.springframework.org/docs/MVC-step-by-step/Spring-MVC-step-by-step.html"><FONT face="Times New Roman">http://www.springframework.org/docs/MVC-step-by-step/Spring-MVC-step-by-step.html</FONT></A></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">作者：</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Thomas Risberg</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">Spring Framework Tutorial</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><A href="http://www.springframework.org/downloads/tutorial.pdf"><FONT face="Times New Roman">http://www.springframework.org/downloads/tutorial.pdf</FONT></A></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">作者：</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Isabelle Muszynski</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</SPAN><SPAN lang=EN-US><A href="http://groups.yahoo.com/group/spring_in_chinese/"><FONT face="Times New Roman">Spring In Chinese Group</FONT></A></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">有</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">PPT</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><FONT face="Times New Roman"> <SPAN lang=EN-US>On Spring by gigix</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">PPT</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><FONT face="Times New Roman"> <SPAN lang=EN-US>Spring Introduction for 3.12M2 by yanger</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">Framework Design</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><A href="http://qca.cn/frameworkdesign/content.htm"><FONT face="Times New Roman">http://qca.cn/frameworkdesign/content.htm</FONT></A></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">作者：林星</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">书籍购买链接</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">Expert One-on-One J2EE Design and Development</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（略）</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">作者：</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Rod Johnson<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中文版：</SPAN><SPAN lang=EN-US><A href="http://www.china-pub.com/computers/common/info.asp?id=14126"><FONT face="Times New Roman">http://www.china-pub.com/computers/common/info.asp?id=14126</FONT></A></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（说明：英文版本身很简明，翻译则评价甚差）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P><SPAN lang=EN-US><o:p>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">我眼中的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Spring</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><A href="http://www.blogbus.com/blogbus/blog/diary.php?diaryid=125334"><FONT face="Times New Roman">http://www.blogbus.com/blogbus/blog/diary.php?diaryid=125334</FONT></A></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">作者：</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">dreamhead</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">Spring is coming</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><A href="http://www.blogbus.com/blogbus/blog/diary.php?diaryid=126737"><FONT face="Times New Roman">http://www.blogbus.com/blogbus/blog/diary.php?diaryid=126737</FONT></A></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">作者：</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">founder_chen<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"></o:p></SPAN></P><img src ="http://www.blogjava.net/jelver/aggbug/34768.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-03-11 08:20 <a href="http://www.blogjava.net/jelver/articles/34768.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring 源码分析：ApplicationContext</title><link>http://www.blogjava.net/jelver/articles/33255.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Thu, 02 Mar 2006 09:09:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/33255.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/33255.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/33255.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/33255.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/33255.html</trackback:ping><description><![CDATA[<H2 class=diaryTitle>Spring 源码分析：ApplicationContext</H2><B>关键词</B>： <A href="http://tag.bokee.com/tag/Spring" target=_blank>Spring</A> &nbsp;&nbsp; <A href="http://tag.bokee.com/tag/ApplicationCont" target=_blank>ApplicationCont</A> &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<P><PRE><FONT color=#3333cc>分析ApplicationContext</FONT></PRE><PRE><FONT color=#3333cc>       Spring的bean包支持通过编码方式管理和操作bean的基本功能，ApplicationContext</FONT></PRE><PRE><FONT color=#3333cc>则以Framework的方式提供BeanFactory的所有功能。使用ApplicationContext，你可以让</FONT></PRE><PRE><FONT color=#3333cc>系统加载你的bean（例如，在Servlet容器初始化ContextLoaderServlet时，通过</FONT></PRE><PRE><FONT color=#3333cc>ContextLoader类加载Spring Framework），而不是使用编码方式来加载。</FONT></PRE><PRE><FONT color=#3333cc>       ApplicationContext接口是context包的基础，位于</FONT></PRE><PRE><FONT color=#3333cc>org.springframework.context包里，提供了BeanFactory的所有功能。除此之外， </FONT></PRE><PRE><FONT color=#3333cc>ApplicationContext为了支持Framework的工作方式，提供了以下的功能：</FONT></PRE><PRE><FONT color=#3333cc>      l.MessageSource，提供了语言信息的国际化支持
      2.提供资源（如URL和文件系统）的访问支持
      3.为实现了ApplicationListener接口的bean提供了事件传播支持
      4.为不同的应用环境提供不同的context，例如支持web应用的XmlWebApplicationContext类

      下面的源代码分析主要集中在ApplicationContext接口特有的功能上，如国际化支持，</FONT></PRE><PRE><FONT color=#3333cc>资源访问和bean的事件传播。

我的问题</FONT></PRE><PRE><FONT color=#3333cc>       现在我的问题是，ApplicationContext是如何实现上面提到的功能的？下面的分析</FONT></PRE><PRE><FONT color=#3333cc>将作出回答。

准备测试用例</FONT></PRE><PRE><FONT color=#3333cc>       1. 首先在类路径根目录编写测试国际化支持的testmsg.xml，并将它加入Spring IDE</FONT></PRE><PRE><FONT color=#3333cc>的管理范围：</FONT></PRE><PRE><FONT color=#3333cc>       &lt;beans&gt;
            &lt;bean id="messageSource" </FONT></PRE><PRE><FONT color=#3333cc>           class="org.springframework.context.support.ResourceBundleMessageSource"&gt;
                 &lt;property name="basenames"&gt;
                      &lt;list&gt;
                            &lt;value&gt;message&lt;/value&gt;
                      &lt;/list&gt;
                 &lt;/property&gt;
            &lt;/bean&gt;
       &lt;/beans&gt;

       2. 编写测试用例，测试国际化支持和资源访问的功能。
           public class MsgTest extends TestCase {
                 ApplicationContext ctx = null;
                 public MsgTest(String arg0) {
                       super(arg0);
                 }
                 protected void setUp() throws Exception {
                       super.setUp();
                       ctx = new FileSystemXmlApplicationContext("testmsg.xml");
                 }
                 public void testMessageResource() {
                       Object[] args = {"我", "你"};
                       String msg = ctx.getMessage("hello", args, Locale.CHINA);
                       //System.out.println("msg=" + msg);
                       assertEquals("我和你", msg);
                       Resource rs = ctx.getResource("classpath:log4j.properties");
                       assertTrue(rs.exists());
                }
           }

       3. 在类路径根目录创建属性文件message.properties，内容为hello={0}和{1}。
 
       此时运行TestCase，果然不出所料，Junit视图的测试状态是红条。将打印msg变量的</FONT></PRE><PRE><FONT color=#3333cc>语句打开，重新测试，发现"和"字是乱码。</FONT></PRE><PRE><FONT color=#3333cc>       在message.properties文件中将"和"字改为ASCII码\u548c，重新运行TestCase，</FONT></PRE><PRE><FONT color=#3333cc>绿条，测试通过。</FONT></PRE><PRE><FONT color=#3333cc>       将testmsg.xml中bean的id改为messageSource1，重新运行测试，出现红条，</FONT></PRE><PRE><FONT color=#3333cc>测试失败，说明bean的名称必须是messageSource，这点值得注意。至于其中的原因稍后</FONT></PRE><PRE><FONT color=#3333cc>说明。

       ApplicationContext接口通过继承BeanFactory，MessageSource和ResourceLoader</FONT></PRE><PRE><FONT color=#3333cc>三个接口，分别支持管理和操作bean的功能，语言信息的国际化支持以及对资源访问的支持。</FONT></PRE><PRE><FONT color=#3333cc>       AbstractApplicationContect是ApplicationContext的抽象实现类，它的继承层次较</FONT></PRE><PRE><FONT color=#3333cc>为紊乱，我觉得这里应该进行代码重构。AbstractXmlApplicationContext是</FONT></PRE><PRE><FONT color=#3333cc>AbstractApplicationContext的子类，提供了对XML配置文件的支持，它有三个子类，分别</FONT></PRE><PRE><FONT color=#3333cc>用于不同的应用环境。</FONT></PRE><PRE><FONT color=#3333cc>       对于MessageSource，Spring提供了两个bean实现，ResourceBundleMessageSource和</FONT></PRE><PRE><FONT color=#3333cc>ReloadableResourceBundleMessageSource。前者提供了访问Properties文件的支持，后者</FONT></PRE><PRE><FONT color=#3333cc>添加了无需重启JVM，重新加载Properties文件的支持。</FONT></PRE><PRE><FONT color=#3333cc>ApplicationContext的国际化和资源访问支持</FONT></PRE><PRE><FONT color=#3333cc>       1. 如类层次图所示，在我们的例子中，FileSystemXmlApplicationContext使用</FONT></PRE><PRE><FONT color=#3333cc>DefaultListableBeanFactory装载和解释testmsg.xml配置文件（参见代码分析的</FONT></PRE><PRE><FONT color=#3333cc>BeanFactory部分）。

       2. FileSystemXmlApplicationContext根据配置文件的BeanDefinition创建</FONT></PRE><PRE><FONT color=#3333cc>ResourceBundleMessageSource，加载&lt;list&gt;元素定义的Properties文件，并保存在</FONT></PRE><PRE><FONT color=#3333cc>AbstractApplicationContext的属性中。当客户程序调用getMessage方法时，</FONT></PRE><PRE><FONT color=#3333cc>AbstractApplicationContext调用ResourceBundleMessageSource的getMessage方法返回</FONT></PRE><PRE><FONT color=#3333cc>Message信息。
</FONT></PRE><PRE><FONT color=#3333cc>       3. 至于上节提到的MessageSource的id只能是messageSource，是因为</FONT></PRE><PRE><FONT color=#3333cc>AbstractApplicationContext的initMessageSource()方法中，有这样一段代码：</FONT></PRE><PRE><FONT color=#3333cc>                   this.messageSource = (MessageSource) 
                   getBean(MESSAGE_SOURCE_BEAN_NAME);</FONT></PRE><PRE><FONT color=#3333cc>           其中MESSAGE_SOURCE_BEAN_NAME的定义为：</FONT></PRE><PRE><FONT color=#3333cc>                   static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";</FONT></PRE><PRE><FONT color=#3333cc>           原因找到了，其实只要稍做代码重构，即可消除这个缺陷。</FONT></PRE><PRE><FONT color=#3333cc>       4. 如类层次图所示，AbstractApplicationContext继承了DefaultResourceLoader，</FONT></PRE><PRE><FONT color=#3333cc>当客户程序调用getResource方法时，使用父类中实现的方法来处理。</FONT></PRE><PRE><FONT color=#3333cc> 
ApplicationContext的事件传播</FONT></PRE><PRE><FONT color=#3333cc>准备测试用例</FONT></PRE><PRE><FONT color=#3333cc>       1. 首先编写测试用例。
           public class SenderBeanTest extends TestCase {
                ApplicationContext ctx = null;
                protected void setUp() throws Exception {
                    super.setUp();
                    ctx = new FileSystemXmlApplicationContext("testlistener.xml");
                }
                public void testSendEmail() {
                    SenderBean sender = (SenderBean)ctx.getBean("sender");
                    String msg = sender.sendMessage("test message");
                    assertEquals("test message", msg);
                }
           }</FONT></PRE><PRE><FONT color=#3333cc>       2. 接着编写testlistener.xml配置文件。
           &lt;beans&gt;
               &lt;bean id="sender" class="unittest.SenderBean"/&gt;
               &lt;bean id="listener" class="unittest.MessageListener"/&gt;
           &lt;/beans&gt;</FONT></PRE><PRE><FONT color=#3333cc>       3. 最后编写SenderBean，MessageListener和MessageEvent类。
           public class SenderBean implements ApplicationContextAware {
                  private ApplicationContext applicationContext;
                  public void setApplicationContext(ApplicationContext applicationContext)
                            throws BeansException {
                        this.applicationContext = applicationContext;
                  }
                  public String sendMessage(String msg) {
                        MessageEvent event = new MessageEvent(msg);
                        this.applicationContext.publishEvent(event);
                        return msg;
                  }
            }
 
            public class MessageListener implements ApplicationListener {
                  public void onApplicationEvent(ApplicationEvent event) {
                        if (event instanceof MessageEvent) {
                              System.out.println("I got the message:" + event.getSource());
                        }
                  }
            }
 
            public class MessageEvent extends ApplicationEvent {
                  public MessageEvent(Object source) {
                        super(source);
                        System.out.println(this.getTimestamp() + ":" + source);
                  }
            }</FONT></PRE><PRE><FONT color=#3333cc>           运行测试案例SenderBeanTest，绿条，测试通过。Console窗口出现以下DEBUG</FONT></PRE><PRE><FONT color=#3333cc>信息：</FONT></PRE><PRE><FONT color=#3333cc>           ……
           796 DEBUG support.DefaultListableBeanFactory - Returning </FONT></PRE><PRE><FONT color=#3333cc>cached instance of singleton bean 'sender'
           1085553911796:test message
           796 DEBUG support.FileSystemXmlApplicationContext - Publishing event </FONT></PRE><PRE><FONT color=#3333cc>in context [org.springframework.context.support.FileSystemXmlApplicationContext;hashCode=13549765]: </FONT></PRE><PRE><FONT color=#3333cc>unittest.MessageEvent[source=test message]
           I got the message:test message

 
事件传播的实现
       1. FileSystemXmlApplicationContext的构造器调用AbstractApplicationContext的</FONT></PRE><PRE><FONT color=#3333cc>refresh方法。如图所示，refresh方法调用refreshListeners方法。</FONT></PRE><PRE><FONT color=#3333cc>       2. AbstractApplicationContext的refreshListeners方法使用BeanFactory的</FONT></PRE><PRE><FONT color=#3333cc>getBeanOfType方法得到所有ApplicationListener类（本例中是MessageListener），并使用</FONT></PRE><PRE><FONT color=#3333cc>addListener方法把它们都放入ApplicationEventMulticasterImpl的Set容器中</FONT></PRE><PRE><FONT color=#3333cc>（eventListeners变量）。</FONT></PRE><PRE><FONT color=#3333cc>       3. 如图所示，SenderBean实现ApplicationContextAware接口，并通过</FONT></PRE><PRE><FONT color=#3333cc>setApplicationContext方法注入ApplicationContext对象实例。</FONT></PRE><PRE><FONT color=#3333cc>       4. 当调用SenderBean类sendMessage方法时，AbstractApplicationContext调用</FONT></PRE><PRE><FONT color=#3333cc>publishEvent方法。</FONT></PRE><PRE><FONT color=#3333cc>       5. AbstractApplicationContext类的publishEvent方法调用</FONT></PRE><PRE><FONT color=#3333cc>ApplicationEventMulticasterImpl类的onApplicationEvent方法。</FONT></PRE><PRE><FONT color=#3333cc>       6. ApplicationEventMulticasterImpl通知Set容器中所有的ApplicationListener</FONT></PRE><PRE><FONT color=#3333cc>对象，调用它们的onApplicationEvent方法。</FONT></PRE><PRE><FONT color=#3333cc> 
       从以上的过程可以看出，ApplicationContext将事件通知所有的</FONT></PRE><PRE><FONT color=#3333cc>ApplicationListener。如果ApplicationListener的子类（如MessageListener）只想接受</FONT></PRE><PRE><FONT color=#3333cc>指定的事件类型，需要自己编写过滤代码，如例子中的if (event instanceof MessageEvent)。</FONT></PRE><img src ="http://www.blogjava.net/jelver/aggbug/33255.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-03-02 17:09 <a href="http://www.blogjava.net/jelver/articles/33255.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring: A Developer's Notebook笔记和小结（1）</title><link>http://www.blogjava.net/jelver/articles/33251.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Thu, 02 Mar 2006 09:05:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/33251.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/33251.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/33251.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/33251.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/33251.html</trackback:ping><description><![CDATA[<H2 class=diaryTitle>Spring: A Developer's Notebook笔记和小结（1）</H2><B>关键词</B>： <A href="http://tag.bokee.com/tag/spring" target=_blank><FONT color=#002c99>spring</FONT></A> &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<P><SPAN class=tpc_content><FONT size=2>/**<BR>作者：Willpower<BR>来源：Rifoo Technology（<A href="http://www.rifoo.com/"><FONT color=#002c99>http://www.rifoo.com</FONT></A>）<BR>时间：2005-12-25<BR>备注：转载请保留以上声明<BR>**/<BR><BR>这本书是一个以代码和实战为主的书，全书在构建一个过山车订购系统，体育商店可以用来对它们的过山车进行管理和订购。第一节作者先硬编码了两个有依赖关系的类CommandLineView.java和RentABike.java。我们先看看源代码：<BR><BR></FONT><FONT size=2><B>Example 1-1. Bike.java<BR>public class Bike {<BR>&nbsp; private String manufacturer;<BR>&nbsp; private String model;<BR>&nbsp; private int frame;<BR>&nbsp; private String serialNo;<BR>&nbsp; private double weight;<BR>&nbsp; private String status;<BR><BR>&nbsp; public Bike(String manufacturer, String model, int frame, <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String serialNo, double weight, String status) {<BR><BR>&nbsp; &nbsp; this.manufacturer = manufacturer;<BR>&nbsp; &nbsp; this.model = model;<BR>&nbsp; &nbsp; this.frame = frame;<BR>&nbsp; &nbsp; this.serialNo = serialNo;<BR>&nbsp; &nbsp; this.weight = weight;<BR>&nbsp; &nbsp; this.status = status;<BR>&nbsp; }<BR><BR>&nbsp; public String toString( ) {<BR>&nbsp; &nbsp; return "Bike : " +<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "manufacturer -- " + manufacturer +<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\n: model -- " + model +<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\n: frame -- " + frame +<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\n: serialNo -- " + serialNo +<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\n: weight -- " + weight +<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\n: status -- " + status +<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ".\n";<BR>&nbsp; }<BR>&nbsp; <BR>&nbsp; public String getManufacturer( ) { return manufacturer; }<BR><BR>&nbsp; public void setManufacturer(String manufacturer) {<BR>&nbsp; &nbsp; this.manufacturer = manufacturer;<BR>&nbsp; }<BR><BR>&nbsp; public String getModel( ) { return model; }<BR><BR>&nbsp; public void setModel(String model) { this.model = model; }<BR><BR>&nbsp; public int getFrame( ) { return frame; }<BR><BR>&nbsp; public void setFrame(int frame) { this.frame = frame; }<BR><BR>&nbsp; public String getSerialNo( ) { return serialNo; }<BR><BR>&nbsp; public void setSerialNo(String serialNo) { this.serialNo = serialNo; }<BR><BR>&nbsp; public double getWeight( ) { return weight; }<BR><BR>&nbsp; public void setWeight(double weight) { this.weight = weight; }<BR><BR>&nbsp; public String getStatus( ) { return status; }<BR><BR>&nbsp; public void setStatus(String status) { this.status = status; }<BR>}</B><BR><BR>可以看出，Bike.java是一个普通的JAVABEAN，用来表述一个过山车实体，包括制造商，型号，规格，序列号，重量和状态等树型。<BR><BR></FONT><FONT size=2><B>Example 1-2. RentABike.java<BR>import java.util.*;<BR>public class RentABike {<BR><BR>&nbsp; private String storeName;<BR>&nbsp; final List bikes = new ArrayList( );<BR><BR>&nbsp; public RentABike(String storeName) {<BR>&nbsp; &nbsp; this.storeName = storeName;//商店名<BR>&nbsp; //添加过山车到数组<BR>&nbsp; &nbsp; bikes.add(new Bike("Shimano", "Roadmaster", 20, "11111", 15, <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Fair"));<BR>&nbsp; &nbsp; bikes.add(new Bike("Cannondale", "F2000 XTR", 18, "22222",12, <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Excellent"));<BR>&nbsp; &nbsp; bikes.add(new Bike("Trek","6000", 19, "33333", 12.4, <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Fair"));<BR>&nbsp; }<BR><BR>&nbsp; public String toString( ) { return "RentABike: " + storeName; }<BR>&nbsp; //得到全部过山车<BR>&nbsp; public List getBikes( ) { return bikes; }<BR>&nbsp; //得到某一个序列号的过山车<BR>&nbsp; public Bike getBike(String serialNo) {<BR>&nbsp; &nbsp; Iterator iter = bikes.iterator( );<BR>&nbsp; &nbsp; while(iter.hasNext( )) {<BR>&nbsp; &nbsp; &nbsp; &nbsp; Bike bike = (Bike)iter.next( );<BR>&nbsp; &nbsp; &nbsp; &nbsp; if(serialNo.equals(bike.getSerialNo( ))) return bike;<BR>&nbsp; &nbsp; }<BR>&nbsp; &nbsp; return null;<BR>&nbsp; }<BR>}</B><BR><BR>这个类描叙了租用一台过山车的操作，storeName是传入的商店名称。它对客户端来说是一个门面，把所租用的过山车都放在一个List数组中存放起来，然后对外提供getBikes和getBike两个方法，可以让客户端知道目前所租用的所有过山车和某一个序列号的过山车是什么。<BR><BR>我们再看看用户接口是如何调用的：<BR></FONT><FONT size=2><B>Example 1-3. CommandLineView.java<BR>import java.util.*;<BR>public class CommandLineView {<BR>&nbsp; private RentABike rentaBike;<BR>&nbsp; public CommandLineView( ) {rentaBike = new RentABike("Bruce's Bikes"); }<BR><BR>&nbsp; public void printAllBikes( ) {<BR>&nbsp; &nbsp; System.out.println(rentaBike.toString( ));<BR>&nbsp; &nbsp; //调用门面的方法<BR>&nbsp; &nbsp; Iterator iter = rentaBike.getBikes( ).iterator( );<BR>&nbsp; &nbsp; while(iter.hasNext( )) {<BR>&nbsp; &nbsp; &nbsp; &nbsp; Bike bike = (Bike)iter.next( );<BR>&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(bike.toString( ));<BR>&nbsp; &nbsp; }<BR>&nbsp; }<BR><BR>&nbsp; public static final void main(String[] args) {<BR>&nbsp; &nbsp; CommandLineView clv = new CommandLineView( );<BR>&nbsp; &nbsp; clv.printAllBikes( );<BR>&nbsp; }<BR>}</B><BR><BR><BR>运行结果：<BR><BR>C:\RentABikeApp\out&gt; java CommandLineView<BR><BR>RentABike: Bruce's Bikes<BR>Bike : manufacturer -- Shimano<BR>: model -- Roadmaster<BR>: frame -- 20<BR>: serialNo -- 11111<BR>: weight -- 15.0<BR>: status -- Fair.<BR><BR>Bike : manufacturer -- Cannondale<BR>: model -- F2000 XTR<BR>: frame -- 18<BR>: serialNo -- 22222<BR>: weight -- 12.0<BR>: status -- Excellent.<BR><BR>Bike : manufacturer -- Trek<BR>: model -- 6000<BR>: frame -- 19<BR>: serialNo -- 33333<BR>: weight -- 12.4<BR>: status -- Fair.<BR><BR>大家看出问题了吗？<BR>1 门面RentABike静态的创建了一个商店里的租用的过山车，所以到时候如果一个新的过山车被引入的话，那么就需要手工修改RentABike的代码，比如我们再加一个Bike2.java，属性和Bike.java不一样。我们还需要在RentABike的类里实例化它才行，这样就造成了硬编码<BR>2 这个模型Bike.java是很难测试的，因为Bikes数组是固定的<BR>3 这用户接口和门面之间是强耦合的，它们存在一个硬编码的依赖，大家注意CommandLineView.java中的这两行代码：<BR>private RentABike rentaBike;<BR>public CommandLineView( ) {rentaBike = new RentABike("Bruce's Bikes"); }<BR><BR>所以，这一段程序虽然能够完成一个简单的租用过山车的操作，但是却不是一个易维护和扩展的。</FONT><BR></SPAN><BR>
<P id=TBPingURL>Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=567619</P><img src ="http://www.blogjava.net/jelver/aggbug/33251.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-03-02 17:05 <a href="http://www.blogjava.net/jelver/articles/33251.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tapestry Spring Hibernate （zhuan）</title><link>http://www.blogjava.net/jelver/articles/32472.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Sun, 26 Feb 2006 02:33:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/32472.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/32472.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/32472.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/32472.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/32472.html</trackback:ping><description><![CDATA[<H2 class=diaryTitle>&nbsp;</H2>
<P>
<P>Web层的Tapestry负责数据输入输出, 响应用户事件，及输入校验的工作, 通过访问预先加载的WebApplicationContext(由Spring提供, 包含着所有Service bean)获得Service层的Service Bean, 把业务操作都委托给它们. </P>
<P>Service层的bean则负责use case逻辑, domain相关的逻辑委托给domain model中的bean去实现. Service通过DAO完成对domain model的持久化工作. Service负责数据库事务和Hibernate Session的管理(通过Spring的声明式事务管理和与之集成的Hibernate Session管理). Service层的另一项重要工作是权限和访问控制。 </P>
<P>Domain model负责表示问题域的数据和domain logic. DAO使用Hibernate持久化数据以及查询. 在实现DAO时, 我们使用了Spring的Hibernate DAO Support,极大地简化了代码, 很多方法都只用简单的一行完成. 有意思的是, 最后完成的HibernateDAO的代码量居然比我写的MockDAO的代码少了一半还多 </P>
<P>这样的架构优点很明显, 层次清晰, 各层的职责也明确, 便于分层设计与开发, 结合mock和spring的IOC, unit test也是非常容易的. 而且后台(Service, domain model and DAO)的代码不依赖于Web容器或是EJB容器的API, 移植性非常好, 同样的代码可以在Web app中使用也可在普通的Java app中使用, 只需更换UI层. </P>
<P>按照这个整合的构架，我们实现一个简单的实例，实现了列表分页查询和显示，数据增删改，基于Hibernate Criteria Query提供了一个比较通用的查询机制。利用Middlegen和Velocity我们可以从已经建好的数据库表结构自动生成Hibernate映射文件，实体类和DAO，极大地减少了工作量。我们还对这个小例子进行了压力测试（测试时的数据量为10万条记录），确定平台不存在性能问题。 </P>
<P>通过这个实例我们把整个架构基本走通一遍，并总结了使用这套架构开发时适用的开发流程和需要做的工作。 </P>
<P>困扰的问题 </P>
<P>问题1：要不要使用DTO？ <BR>在上面的架构中我们并没有明确Service和Web层间的数据传输是如何进行的。我们讨论好久要不要使用DTO，最后的结论是不用。 </P>
<P>使用DTO有两个主要的理由：<BR>1、减少Web层和Service层间的方法调用，通过一个方法调用就将Web需要的数据都传给Web。<BR>2、隔离domain model和Web层。 </P>
<P>第一个理由在当前架构下是不成立的。因为我们的架构是集中式的，Web和Service是在同一个JVM中，它们之间的方法调用是没有EJB远程访问的巨大消耗的。 <BR>第二个理由还是需要考虑的。如果允许把domain model中的对象传给Web层，那么修改domain model，就会影响到Web层。<BR>如果使用DTO，那么domain model实现上的变化就不会影响到Web。但是大量的变化不是domain model实现上的变化，而是domain model接口的变化，比如一个domain model的对象上添加了一个属性，而这个属性需要用户修改，那么这时候必须修改Web层，不管是不是用了DTO。<BR>而且使用DTO，就需要维护着一大堆对象，或是它们的生成器，这是非常无聊、且容易出错的工作。 <BR>基于这些考虑，没有必要使用DTO, 直接把domain object传给Tapestry的web层，利用Tapestry提供强大的数据绑定和组件功能很方便</P>
<P>&nbsp;</P>
<P>问题2：Entity like domain model or rich domain model? <BR>我们使用Middlegen自动生成Hibernate映射文件，Entity类和DAO类, 但是生成的Entity只含有简单的属性和getter, setter方法。<BR>因此我们遇到了一个问题：我们的domain model还要不要包含domain logic？如果包含，那么和自动生成工具如何结合？ <BR>虽然一个rich domain model可以减少Service中的重复代码，提高复用性。 但是如何同自动生成结合？<BR>或许可以使用&lt;meta&gt;标签，生成抽象基类，我们继承这些自动生成的基类，添加业务方法。<BR>但是单纯从结构的分离角度来考虑, domain model不应该包括复杂的domain logic, 只是作为一个data model bean, 再加上一些简单的logic, 比如addChild的同时，设置child的parent此类简单logic<BR>而且在POJO里面塞太多业务逻辑会导致Hibernate产生你预想不到的后果。 </P>
<P>&nbsp;</P>
<P><BR>问题3：Model driven or Data driven? <BR>这其实是一个很无聊的问题. 采用Model driven还是Data driven的方式一直都处于热烈的讨论中。我们主要是受到Rod Johnson(Expert one-on-one J2EE Design and Development 一书的作者) 的影响，采用了Data driven的方式。先作数据库设计，生成库表，然后用Middlegen反向生成Hibernate映射文件和Entity及DAO。<BR>但是在进入项目应用之后发现这种方法有可能会出现两个问题： <BR>a） 数据库设计仅说明了系统要管理的静态数据，我们还是得作面向对象分析，以反映系统的动态行为。特别是当系统的业务不仅仅是简单的CRUD操作时，这个问题更严重。 <BR>b） 数据库设计为了优化性能，可能会把好几个应该是单独实体的数据放入一个实体中。这样如果直接把这种极粗粒度实体映射成Entity类，那简直是不可接受的。<BR>面向对象的分析设计模型得到的类都是相当细粒度的。这种情况还得作面向对象的分析，明确到底这个粗粒度的大表应该映射成那几个细粒度的对象。 <BR>如果采用Model driven，则可以用AndroMDA生成domain model，Hibernate DAO，Hibernate mapping，数据库表，简单的Service和前台的Tapestry页面。 <BR>不过换个角度分析, 采用哪种设计模式只是个人习惯而已，无论是Model driven或者Data driven，对于相同的需求，2者最终的设计应该都是很类似的。<BR>更周全的做法大概可以从2边同时考虑的，一边做Model，一边还要考虑数据库的结构， 再进行相应的调整，用下来也没有什么问题。没有用代码生成， <BR>只是用Hibernate的Eclipse plugin (Hibernate Synchronizer)来帮我做一些code assist. 也可以用xDoclet来生成mapping文件和DDL.</P>
<P>&nbsp;</P>
<P>问题4：Hibernate Session生命周期如何管理？ <BR>对于Hibernate Session的生命周期我们采用的是Session-per-Transaction模式，未采用Open Session in View模式。 <BR>虽然Hibernate team认为这种方法没什么不好，而且FreeRoller和Atlassian的confluence都使用了Open Session In View这种模式，但是我们对它可能产生的影响还没有很好的把握，所以暂时弃置不用。 <BR>如果Web层要访问lazy load的数据, 需要先调用Service的业务方法, 以获得数据. 不过Open Session in View模式其实并不复杂. </P>
<P><BR>问题5：Use case logic 和 domain logic 如何区分？ <BR>Service负责use case logic，domain model负责domain logic。这样的划分看起来很好，实现起来就很麻烦。<BR>如何确定什么是use case logic，什么是domain logic？<BR>不过如果像第二个问题中最后所说, domain model里面没有什么domain logic 的话，这个问题不存在</P>
<P><BR>问题6：Service粒度如何确定？ <BR>这个问题真是很烦，原先考虑使用usecase controller的方式，每个usecase对应一个Service，但是发现这样复用性太低，而且好多地方必须复用相同的功能 <BR>另一种方法是用package level service，每个package作个service，这样倒是可以重用，但是感觉太死了，不好。 <BR>回到domain model里面没有什么domain logic的情况下，Service的功能就切得很细，尽量重用，一个package可能有多个service</P>
<P>现在也没有什么很好的办法，只好在详细设计时根据具体情况确定需要多少个Service了。TBD. </P>
<P>问题7：权限如何设定？如何检查？ <BR>权限设定也是个头疼的问题。我们本想是按照use case设定权限，每个用例一个权限。在角色设定的时候直接处理的都是业务意义非常明确的权限。<BR>但是在权限验证过程中发现了问题：如果在Service的方法中验证权限，而且这个方法在多个用例中用到（复用Service），那么这个Service的方法就需要检查多个权限; 如果每个Service方法对应一个权限, 那么权限又太细了, 不像use case权限那样代表一个完整的业务.<BR>一种考虑是将权限控制都做在Service上，权限系统的设计理念来自于Unix操作系统的权限策略，只不过我把文件和文件夹换成了Service，把组换成了Role，此外又加了一些控制对象进去，这样实现下来功能相当的强大，而且很灵活，扩展起来很方便，增加一个Service，只需要在配置文件里面设定该Service的权限级别就行了.<BR>时针对Service的权限是得自己写代码实现的，先是定义一个权限控制接口，然后写了一个抽象类继承该权限接口，把主要的代码实现都写好了，针对特定的Service不同的部分定义为一个抽象方法，其实该抽象方法也就是把类名传递过去而已。这样每个要实施权限控制的Service只要继承该抽象方法，然后在配置文件里面定义自己的权限级别就行了。就算以后再增加别的Service模块，也非常快捷，不需要动现有的代码<BR>如果结合了Spring, 在Spring里面可以使用AOP的办法针对Service增加权限控制，而不需要自己手工写.<BR>看起来手工方式还是没有上面描述的Spring控制方式优雅</P>
<P>&nbsp;</P>
<P>额外的问题: <BR>从问题5/6中再上升一步, 考虑一下DAO的做法.一种常见的用法是写一个通用的DAO类, 而是整个系统就一个DAO (PersistenceManager), 里面只有create, update, delete entity这3个方法。另外写一个DAO, 专门做查询 (QueryManager), 用hibernate的named query做常用的查询， 用criteria来做基于用户输入的动态查询.<BR>criteria 和 named query其实都是hardcode，domain object attribute name改变的时候，还得记得手工去修改这些代码，unit test很难覆盖到所有的criteria search 和 named query里面的代码.<BR>DAO是为了切换持久层API用的，准确的来说，是当你在使用JDBC来直接访问数据库的时候，由于不同的数据库的sql有差别，所以需要一个DAO来切换不同的数据库的JDBC访问代码。每个数据库的JDBC代码你都要写一套，当切换数据库的时候，就可以通过DAO来切换不同的JDBC代码实现了.<BR>是当我们使用Hibernate的时候，除了个别情况，大部分时候是不需要考虑跨数据库问题的，Hibernate已经做的足够好了。个别情况下的代码我们也可以单独做为特例处理，因此我想不到DAO的必要性了。 <BR>如果说使用DAO是为了将来切换别的O/R Mapping的话，我觉得这个话是不现实的，毕竟每种O/R Mapping的实现方式差异还是很大的，这直接影响到整个持久层设计.<BR>而当业务层代码是直接调用Hibernate API来操纵PO的，持久层就只剩下了简单的POJO了.<BR>另外一种常见用法是而在业务层针对每个POJO，写一个对他的CRUD操作的Manager类. 可以参看一下Appfuse的做法.其实这等于是在完成DAOImpl应该完成的工作，只不过现在把他归到了业务层来说罢了。然后你就可以根据你的业务逻辑来写你的业务Service了<BR>在这里，至于如何切换业务逻辑的颗粒度问题, 基于OOAD的原则，应该把无关的业务放在不同的class里面，降低类之间的耦合性，提高类的可重用度。那么根据这个原则如何切分就是一个清楚的事情了.</P>
<P><BR>(以上文字整理自洛宾,QW等N人在爪哇爱死论坛上的讨论)</P><img src ="http://www.blogjava.net/jelver/aggbug/32472.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-02-26 10:33 <a href="http://www.blogjava.net/jelver/articles/32472.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IOC和Dependency Injection</title><link>http://www.blogjava.net/jelver/articles/32340.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Fri, 24 Feb 2006 12:55:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/32340.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/32340.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/32340.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/32340.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/32340.html</trackback:ping><description><![CDATA[其实<SPAN lang=EN-US>IOC</SPAN><SPAN>模式并不是什么新的东西，它是一种很普遍的概念（或者说结构），</SPAN><SPAN lang=EN-US>GoF</SPAN><SPAN>中的</SPAN><SPAN lang=EN-US>Template Method </SPAN><SPAN>就是</SPAN><SPAN lang=EN-US>IOC</SPAN><SPAN>的结构。顾名思义，</SPAN><SPAN lang=EN-US>IOC</SPAN><SPAN>即控制反转。著名的好莱坞原则：“</SPAN><SPAN lang=EN-US>Don’t Call us, We will call you</SPAN><SPAN>”，以及</SPAN><SPAN lang=EN-US>Robert C. Martin</SPAN><SPAN>在其敏捷软件开发中所描述的依赖倒置原则（</SPAN><SPAN lang=EN-US>Dependency Inversion Principle, DIP</SPAN><SPAN>）都是这一思想的体现。</SPAN><SPAN lang=EN-US>Dependency Injection</SPAN><SPAN>是</SPAN><SPAN lang=EN-US>Martin Flower</SPAN><SPAN>对</SPAN><SPAN lang=EN-US>IOC</SPAN><SPAN>模式的一种扩展的解释，下面我们从一个简单的实例开始。</SPAN>
<P><SPAN lang=EN-US><FONT size=2></FONT></SPAN></P>
<P><FONT size=2><SPAN>考虑一个</SPAN><SPAN lang=EN-US>Button</SPAN><SPAN>来控制</SPAN><SPAN lang=EN-US>Lamp</SPAN><SPAN>的开和关。</SPAN></FONT></P>
<P><SPAN><FONT size=2>如下的类图，并写下了代码。</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2>&nbsp;</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2>public class Button {</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>private Lamp lnkLamp;</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public void poll() {</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>lnkLamp.Turnon();</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2>}</FONT></SPAN></P>
<P><FONT size=2><SPAN>但是马上发现这个设计的问题，</SPAN><SPAN lang=EN-US>Button</SPAN><SPAN>类直接依赖于</SPAN><SPAN lang=EN-US>Lamp</SPAN><SPAN>类，这个依赖关系意味着当</SPAN><SPAN lang=EN-US>Lamp</SPAN><SPAN>类修改时，</SPAN><SPAN lang=EN-US>Button</SPAN><SPAN>类会受到影响。此外，想重用</SPAN><SPAN lang=EN-US>Button</SPAN><SPAN>类来控制类似与</SPAN><SPAN lang=EN-US>Lamp</SPAN><SPAN>的另外一个对象则是不可能的。即</SPAN><SPAN lang=EN-US>Button</SPAN><SPAN>控制</SPAN><SPAN lang=EN-US>Lamp</SPAN><SPAN>，并且只能控制</SPAN><SPAN lang=EN-US>Lamp</SPAN><SPAN>。</SPAN></FONT></P>
<P><FONT size=2><SPAN>显然，我违反了“高层模块不应该依赖于底层模块，两者都应该依赖于抽象；抽象不应该依赖于具体实现，细节应该依赖于抽象”</SPAN> <SPAN>这一原则（</SPAN><SPAN lang=EN-US>DIP</SPAN><SPAN>原则）。</SPAN></FONT></P>
<P><FONT size=2><SPAN>考虑到上述问题，自然地想到应该抽象出一个接口，来消除</SPAN><SPAN lang=EN-US>Button</SPAN><SPAN>对</SPAN><SPAN lang=EN-US>Lamp</SPAN></FONT><SPAN><FONT size=2>的依赖，于是设计如下：<BR></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2></FONT></SPAN></P>
<P><SPAN><BR><FONT size=2>&nbsp;&nbsp;&nbsp; 这样，我们倒置了</FONT></SPAN><FONT size=2><SPAN lang=EN-US>Button</SPAN><SPAN>对</SPAN><SPAN lang=EN-US>Lamp</SPAN><SPAN>的依赖关系，使得</SPAN><SPAN lang=EN-US>Lamp</SPAN><SPAN>依赖于</SPAN><SPAN lang=EN-US>SwitchableDevice</SPAN><SPAN>接口，</SPAN><SPAN lang=EN-US>SwitchableDevice</SPAN><SPAN>并没有依赖于</SPAN><SPAN lang=EN-US>Button</SPAN><SPAN>类，任何知道如何操纵该接口的对象都可以控制</SPAN><SPAN lang=EN-US>Lamp</SPAN><SPAN>。同时</SPAN><SPAN lang=EN-US>Button</SPAN><SPAN>不只是可以控制</SPAN><SPAN lang=EN-US>Lamp</SPAN><SPAN>，还可以控制同样实现</SPAN><SPAN lang=EN-US>SwitchableDevice</SPAN><SPAN>接口的如</SPAN><SPAN lang=EN-US>Computer</SPAN><SPAN>、</SPAN><SPAN lang=EN-US>Cell Phone</SPAN><SPAN>等等。回头想想，这种做法好像似曾相识，拍拍脑袋，哦！这不是</SPAN><SPAN lang=EN-US>GoF</SPAN><SPAN>策略（</SPAN><SPAN lang=EN-US>Strategy</SPAN><SPAN>）模式吗？！正是，不经意间我就应用了设计模式（有点得意哦</SPAN><SPAN lang=EN-US>~~~~</SPAN><SPAN>）。</SPAN></FONT></P>
<P><FONT size=2><SPAN>现在再来考虑一个问题，刚才的做法虽然倒置了依赖关系，但是如果将</SPAN><SPAN lang=EN-US>Button</SPAN><SPAN>作为一个应用程序来控制</SPAN><SPAN lang=EN-US>Lamp</SPAN><SPAN>或者同样实现</SPAN><SPAN lang=EN-US>SwitchableDevice</SPAN><SPAN>的</SPAN><SPAN lang=EN-US>Computer</SPAN><SPAN>、</SPAN><SPAN lang=EN-US>Cell Phone</SPAN><SPAN>等，则代码可能如下：</SPAN></FONT></P>
<P><SPAN lang=EN-US><FONT size=2>public class Button {</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2>private SwitchableDevice lnkLamp;</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2>public Button(){</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>lnkLamp= new Lamp();</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2>}</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2>…</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2>}</FONT></SPAN></P>
<P><FONT size=2><SPAN>也就是说</SPAN><SPAN lang=EN-US>Button</SPAN><SPAN>和</SPAN><SPAN lang=EN-US>Lamp</SPAN><SPAN>之间仍然存在《</SPAN><SPAN lang=EN-US>creates</SPAN><SPAN>》这样的依赖关系。</SPAN></FONT></P>
<P><FONT size=2><SPAN>为了解除这种依赖关系，首先看</SPAN><SPAN lang=EN-US>GoF</SPAN><SPAN>能作些什么。显然，这个地方应该用</SPAN><SPAN lang=EN-US>Factory</SPAN><SPAN>模式，将对象的创建交给</SPAN><SPAN lang=EN-US>Factory Class</SPAN><SPAN>来处理，这样虽然解开了</SPAN><SPAN lang=EN-US>Lamp</SPAN><SPAN>组件与我们应用程序</SPAN><SPAN lang=EN-US>Button</SPAN><SPAN>之间的耦合关系，但是组件的创建仍然是显式的（</SPAN><SPAN lang=EN-US>explicitly</SPAN><SPAN>），在组件更改时仍需要重新编译。</SPAN></FONT></P>
<P><FONT size=2><SPAN>另外，通过一个</SPAN><SPAN lang=EN-US>ServiceLocator</SPAN><SPAN>去</SPAN><SPAN lang=EN-US>look up</SPAN><SPAN>实现类也是一种解除耦合的办法，看到这儿，你不禁会想</SPAN><SPAN lang=EN-US>EJB</SPAN><SPAN>不就是这么实现的嘛，</SPAN><SPAN lang=EN-US>U are Right! <SPAN>Rod Johnson</SPAN>&nbsp;</SPAN><SPAN>在其大作</SPAN><SPAN lang=EN-US>J2EE without EJB</SPAN><SPAN>中称这种方式为</SPAN><SPAN lang=EN-US>Dependency Look up</SPAN><SPAN>，但这种方式也有其弊端，比如无法脱离容器环境，以及不利于</SPAN><SPAN lang=EN-US>Unit test</SPAN><SPAN>等。</SPAN></FONT></P>
<P><FONT size=2><SPAN>“</SPAN><SPAN lang=EN-US>Don’t Call us, We will Call you</SPAN><SPAN>”，这个原则启示我们应该换一个思路，不应该在应用类中创建具体对象的实例，而是应该将具体对象实例的创建插入</SPAN><SPAN lang=EN-US>(plug)</SPAN><SPAN>或者说注射（</SPAN><SPAN lang=EN-US>inject</SPAN><SPAN>）到应用类中，这大概是依赖注射名称的由来吧。</SPAN></FONT></P>
<P><FONT size=2><SPAN>这种实现方式需要在应用类以及调用组件之间建立一个</SPAN><SPAN lang=EN-US>assembler</SPAN><SPAN>来解除两者之间的依赖，看起来与前面的方式没有太大区别，来看一下结构：</SPAN></FONT></P>
<P><SPAN lang=EN-US><FONT size=2></FONT></SPAN></P>
<P><SPAN><BR><FONT size=2>&nbsp;&nbsp;&nbsp; 仔细查看会发现还是有比较大的不同，依赖关系是相反的，也就是说这个过程中依然倒置了依赖关系。</FONT></SPAN><FONT size=2><SPAN lang=EN-US>Lamp</SPAN><SPAN>通过</SPAN><SPAN lang=EN-US>Assembler</SPAN><SPAN>将其创建过程注射到了</SPAN><SPAN lang=EN-US>Button</SPAN><SPAN>中，从而消除了两者之间的耦合，增加了灵活性。</SPAN></FONT></P>
<P><FONT size=2><SPAN>下面我们看一下具体的实现，在</SPAN><SPAN lang=EN-US>PicoContainer</SPAN><SPAN>以及</SPAN><SPAN lang=EN-US>Spring</SPAN><SPAN>中有着其不同的实现，分别代表了两种类型的</SPAN><SPAN lang=EN-US>Dependency Injection, </SPAN><SPAN>即</SPAN><SPAN lang=EN-US>Constructor Injection </SPAN><SPAN>和</SPAN><SPAN lang=EN-US>Setter Injection</SPAN><SPAN>。</SPAN></FONT></P>
<P><SPAN lang=EN-US><FONT size=2>private MutablePicoContainer configureContainer() {</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>MutablePicoContainer pico = new DefaultPicoContainer();</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>pico.registerComponentImplementation(SwitchableDevice.class, Lamp.class);</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>pico.registerComponentImplementation(Button.class);</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>return pico;</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT size=2>}</FONT></SPAN></P>
<P><FONT size=2><SPAN>然后可以通过</SPAN><SPAN lang=EN-US>MutablePicoContainer</SPAN><SPAN>的</SPAN><SPAN lang=EN-US>getComponentImplementation</SPAN><SPAN>方法获得实现类，调用其</SPAN><SPAN lang=EN-US>poll</SPAN><SPAN>方法控制</SPAN><SPAN lang=EN-US>Lamp</SPAN><SPAN>的开关，这样一来，两者之间的耦合通过</SPAN><SPAN lang=EN-US>PicoContainer</SPAN><SPAN>提供的</SPAN><SPAN lang=EN-US>Assembler</SPAN><SPAN>完全消除了。</SPAN></FONT></P>
<P><FONT size=2><SPAN lang=EN-US>Spring</SPAN><SPAN>则通过一个</SPAN><SPAN lang=EN-US>XML</SPAN><SPAN>格式的配置文件，将两者联系起来，使用时，通过</SPAN><SPAN lang=EN-US>ApplicationContext</SPAN><SPAN>获得</SPAN><SPAN lang=EN-US>Button Bean</SPAN><SPAN>，再调用其方法实现，同样也消除了耦合关系</SPAN></FONT></P><img src ="http://www.blogjava.net/jelver/aggbug/32340.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-02-24 20:55 <a href="http://www.blogjava.net/jelver/articles/32340.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Spring中IOC的实现 (转)</title><link>http://www.blogjava.net/jelver/articles/32339.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Fri, 24 Feb 2006 12:53:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/32339.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/32339.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/32339.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/32339.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/32339.html</trackback:ping><description><![CDATA[<BR>
<DIV><FONT size=2><SPAN><SPAN style="FONT-SIZE: 14pt">
<DIV>
<P><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 了解了</SPAN><FONT face=宋体><SPAN lang=EN-US>IOC</SPAN><SPAN>模式的思想以及其优点，再来学习其实现。上篇</SPAN><SPAN lang=EN-US>blog</SPAN><SPAN>中大致描述了</SPAN><SPAN lang=EN-US>PicoContainer</SPAN><SPAN>以及</SPAN><SPAN lang=EN-US>Spring</SPAN><SPAN>各自对</SPAN><SPAN lang=EN-US>IOC</SPAN><SPAN>的实现，这篇来详细看一下</SPAN><SPAN lang=EN-US>Spring</SPAN><SPAN>中它的实现。</SPAN></FONT></FONT></P>
<P><FONT face=宋体><FONT size=2><SPAN lang=EN-US>Spring</SPAN><SPAN>中</SPAN><SPAN lang=EN-US>IOC</SPAN><SPAN>贯穿了其整个框架，但正如</SPAN><SPAN lang=EN-US>martinflower</SPAN><SPAN>所说：“</SPAN><SPAN lang=EN-US>saying that these lightweight containers are special because they use inversion of control is like saying my car is special because it has wheels</SPAN><SPAN>”，</SPAN><SPAN lang=EN-US>IOC</SPAN><SPAN>已经称为框架设计中必不可少的部分。就实现上来讲</SPAN><SPAN lang=EN-US>Spring</SPAN><SPAN>采取了配置文件的形式来实现依赖的注射，并且支持</SPAN><SPAN lang=EN-US>Type2 IOC</SPAN><SPAN>（</SPAN><SPAN lang=EN-US>Setter Injection</SPAN><SPAN>）以及</SPAN><SPAN lang=EN-US>Type3 IOC</SPAN><SPAN>（</SPAN><SPAN lang=EN-US>Constructor Injection</SPAN><SPAN>）。</SPAN></FONT></FONT></P>
<P align=left><FONT face=宋体><FONT size=2><SPAN lang=EN-US>&nbsp;&nbsp;&nbsp;&nbsp; Spring</SPAN><SPAN>中</SPAN><SPAN lang=EN-US>IOC</SPAN><SPAN>的实现的核心是其</SPAN><SPAN lang=EN-US>Core Bean Factory</SPAN><SPAN>，它将框架内部的组件以一定的耦合度组装起来，并对使用它的应用提供一种面向服务的编程模式</SPAN><SPAN lang=EN-US>(SOP</SPAN><SPAN>：</SPAN><SPAN lang=EN-US>Service-Orient Programming)</SPAN><SPAN>，比如</SPAN><SPAN lang=EN-US>Spring</SPAN><SPAN>中的</SPAN><SPAN lang=EN-US>AOP</SPAN><SPAN>、以及持久化（</SPAN><SPAN lang=EN-US>Hibernate</SPAN><SPAN>、</SPAN><SPAN lang=EN-US>ibatics</SPAN><SPAN>）的实现。</SPAN></FONT></FONT><SPAN lang=EN-US><BR><SPAN><FONT face=宋体 size=2>&nbsp;&nbsp;&nbsp; </FONT></SPAN><FONT size=2><SPAN>首先从最底层最基础的</SPAN><FONT face=宋体><SPAN lang=EN-US>factory Bean</SPAN><SPAN>开始，先来看</SPAN><SPAN lang=EN-US>org.springframework.beans.factory.Bean</SPAN></FONT></FONT></P>
<P align=left><FONT face=宋体><FONT size=2><SPAN lang=EN-US>Factory</SPAN><SPAN>接口，它是一个非常简单的接口，</SPAN><SPAN lang=EN-US>getBean</SPAN><SPAN>方法是其中最重要的方法，</SPAN><SPAN lang=EN-US>Spring</SPAN><SPAN>通常是使用</SPAN><SPAN lang=EN-US>xml</SPAN><SPAN>来</SPAN><SPAN lang=EN-US>populate Bean</SPAN><SPAN>，所以比较常用的是</SPAN><SPAN lang=EN-US>XMLFactoryBean</SPAN></FONT><FONT size=2><SPAN>。<BR></SPAN></FONT></FONT></P>
<P align=left><SPAN><BR><FONT size=2>用一个简单的示例看一下其用法。首先写下两个</FONT></SPAN><FONT face=宋体><FONT size=2><SPAN lang=EN-US>Bean</SPAN><SPAN>类：</SPAN></FONT></FONT></P>
<P align=left><FONT face=宋体><FONT size=2><SPAN lang=EN-US>ExampleBean </SPAN><SPAN>类：<BR></SPAN></FONT></FONT><SPAN lang=EN-US><FONT face=宋体><FONT size=2>public class ExampleBean {<BR><BR></FONT></FONT></SPAN><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN>private String psnName=null;</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>private RefBean refbean=null;</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>private String addinfo=null;</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2></FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public String getAddinfo() {</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>return getRefbean().getAddress()+getRefbean().getZipcode();</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public String getPsnName() {</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>return psnName;</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public void setPsnName(String psnName) {</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>this.psnName = psnName;</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public void setRefbean(RefBean refbean) {</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>this.refbean = refbean;</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public RefBean getRefbean() {</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>return refbean;</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</FONT></FONT></SPAN></P>
<P align=left><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public void setAddinfo(String addinfo) {<BR></FONT></FONT></SPAN><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>this.addinfo = addinfo;<BR></FONT></FONT></SPAN><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}<BR></FONT></FONT></SPAN><FONT face=宋体><FONT size=2><SPAN lang=EN-US>}<BR><BR>RefBean</SPAN><SPAN>类：</SPAN></FONT></FONT></P>
<P><SPAN lang=EN-US><FONT face=宋体 size=2>public class RefBean {</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public String getAddress() {</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>return address;</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public void setAddress(String address) {</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>this.address = address;</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public String getZipcode() {</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>return zipcode;</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public void setZipcode(String zipcode) {</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>this.zipcode = zipcode;</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>private String zipcode=null;</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>private String address=null;</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体 size=2>}<BR></FONT></SPAN></P>
<P><SPAN><BR><FONT size=2>其</FONT></SPAN><FONT face=宋体><FONT size=2><SPAN lang=EN-US>xml</SPAN><SPAN>配置文件</SPAN><SPAN lang=EN-US> Bean.xml </SPAN></FONT></FONT></P><FONT face=宋体><SPAN lang=EN-US><SPAN style="FONT-SIZE: 12pt">
<P align=left><FONT face=宋体><SPAN lang=EN-US>&lt;?xml version="1.0" encoding="UTF-8"?&gt;</SPAN></FONT></P>
<P align=left><FONT face=宋体><SPAN lang=EN-US>&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"</SPAN></FONT></P>
<P align=left><FONT face=宋体><SPAN lang=EN-US>"http://www.springframework.org/dtd/spring-beans.dtd"&gt;</SPAN></FONT></P>
<P align=left><FONT face=宋体><SPAN lang=EN-US>&lt;beans&gt;</SPAN></FONT></P>
<P align=left><FONT face=宋体><SPAN lang=EN-US><SPAN>&nbsp; </SPAN>&lt;bean id="exampleBean" class="test.ExampleBean"&gt;</SPAN></FONT></P>
<P align=left><FONT face=宋体><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>&lt;property name="psnName"&gt;&lt;value&gt;xkf&lt;/value&gt;&lt;/property&gt;</SPAN></FONT></P>
<P align=left><FONT face=宋体><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>&lt;property name="refbean"&gt;</SPAN></FONT></P>
<P align=left><FONT face=宋体><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;ref bean="refBean"/&gt;</SPAN></FONT></P>
<P align=left><FONT face=宋体><SPAN lang=EN-US><SPAN>&nbsp;&nbsp;&nbsp; </SPAN>&lt;/property&gt;</SPAN></FONT></P>
<P align=left><FONT face=宋体><SPAN lang=EN-US><SPAN>&nbsp; </SPAN>&lt;/bean&gt;</SPAN></FONT></P>
<P align=left><FONT face=宋体><SPAN lang=EN-US><SPAN>&nbsp; </SPAN>&lt;bean id="refBean" class="test.RefBean"&gt;</SPAN></FONT></P>
<P align=left><FONT face=宋体><SPAN lang=EN-US><SPAN>&nbsp; </SPAN>&lt;property name="address"&gt;&lt;value&gt;BeiJing&lt;/value&gt;&lt;/property&gt;</SPAN></FONT></P>
<P align=left><FONT face=宋体><SPAN lang=EN-US><SPAN>&nbsp; </SPAN>&lt;property name="zipcode"&gt;&lt;value&gt;100085&lt;/value&gt;&lt;/property&gt;</SPAN></FONT></P>
<P align=left><FONT face=宋体><SPAN lang=EN-US><SPAN>&nbsp; </SPAN>&lt;/bean&gt;</SPAN></FONT></P>
<P><FONT face=宋体><SPAN lang=EN-US>&lt;/beans&gt;</SPAN></FONT></P></SPAN></SPAN></FONT>
<P><SPAN lang=EN-US><FONT face=宋体>&nbsp;</FONT></SPAN></P>
<P><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;然后可以写个测试类来测试，当然，需要</SPAN><FONT face=宋体><SPAN lang=EN-US>Spring</SPAN><SPAN>中的</SPAN><SPAN lang=EN-US>Spring-core.jar</SPAN><SPAN>以及</SPAN><SPAN lang=EN-US>commons-logging.jar</SPAN><SPAN>，当然在</SPAN><SPAN lang=EN-US>elipse</SPAN><SPAN>中可以通过安装</SPAN><SPAN lang=EN-US>spring-ide</SPAN><SPAN>插件来轻松实现。</SPAN></FONT></FONT></P>
<P><SPAN lang=EN-US><FONT face=宋体 size=2>public class Test {</FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public static void main(String[] args){</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>try{</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>Resource input = new ClassPathResource("test/Bean.xml");</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>System.out.println("resource is:"+input);</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>BeanFactory factory = new XmlBeanFactory(input);</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>ExampleBean eb =</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>(ExampleBean)factory.getBean("exampleBean");</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>System.out.println(eb.getPsnName());</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>System.out.println(eb.getAddinfo());</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>catch(Exception e){</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>e.printStackTrace();</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体><FONT size=2><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</FONT></FONT></SPAN></P>
<P><SPAN lang=EN-US><FONT face=宋体 size=2>}<BR></FONT></SPAN></P><SPAN><BR><FONT size=2>&nbsp;&nbsp;&nbsp;&nbsp; 这样，通过</FONT></SPAN><FONT face=宋体><FONT size=2><SPAN lang=EN-US>BeanFactory</SPAN><SPAN>的</SPAN><SPAN lang=EN-US>getBean</SPAN><SPAN>方法，以及</SPAN><SPAN lang=EN-US>xml</SPAN><SPAN>配置文件，避免了在</SPAN><SPAN lang=EN-US>test</SPAN><SPAN>类中直接实例化</SPAN><SPAN lang=EN-US>ExampleBean</SPAN><SPAN>，消除了应用程序</SPAN><SPAN lang=EN-US>(Test)</SPAN><SPAN>与服务</SPAN><SPAN lang=EN-US>(ExampleBean)</SPAN><SPAN>之间的耦合，实现了</SPAN><SPAN lang=EN-US>IOC</SPAN><SPAN>（控制反转）或者说实现了依赖的注射（</SPAN><SPAN lang=EN-US>Dependency Injection</SPAN><SPAN>）。</SPAN></FONT></FONT></SPAN></DIV></SPAN></SPAN></FONT></DIV><img src ="http://www.blogjava.net/jelver/aggbug/32339.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-02-24 20:53 <a href="http://www.blogjava.net/jelver/articles/32339.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Acegi作为基于Spring框架的WEB应用的安全框架(zhuan)</title><link>http://www.blogjava.net/jelver/articles/32266.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Fri, 24 Feb 2006 03:12:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/32266.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/32266.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/32266.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/32266.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/32266.html</trackback:ping><description><![CDATA[<H2>实战Acegi：使用Acegi作为基于Spring框架的WEB应用的安全框架<BR>&nbsp;source:http://www.blogjava.net/youlq/archive/2005/12/06/22678.html</H2>
<P>最近项目使用Acegi作为安全框架的实现,效果不错,就写了这篇文章作为总结.<BR><BR>对于任何一个完整的应用系统，完善的认证和授权机制是必不可少的。在基于SpringFramework的WEB应用中，<BR>我们可以使用Acegi作为安全架构的实现。本文将介绍如何在基于Spring构架的Web应用中使用Acegi，并且详细介<BR>绍如何配置和扩展Acegi框架以适应实际需要。<BR></P>
<P>文章和代码下载:<BR><BR><A HREF="/Files/youlq/Acegi.zip"><FONT color=#000080>http://www.blogjava.net/Files/youlq/Acegi.zip</FONT></A><BR><BR><BR><STRONG><FONT color=#ff0000>注意：许多朋友在部署上遇到一些麻烦，所以我将可以部署的完整的war文件传上来，注意：java代码在acegi-sample.war\WEB-INF 目录下，例子需要Mysql，建库脚本在acegi-sample.war\db目录下。</FONT></STRONG><BR><BR><A HREF="/Files/youlq/acegi-sample.part1.rar"><FONT color=#002c99>acegi-sample.part1.rar</FONT></A><BR><A HREF="/Files/youlq/acegi-sample.part2.rar"><FONT color=#002c99>acegi-sample.part2.rar</FONT></A><BR><A HREF="/Files/youlq/acegi-sample.part3.rar"><FONT color=#002c99>acegi-sample.part3.rar</FONT></A><BR><A HREF="/Files/youlq/acegi-sample.part4.rar"><FONT color=#002c99>acegi-sample.part4.rar</FONT></A><BR><BR>附注：<BR><BR>有些朋友询问我如何部署文中的例子，在此再次说明一下（文章中已经有提到）：<BR><BR>Mysql的建表脚本在db目录下<BR>为了减小体积，已经将WEB-INF\lib下的依赖包删除，请自行下载以下包，并拷贝至WEB-INF\lib下：<BR>spring-1.2.4.jar<BR>acegi-security-0.8.3.jar<BR>aopalliance-1.0.jar<BR>c3p0-0.9.0.jar<BR>commons-logging-1.0.4.jar<BR>ehcache-1.1.jar<BR>log4j-1.2.8.jar<BR>mysql-connector-java-3.1.10-bin.jar<BR>oro-2.0.8.jar<BR><BR>提示：<BR>acegi-security-0.8.3.jar<BR>aopalliance-1.0.jar<BR>c3p0-0.9.0.jar<BR>commons-logging-1.0.4.jar<BR>ehcache-1.1.jar<BR>log4j-1.2.8.jar<BR>oro-2.0.8.jar<BR>可以在acegi-security-0.8.3.zip所带的acegi-security-sample-contacts-filter.war中找到。<BR>spring-1.2.4.jar<BR>mysql-connector-java-3.1.10-bin.jar<BR>要分别到springframework和mysql网站下载。</P><img src ="http://www.blogjava.net/jelver/aggbug/32266.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-02-24 11:12 <a href="http://www.blogjava.net/jelver/articles/32266.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用Acegi为你的Spring应用加把锁！(zhuan)</title><link>http://www.blogjava.net/jelver/articles/32263.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Fri, 24 Feb 2006 03:06:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/32263.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/32263.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/32263.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/32263.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/32263.html</trackback:ping><description><![CDATA[<P><STRONG><FONT color=#0000ff><A href="http://www.blogcn.com.cn/user1/2313/archives/2005/11791.shtml">http://www.blogcn.com.cn/user1/2313/archives/2005/11791.shtml</A><BR>{简介]</FONT></STRONG> <BR><FONT size=2>对于一个典型的Web应用，完善的认证和授权机制是必不可少的，在SpringFramework中，Juergen Hoeller提供的范例JPetStore给了一些这方面的介绍，但还远远不够，Acegi是一个专门为SpringFramework提供安全机制的 项目，全称为Acegi Security System for Spring，当前版本为0.5.1，就其目前提供的功能，应该可以满足绝大多数应用的需求。 <BR><BR>本文的主要目的是希望能够说明如何在基于Spring构架的Web应用中使用Acegi，而不是详细介绍其中的每个接口、每个类。注意，即使对已经存在的Spring应用，通过下面介绍的步骤，也可以马上享受到Acegi提供的认证和授权。</FONT> <BR><FONT color=#0000ff><BR><B>[基础工作]</B></FONT> <BR><FONT size=2>在你的Web应用的lib中添加Acegi下载包中的acegi-security.jar</FONT> <BR><BR><FONT color=#0000ff><B>[web.xml]</B></FONT> <BR><FONT size=2>实现认证和授权的最常用的方法是通过filter，Acegi亦是如此，通常Acegi需要在web.xml添加以下5个filter:</FONT> <BR><FONT size=2><BR><FONT color=#800080>&lt;filter&gt; <BR>&nbsp; &lt;filter-name&gt;Acegi Channel Processing Filter&lt;/filter-name&gt; <BR>&nbsp; &lt;filter-class&gt;net.sf.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt; <BR>&nbsp; &lt;init-param&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;param-name&gt;targetClass&lt;/param-name&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;param-value&gt;net.sf.acegisecurity.securechannel.ChannelProcessingFilter&lt;/param-value&gt; <BR>&nbsp; &lt;/init-param&gt; <BR>&lt;/filter&gt; <BR>&lt;filter&gt; <BR>&nbsp; &lt;filter-name&gt;Acegi Authentication Processing Filter&lt;/filter-name&gt; <BR>&nbsp; &lt;filter-class&gt;net.sf.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt; <BR>&nbsp; &lt;init-param&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;param-name&gt;targetClass&lt;/param-name&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;param-value&gt;net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter&lt;/param-value&gt; <BR>&nbsp; &lt;/init-param&gt; <BR>&lt;/filter&gt; <BR>&lt;filter&gt; <BR>&nbsp; &lt;filter-name&gt;Acegi HTTP BASIC Authorization Filter&lt;/filter-name&gt; <BR>&nbsp; &lt;filter-class&gt;net.sf.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt; <BR>&nbsp; &lt;init-param&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;param-name&gt;targetClass&lt;/param-name&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;param-value&gt;net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter&lt;/param-value&gt; <BR>&nbsp; &lt;/init-param&gt; <BR>&lt;/filter&gt; <BR>&lt;filter&gt; <BR>&nbsp; &lt;filter-name&gt;Acegi Security System for Spring Auto Integration Filter&lt;/filter-name&gt; <BR>&nbsp; &lt;filter-class&gt;net.sf.acegisecurity.ui.AutoIntegrationFilter&lt;/filter-class&gt; <BR>&lt;/filter&gt; <BR>&lt;filter&gt; <BR>&nbsp; &lt;filter-name&gt;Acegi HTTP Request Security Filter&lt;/filter-name&gt; <BR>&nbsp; &lt;filter-class&gt;net.sf.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt; <BR>&nbsp; &lt;init-param&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;param-name&gt;targetClass&lt;/param-name&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;param-value&gt;net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter&lt;/param-value&gt; <BR>&nbsp; &lt;/init-param&gt; <BR>&lt;/filter&gt; <BR></FONT><BR>最先引起迷惑的是net.sf.acegisecurity.util.FilterToBeanProxy，Acegi自己的文档上解释是： “What&nbsp; FilterToBeanProxy does is delegate the Filter's methods through to a bean which is obtained from the <BR>Spring application context. This enables the bean to benefit from the Spring application context lifecycle support and configuration flexibility.”，如希望深究的话，去看看源代码应该不难理解。 <BR><BR>再下来就是添加filter-mapping了： <BR><FONT color=#800080>&lt;filter-mapping&gt; <BR>&nbsp; &lt;filter-name&gt;Acegi Channel Processing Filter&lt;/filter-name&gt; <BR>&nbsp; &lt;url-pattern&gt;/*&lt;/url-pattern&gt; <BR>&lt;/filter-mapping&gt; <BR>&lt;filter-mapping&gt; <BR>&nbsp; &lt;filter-name&gt;Acegi Authentication Processing Filter&lt;/filter-name&gt; <BR>&nbsp; &lt;url-pattern&gt;/*&lt;/url-pattern&gt; <BR>&lt;/filter-mapping&gt; <BR>&lt;filter-mapping&gt; <BR>&nbsp; &lt;filter-name&gt;Acegi HTTP BASIC Authorization Filter&lt;/filter-name&gt; <BR>&nbsp; &lt;url-pattern&gt;/*&lt;/url-pattern&gt; <BR>&lt;/filter-mapping&gt; <BR>&lt;filter-mapping&gt; <BR>&nbsp; &lt;filter-name&gt;Acegi Security System for Spring Auto Integration Filter&lt;/filter-name&gt; <BR>&nbsp; &lt;url-pattern&gt;/*&lt;/url-pattern&gt; <BR>&lt;/filter-mapping&gt; <BR>&lt;filter-mapping&gt; <BR>&nbsp; &lt;filter-name&gt;Acegi HTTP Request Security Filter&lt;/filter-name&gt; <BR>&nbsp; &lt;url-pattern&gt;/*&lt;/url-pattern&gt; <BR>&lt;/filter-mapping&gt; <BR></FONT><BR>这里，需要注意以下两点： <BR>1) 这几个filter的顺序是不能更改的，顺序不对将无法正常工作； <BR>2) 如果你的应用不需要安全传输，如https，则将"Acegi Channel Processing Filter"相关内容注释掉即可； <BR>3) 如果你的应用不需要Spring提供的远程访问机制，如Hessian and Burlap，将"Acegi HTTP BASIC Authorization <BR>Filter"相关内容注释掉即可。 <BR><BR><B><FONT color=#0000ff size=3>[applicationContext.xml]</FONT></B> <BR>接下来就是要添加applicationContext.xml中的内容了，从刚才FilterToBeanFactory的解释可以看出，真正的filter都 <BR>在Spring的applicationContext中管理： <BR><BR>1) 首先，你的数据库中必须具有保存用户名和密码的table，Acegi要求table的schema必须如下： <BR><BR><FONT color=#800080>CREATE TABLE users ( <BR>&nbsp;&nbsp; &nbsp;username VARCHAR(50) NOT NULL PRIMARY KEY, <BR>&nbsp;&nbsp; &nbsp;password VARCHAR(50) NOT NULL, <BR>&nbsp;&nbsp; &nbsp;enabled BIT NOT NULL <BR>); <BR>CREATE TABLE authorities ( <BR>&nbsp;&nbsp; &nbsp;username VARCHAR(50) NOT NULL, <BR>&nbsp;&nbsp; &nbsp;authority VARCHAR(50) NOT NULL <BR>); <BR>CREATE UNIQUE INDEX ix_auth_username ON authorities ( username, authority ); <BR>ALTER TABLE authorities ADD CONSTRAINT fk_authorities_users foreign key (username) REFERENCES users <BR>(username); <BR></FONT><BR>2) 添加访问你的数据库的datasource和Acegi的jdbcDao，如下： <BR><BR><FONT color=#800080>&lt;bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt; <BR>&nbsp; &lt;property name="driverClassName"&gt;&lt;value&gt;${jdbc.driverClassName}&lt;/value&gt;&lt;/property&gt; <BR>&nbsp; &lt;property name="url"&gt;&lt;value&gt;${jdbc.url}&lt;/value&gt;&lt;/property&gt; <BR>&nbsp; &lt;property name="username"&gt;&lt;value&gt;${jdbc.username}&lt;/value&gt;&lt;/property&gt; <BR>&nbsp; &lt;property name="password"&gt;&lt;value&gt;${jdbc.password}&lt;/value&gt;&lt;/property&gt; <BR>&lt;/bean&gt; <BR>&lt;bean id="jdbcDaoImpl" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl"&gt; <BR>&nbsp; &lt;property name="dataSource"&gt;&lt;ref bean="dataSource"/&gt;&lt;/property&gt; <BR>&lt;/bean&gt;</FONT> <BR><BR>3) 添加DaoAuthenticationProvider: <BR><BR><FONT color=#800080>&lt;bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"&gt; <BR>&nbsp; &lt;property name="authenticationDao"&gt;&lt;ref bean="authenticationDao"/&gt;&lt;/property&gt; <BR>&nbsp; &lt;property name="userCache"&gt;&lt;ref bean="userCache"/&gt;&lt;/property&gt; <BR>&lt;/bean&gt; <BR><BR>&lt;bean id="userCache" class="net.sf.acegisecurity.providers.dao.cache.EhCacheBasedUserCache"&gt; <BR>&nbsp; &lt;property name="minutesToIdle"&gt;&lt;value&gt;5&lt;/value&gt;&lt;/property&gt; <BR>&lt;/bean&gt;</FONT> <BR><BR>如果你需要对密码加密，则在daoAuthenticationProvider中加入：&lt;property name="passwordEncoder"&gt;&lt;ref <BR>bean="passwordEncoder"/&gt;&lt;/property&gt;，Acegi提供了几种加密方法，详细情况可看包 <BR>net.sf.acegisecurity.providers.encoding <BR><BR>4) 添加authenticationManager: <BR><BR><FONT color=#800080>&lt;bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager"&gt; <BR>&nbsp; &lt;property name="providers"&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;list&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref bean="daoAuthenticationProvider"/&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;/list&gt; <BR>&nbsp;&nbsp; &lt;/property&gt; <BR>&lt;/bean&gt;</FONT> <BR><BR>5) 添加accessDecisionManager: <BR><BR><FONT color=#800080>&lt;bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased"&gt; <BR>&nbsp; &lt;property name="allowIfAllAbstainDecisions"&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;value&gt;false&lt;/value&gt; <BR>&nbsp; &lt;/property&gt; <BR>&nbsp; &lt;property name="decisionVoters"&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;list&gt;&lt;ref bean="roleVoter"/&gt;&lt;/list&gt; <BR>&nbsp; &lt;/property&gt; <BR>&lt;/bean&gt; <BR>&lt;bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/&gt; <BR></FONT><BR>6) 添加authenticationProcessingFilterEntryPoint: <BR><BR><FONT color=#800080>&lt;bean id="authenticationProcessingFilterEntryPoint" <BR>class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"&gt; <BR>&nbsp; &lt;property name="loginFormUrl"&gt;&lt;value&gt;/acegilogin.jsp&lt;/value&gt;&lt;/property&gt; <BR>&nbsp; &lt;property name="forceHttps"&gt;&lt;value&gt;false&lt;/value&gt;&lt;/property&gt; <BR>&lt;/bean&gt;</FONT> <BR><BR>其中acegilogin.jsp是登陆页面，一个最简单的登录页面如下： <BR><BR><FONT color=#800080>&lt;%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %&gt; <BR>&lt;%@ page import="net.sf.acegisecurity.ui.AbstractProcessingFilter" %&gt; <BR>&lt;%@ page import="net.sf.acegisecurity.AuthenticationException" %&gt; <BR>&lt;html&gt; <BR>&nbsp; &lt;head&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;title&gt;Login&lt;/title&gt; <BR>&nbsp; &lt;/head&gt; <BR><BR>&nbsp; &lt;body&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;h1&gt;Login&lt;/h1&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;form action="&lt;c:url value='j_acegi_security_check'/&gt;" method="POST"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;table&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt;&lt;td&gt;User:&lt;/td&gt;&lt;td&gt;&lt;input type='text' name='j_username'&gt;&lt;/td&gt;&lt;/tr&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt;&lt;td&gt;Password:&lt;/td&gt;&lt;td&gt;&lt;input type='password' name='j_password'&gt;&lt;/td&gt;&lt;/tr&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt;&lt;td colspan='2'&gt;&lt;input name="submit" type="submit"&gt;&lt;/td&gt;&lt;/tr&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt;&lt;td colspan='2'&gt;&lt;input name="reset" type="reset"&gt;&lt;/td&gt;&lt;/tr&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/table&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;/form&gt; <BR>&nbsp; &lt;/body&gt; <BR>&lt;/html&gt;</FONT> <BR><BR>7) 添加filterInvocationInterceptor: <BR><BR><FONT color=#800080>&lt;bean id="filterInvocationInterceptor" <BR>class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor"&gt; <BR>&nbsp; &lt;property name="authenticationManager"&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;ref bean="authenticationManager"/&gt; <BR>&nbsp; &lt;/property&gt; <BR>&nbsp; &lt;property name="accessDecisionManager"&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;ref bean="accessDecisionManager"/&gt; <BR>&nbsp; &lt;/property&gt; <BR>&nbsp; &lt;property name="objectDefinitionSource"&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;value&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \A/sec/administrator.*\Z=ROLE_SUPERVISOR <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \A/sec/user.*\Z=ROLE_TELLER <BR>&nbsp;&nbsp;&nbsp; &lt;/value&gt; <BR>&nbsp; &lt;/property&gt; <BR>&lt;/bean&gt;</FONT> <BR><BR>这里请注意，要objectDefinitionSource中定义哪些页面需要权限访问，需要根据自己的应用需求进行修改，我上面给出 <BR>的定义的意思是这样的： <BR>&nbsp;a. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON意思是在比较请求路径时全部转换为小写 <BR>&nbsp;b. \A/sec/administrator.*\Z=ROLE_SUPERVISOR意思是只有权限为ROLE_SUPERVISOR才能访问/sec/administrator*的页面 <BR>&nbsp;c. \A/sec/user.*\Z=ROLE_TELLER意思是只有权限为ROLE_TELLER的用户才能访问/sec/user*的页面 <BR><BR>8) 添加securityEnforcementFilter: <BR><BR><FONT color=#800080>&lt;bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter"&gt; <BR>&nbsp; &lt;property name="filterSecurityInterceptor"&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;ref bean="filterInvocationInterceptor"/&gt; <BR>&nbsp; &lt;/property&gt; <BR>&nbsp; &lt;property name="authenticationEntryPoint"&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;ref bean="authenticationProcessingFilterEntryPoint"/&gt; <BR>&nbsp; &lt;/property&gt; <BR>&lt;/bean&gt; <BR><BR><FONT color=#000000>9) 添加authenticationProcessingFilter:</FONT> <BR><BR>&lt;bean id="authenticationProcessingFilter" <BR>class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter"&gt; <BR>&nbsp; &lt;property name="authenticationManager"&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;ref bean="authenticationManager"/&gt; <BR>&nbsp; &lt;/property&gt; <BR>&nbsp; &lt;property name="authenticationFailureUrl"&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;value&gt;/loginerror.jsp&lt;/value&gt; <BR>&nbsp; &lt;/property&gt; <BR>&nbsp; &lt;property name="defaultTargetUrl"&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;value&gt;/&lt;/value&gt; <BR>&nbsp; &lt;/property&gt; <BR>&nbsp; &lt;property name="filterProcessesUrl"&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;value&gt;/j_acegi_security_check&lt;/value&gt; <BR>&nbsp; &lt;/property&gt; <BR>&lt;/bean&gt;</FONT> <BR>其中authenticationFailureUrl是认证失败的页面。 <BR><BR>10) 如果需要一些页面通过安全通道的话，添加下面的配置: <BR><BR><FONT color=#800080>&lt;bean id="channelProcessingFilter" class="net.sf.acegisecurity.securechannel.ChannelProcessingFilter"&gt; <BR>&nbsp; &lt;property name="channelDecisionManager"&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;ref bean="channelDecisionManager"/&gt; <BR>&nbsp; &lt;/property&gt; <BR>&nbsp; &lt;property name="filterInvocationDefinitionSource"&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;value&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \A/sec/administrator.*\Z=REQUIRES_SECURE_CHANNEL <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \A/acegilogin.jsp.*\Z=REQUIRES_SECURE_CHANNEL <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \A/j_acegi_security_check.*\Z=REQUIRES_SECURE_CHANNEL <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \A.*\Z=REQUIRES_INSECURE_CHANNEL <BR>&nbsp;&nbsp;&nbsp; &lt;/value&gt; <BR>&nbsp; &lt;/property&gt; <BR>&lt;/bean&gt; <BR><BR>&lt;bean id="channelDecisionManager" class="net.sf.acegisecurity.securechannel.ChannelDecisionManagerImpl"&gt; <BR>&nbsp; &lt;property name="channelProcessors"&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;list&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref bean="secureChannelProcessor"/&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref bean="insecureChannelProcessor"/&gt; <BR>&nbsp;&nbsp;&nbsp; &lt;/list&gt; <BR>&nbsp; &lt;/property&gt; <BR>&lt;/bean&gt; <BR>&lt;bean id="secureChannelProcessor" class="net.sf.acegisecurity.securechannel.SecureChannelProcessor"/&gt; <BR>&lt;bean id="insecureChannelProcessor" class="net.sf.acegisecurity.securechannel.InsecureChannelProcessor"/&gt;</FONT> <BR><BR><B><FONT color=#0000ff size=3>[缺少了什么？]</FONT></B> <BR>Acegi目前提供了两种"secure object"，分别对页面和方法进行安全认证管理，我这里介绍的只是利用 <BR>FilterSecurityInterceptor对访问页面的权限控制，除此之外，Acegi还提供了另外一个Interceptor—— <BR>MethodSecurityInterceptor，它结合runAsManager可实现对对象中的方法的权限控制，使用方法可参看Acegi自带的文档 <BR>和contact范例。 <BR><BR><B><FONT color=#0000ff size=3>[最后要说的]</FONT></B> <BR>本来以为只是说明如何使用Acegi而已，应该非常简单，但真正写起来才发现想要条理清楚的理顺所有需要的bean还是很 <BR>困难的，但愿我没有遗漏太多东西，如果我的文章有什么遗漏或错误的话，还请参看Acegi自带的quick-start范例，但请 <BR>注意，这个范例是不能直接拿来用的</FONT></P><img src ="http://www.blogjava.net/jelver/aggbug/32263.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-02-24 11:06 <a href="http://www.blogjava.net/jelver/articles/32263.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring安全系统：Acegi Security(zhuan)</title><link>http://www.blogjava.net/jelver/articles/32259.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Fri, 24 Feb 2006 03:02:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/32259.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/32259.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/32259.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/32259.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/32259.html</trackback:ping><description><![CDATA[<H4>Acegi简介</H4>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Acegi安全系统，是一个用于Spring Framework的安全框架，能够和目前流行的Web容器无缝集成。它使用了Spring的方式提供了安全和认证安全服务，包括使用Bean Context，拦截器和面向接口的编程方式。因此，Acegi安全系统能够轻松地适用于复杂的安全需求。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 安全涉及到两个不同的概念，认证和授权。前者是关于确认用户是否确实是他们所宣称的身份。授权则是关于确认用户是否有允许执行一个特定的操作。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在Acegi安全系统中，需要被认证的用户，系统或代理称为"Principal"。Acegi安全系统和其他的安全系统不同，它并没有角色和用户组的概念。 </P>
<H4>Acegi系统设计</H4>
<H5>&nbsp; 关键组件</H5>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Acegi安全系统包含以下七个关键的功能组件： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; l&nbsp;Authentication对象，包含了Principal，Credential和Principal的授权信息。同时还可以包含关于发起认证请求的客户的其他信息，如IP地址。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp;ContextHolder对象，使用ThreadLocal储存Authentication对象的地方。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3&nbsp;AuthenticationManager，用于认证ContextHolder中的Authentication对象。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4&nbsp;AccessDecissionManager，用于授权一个特定的操作。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp;RunAsManager，当执行特定的操作时，用于选择性地替换Authentication对象。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6&nbsp;Secure Object拦截器，用于协调AuthenticationManager，AccessDecissionManager，RunAsManager和特定操作的执行。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7&nbsp;ObjectDefinitionSource，包含了特定操作的授权定义。 </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这七个关键的功能组件的关系如下图所示（图中灰色部分是关键组件）：</P>
<H5 align=center><IMG style="CURSOR: pointer" onclick=javascript:window.open(this.src); src="http://starrynight.blogdriver.com/diary/starrynight/inc/acegi1.gif" width=454 onload="javascript:if(this.width>500){this.resized=true;this.style.width=500;}"></H5>
<H5 align=left><BR>&nbsp; 安全管理对象</H5>
<P align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Acegi安全系统目前支持两类安全管理对象。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第一类的安全管理对象管理AOP Alliance的MethodInvocation，开发人员可以用它来保护Spring容器中的业务对象。为了使Spring管理的Bean可以作为MethodInvocation来使用，Bean可以通过ProxyFactoryBean和BeanNameAutoProxyCreator来管理，就像在Spring的事务管理一样使用。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第二类是FilterInvocation。它用过滤器（Filter）来创建，并简单地包装了HTTP的ServletRequest，ServletResponse和FilterChain。FilterInvocation可以用来保护HTTP资源。通常，开发人员并不需要了解它的工作机制，因为他们只需要将Filter加入web.xml，Acegi安全系统就可以工作了。 </P>
<H5 align=left>&nbsp; 安全配置参数</H5>
<P align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 每个安全管理对象都可以描述数量不限的各种安全认证请求。例如，MethodInvocation对象可以描述带有任意参数的任意方法的调用，而FilterInvocation可以描述任意的HTTP URL。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Acegi安全系统需要记录应用于每个认证请求的安全配置参数。例如，对于BankManager.getBalance（int accountNumber）方法和BankManager.approveLoan（int applicationNumber）方法，它们需要的认证请求的安全配置很不相同。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为了保存不同的认证请求的安全配置，需要使用配置参数。从实现的视角来看，配置参数使用ConfigAttribute接口来表示。Acegi安全系统提供了ConfigAttribute接口的一个实现，SecurityConfig，它把配置参数保存为一个字符串。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ConfigAttributeDefinition类是ConfigAttribute对象的一个简单的容器，它保存了和特定请求相关的ConfigAttribute的集合。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当安全拦截器收到一个安全认证请求时，需要决定应用哪一个配置参数。换句话说，它需要找出应用于这个请求的ConfigAttributeDefinition对象。这个查找的过程是由ObjectDefinitionSource接口来处理的。这个接口的主要方法是public ConfigAttributeDefinition getAttributes(Object object)，其中Object参数是一个安全管理对象。因为安全管理对象包含有认证请求的详细信息，所以ObjectDefinitionSource接口的实现类可以从中获得所需的详细信息，以查找相关的ConfigAttributeDefiniton对象。 </P>
<H5 align=left>&nbsp; Acegi如何工作</H5>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为了说明Acegi安全系统如何工作，我们设想一个使用Acegi的例子。通常，一个安全系统需要发挥作用，它必须完成以下的工作： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; l&nbsp;首先，系统从客户端请求中获得Principal和Credential； <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;然后系统认证Principal和Credential信息； <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3&nbsp;如果认证通过，系统取出Principal的授权信息； <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4&nbsp;接下来，客户端发起操作请求； <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp;系统根据预先配置的参数检查Principal对于该操作的授权； <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6&nbsp;如果授权检查通过则执行操作，否则拒绝。 </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那么，Acegi安全系统是如何完成这些工作的呢？首先，我们来看看Acegi安全系统的认证和授权的相关类图： </P>
<P align=center>&nbsp;<IMG style="CURSOR: pointer" onclick=javascript:window.open(this.src); src="http://starrynight.blogdriver.com/diary/starrynight/inc/acegi2.gif" width=500 onload="javascript:if(this.width>500){this.resized=true;this.style.width=500;}"> </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 图中绿色部分是安全拦截器的抽象基类，它包含有两个管理类，AuthenticationManager和AccessDecisionManager，如图中灰色部分。AuthenticationManager用于认证ContextHolder中的Authentication对象（包含了Principal，Credential和Principal的授权信息）；AccessDecissionManager则用于授权一个特定的操作。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面来看一个MethodSecurityInterceptor的例子： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean id="bankManagerSecurity" <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="validateConfigAttributes"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;true&lt;/value&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&lt;/property&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&lt;property name="authenticationManager"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&lt;ref bean="authenticationManager"/&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="accessDecisionManager"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&lt;ref bean="accessDecisionManager"/&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&lt;/property&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&lt;property name="objectDefinitionSource"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&lt;value&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;net.sf.acegisecurity.context.BankManager.delete*= <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ROLE_SUPERVISOR,RUN_AS_SERVER <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;net.sf.acegisecurity.context.BankManager.getBalance= <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER,RUN_ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/value&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/bean&gt; </P>
<P></P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;上面的配置文件中，MethodSecurityInterceptor是AbstractSecurityInterceptor的一个实现类。它包含了两个管理器，authenticationManager和accessDecisionManager。这两者的配置如下：</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean id="authenticationDao" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="dataSource"&gt;&lt;ref bean="dataSource"/&gt;&lt;/property&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/bean&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean id="daoAuthenticationProvider" <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="authenticationDao"&gt;&lt;ref bean="authenticationDao"/&gt;&lt;/property&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="providers"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;list&gt;&lt;ref bean="daoAuthenticationProvider"/&gt;&lt;/list&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&lt;/property&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/bean&gt; </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="allowIfAllAbstainDecisions"&gt;&lt;value&gt;false&lt;/value&gt;&lt;/property&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="decisionVoters"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&lt;list&gt;&lt;ref bean="roleVoter"/&gt;&lt;/list&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&lt;/property&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/bean&gt; </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 准备工作做好了，现在我们来看看Acegi安全系统是如何实现认证和授权机制的。以使用HTTP BASIC认证的应用为例子，它包括下面的步骤： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.&nbsp;用户登录系统，Acegi从acegisecurity.ui子系统的安全拦截器（如BasicProcessingFilter）中得到用户的登录信息（包括Principal和Credential）并放入Authentication对象，并保存在ContextHolder对象中； <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.&nbsp;安全拦截器将Authentication对象交给AuthenticationManager进行身份认证，如果认证通过，返回带有Principal授权信息的Authentication对象。此时ContextHolder对象的Authentication对象已拥有Principal的详细信息； <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.&nbsp;用户登录成功后，继续进行业务操作； <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.&nbsp;安全拦截器（bankManagerSecurity）收到客户端操作请求后，将操作请求的数据包装成安全管理对象（FilterInvocation或MethodInvocation对象）； <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5.&nbsp;然后，从配置文件（ObjectDefinitionSource）中读出相关的安全配置参数ConfigAttributeDefinition； <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6.&nbsp;接着，安全拦截器取出ContextHolder中的Authentication对象，把它传递给AuthenticationManager进行身份认证，并用返回值更新ContextHolder的Authentication对象； <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7.&nbsp;将Authentication对象，ConfigAttributeDefinition对象和安全管理对象（secure Object）交给AccessDecisionManager，检查Principal的操作授权； <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8.&nbsp;如果授权检查通过则执行客户端请求的操作，否则拒绝； </P>
<P>&nbsp; <STRONG>AccessDecisionVoter</STRONG> </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注意上节的accessDecisionManager是一个AffirmativeBased类，它对于用户授权的投票策略是，只要通过其中的一个授权投票检查，即可通过；它的allowIfAllAbstainDecisions属性值是false，意思是如果所有的授权投票是都是弃权，则通不过授权检查。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Acegi安全系统包括了几个基于投票策略的AccessDecisionManager，上节的RoleVoter就是其中的一个投票策略实现，它是AccessDecisionVoter的一个子类。AccessDecisionVoter的具体实现类通过投票来进行授权决策，AccessDecisionManager则根据投票结果来决定是通过授权检查，还是抛出AccessDeniedException例外。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AccessDecisionVoter接口共有三个方法： <BR>public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config); <BR>public boolean supports(ConfigAttribute attribute); <BR>public boolean supports(Class clazz); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其中的vote方法返回int返回值，它们是AccessDecisionVoter的三个静态成员属性：ACCESS_ABSTAIN,，ACCESS_DENIED和ACCESS_GRANTED，它们分别是弃权，否决和赞成。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Acegi安全系统中，使用投票策略的AccessDecisionManager共有三个具体实现类：AffirmativeBased、ConsensusBased和UnanimousBased。它们的投票策略是，AffirmativeBased类只需有一个投票赞成即可通过；ConsensusBased类需要大多数投票赞成即可通过；而UnanimousBased类需要所有的投票赞成才能通过。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RoleVoter类是一个Acegi安全系统AccessDecisionVoter接口的实现。如果ConfigAttribute以ROLE_开头，RoleVoter则进行投票。如果GrantedAuthority的getAutority方法的String返回值匹配一个或多个以ROLE_开头的ConfigAttribute，则投票通过，否则不通过。如果没有以ROLE_开头的ConfigAttribute，RoleVoter则弃权。 </P>
<H4>安全拦截器</H4>
<H5>&nbsp; 拦截器如何工作 <BR>&nbsp; MethodInvocation拦截器 <BR>&nbsp; FilterInvocation拦截器</H5>
<H4>认证</H4>
<H5>&nbsp; 认证请求 <BR>&nbsp; 认证管理器 <BR>&nbsp; Authentication Provider</H5>
<H4>授权</H4>
<H5>&nbsp; Access Decision Manager <BR>&nbsp; Voting Decision Manager <BR>&nbsp; 授权管理推荐</H5>
<H4>ContextHolder的用户接口</H4>
<H5>&nbsp; 用户接口目标 <BR>&nbsp; HTTP会话认证 <BR>&nbsp; HTTP Basic认证</H5>
<P>&nbsp;</P><img src ="http://www.blogjava.net/jelver/aggbug/32259.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-02-24 11:02 <a href="http://www.blogjava.net/jelver/articles/32259.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Spring 的MVC+Hibernate的数据库操作例子(转)</title><link>http://www.blogjava.net/jelver/articles/32189.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Thu, 23 Feb 2006 11:27:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/32189.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/32189.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/32189.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/32189.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/32189.html</trackback:ping><description><![CDATA[<P>网上讲Spring的资料很多，大部分实例都是针对Spring的某一部分做出的例子，如IoC,Aop,MVC,数据持久层等等，没有一个完整的例子。</P>
<P>这两天根据夏昕的Spring开发指南，在加上自己参考其他资料，做出了一个利用Spring的MVC，加上Hibernate的网站的实例，包括Jsp界面表单的提交，Spring的 MVC控制，使用Spring提供的HibernateTemplate进行数据持久的完整例子.</P>
<P>下面把程序的详细代码贴出来，由于自己也是初学，有不对的地方，还请过路的大侠指点一二。</P>
<P>一、需求：表单填写用户ID，用户名和地址，写入数据库</P>
<P>二、具体实现。。。。&nbsp; 代码见详细内容</P><BR>
<P>网上讲Spring的资料很多，大部分实例都是针对Spring的某一部分做出的例子，如Ioc,Aop,MVC,数据持久层等等，没有一个完整的例子。</P>
<P>这两天根据夏昕的Spring开发指南，在加上自己参考其他资料，做出了一个利用Spring的MVC，加上Hibernate的网站的实例，包括Jsp界面表单的提交，Spring的 MVC控制，使用Spring提供的HibernateTemplate进行数据持久的完整例子.</P>
<P>下面把程序的详细代码贴出来，自己也是初学，有不对的地方，还请过路的大侠指点一二。</P>
<P>一、需求：表单填写用户ID，用户名和地址，写入数据库</P>
<P>二、具体实现</P>
<P>1.UserInfoAdd.jsp</P>
<P>填写表单界面，输入ID,Name,Address后提交到UserInfoAddAction.do
<TABLE border=0>
<TBODY>
<TR>
<TD>
<P><!--page language="java" contentType="text/html; charset=gb2312--></P><BR><BR>
<P></P>
<P>UserID:<INPUT name=nid>Name:<INPUT name=name></P><BR>Address:<INPUT name=address><BR>&nbsp;&nbsp; 
<P><INPUT name=sumbit1 type=submit value=提交查询内容></P><BR></TD></TR></TBODY></TABLE></P>
<P>2.UserInfoVO&nbsp; </P>
<P>表单的映射。 Value Object类，用来获取表单提交的数据</P>
<TABLE border=0 height=602 width=481>
<TBODY>
<TR>
<TD>
<P>&nbsp;package com.kacakong.spring.vo;</P>
<P>public class UserInfoVO {<BR>&nbsp;public String nid;<BR>&nbsp;public String name;<BR>&nbsp;public String address;<BR>&nbsp;public String getAddress() {<BR>&nbsp;&nbsp;return address;<BR>&nbsp;}</P>
<P>&nbsp;public void setAddress(String address) {<BR>&nbsp;&nbsp;this.address = address;<BR>&nbsp;}</P>
<P>&nbsp;public String getName() {<BR>&nbsp;&nbsp;return name;<BR>&nbsp;}</P>
<P>&nbsp;public void setName(String name) {<BR>&nbsp;&nbsp;this.name = name;<BR>&nbsp;}</P>
<P>&nbsp;public String getNid() {<BR>&nbsp;&nbsp;return nid;<BR>&nbsp;}<BR>&nbsp;</P>
<P>&nbsp;public void setNid(String nid) {<BR>&nbsp;&nbsp;this.nid = nid;<BR>&nbsp;}<BR>&nbsp;</P>
<P>}<BR></P></TD></TR></TBODY></TABLE>
<P>&nbsp;</P>
<P>3.UserInfoAddAction</P>
<P>Control类，根据Spring的配置文件，调用合适的接口，执行业务操作，控制页面转向。如果添加数据成功，就重定向到成功页面，如果失败，就装到操作失败页面。具体调用的操作类，是根据Spring的配置文件来找的。使用的是接口操作，而不是实现类的操作。</P>
<TABLE border=0>
<TBODY>
<TR>
<TD>
<P>package com.kacakong.spring.action;</P>
<P>import org.springframework.validation.BindException;<BR>import org.springframework.web.context.WebApplicationContext;<BR>import org.springframework.web.servlet.ModelAndView;<BR>import org.springframework.web.servlet.mvc.SimpleFormController;</P>
<P>import com.kacakong.hibernate.dao.UserInfoDAO;<BR>import com.kacakong.hibernate.pojos.UserInfo;<BR>import com.kacakong.spring.vo.UserInfoVO;</P>
<P>public class UserInfoAddAction extends SimpleFormController {<BR>&nbsp;<BR>&nbsp;private String fail_view;</P>
<P>&nbsp;private String success_view;<BR>&nbsp;<BR>&nbsp;protected ModelAndView onSubmit(Object cmd, BindException ex)<BR>&nbsp;&nbsp;&nbsp;throws Exception {<BR>&nbsp;&nbsp;UserInfoVO vo = (UserInfoVO) cmd;<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;UserInfo userinfo=new UserInfo();<BR>&nbsp;&nbsp;userinfo.setNid(Integer.valueOf(vo.getNid()));<BR>&nbsp;&nbsp;userinfo.setName(vo.getName());<BR>&nbsp;&nbsp;userinfo.setAddress(vo.getAddress());<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;if (this.doAdd(userinfo)==1){<BR>&nbsp;&nbsp;&nbsp;&nbsp; return new ModelAndView(this.getSuccess_view());<BR>&nbsp;&nbsp;}else{<BR>&nbsp;&nbsp;&nbsp;&nbsp; return new ModelAndView(this.getFail_view());<BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;}</P>
<P>&nbsp;private int doAdd(UserInfo userinfo) {&nbsp;<BR>&nbsp;&nbsp;WebApplicationContext&nbsp; ctx=this.getWebApplicationContext();<BR>&nbsp;&nbsp;UserInfoDAO dao=(UserInfoDAO)ctx.getBean("UserInfoDAO");<BR>&nbsp;&nbsp;try{<BR>&nbsp;&nbsp;&nbsp;dao.save(userinfo);<BR>&nbsp;&nbsp;&nbsp;return 1;<BR>&nbsp;&nbsp;}catch(Exception e){&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;e.printStackTrace();<BR>&nbsp;&nbsp;&nbsp;return 0;<BR>&nbsp;&nbsp;}<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;public String getFail_view() {<BR>&nbsp;&nbsp;return fail_view;<BR>&nbsp;}</P>
<P>&nbsp;public String getSuccess_view() {<BR>&nbsp;&nbsp;return success_view;<BR>&nbsp;}</P>
<P>&nbsp;public void setFail_view(String string) {<BR>&nbsp;&nbsp;fail_view = string;<BR>&nbsp;}</P>
<P>&nbsp;public void setSuccess_view(String string) {<BR>&nbsp;&nbsp;success_view = string;<BR>&nbsp;}</P>
<P>}<BR>&nbsp;</P></TD></TR></TBODY></TABLE>
<P>4.UserInfo</P>
<P>PO类，数据model层的反映，与数据库建立O/R mapping的映射</P>
<TABLE border=0 height=613 width=395>
<TBODY>
<TR>
<TD>
<P>&nbsp;package com.kacakong.hibernate.pojos;</P>
<P>public class UserInfo {<BR>&nbsp;public Integer nid;<BR>&nbsp;public String name;<BR>&nbsp;public String address;<BR>&nbsp;public String getAddress() {<BR>&nbsp;&nbsp;return address;<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;public void setAddress(String address) {<BR>&nbsp;&nbsp;this.address = address;<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;public String getName() {<BR>&nbsp;&nbsp;return name;<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;public void setName(String name) {<BR>&nbsp;&nbsp;this.name = name;<BR>&nbsp;}</P>
<P>&nbsp;public Integer getNid() {<BR>&nbsp;&nbsp;return nid;<BR>&nbsp;}<BR>&nbsp;</P>
<P>&nbsp;public void setNid(Integer nid) {<BR>&nbsp;&nbsp;this.nid = nid;<BR>&nbsp;}<BR>&nbsp;</P>
<P><BR>&nbsp;<BR></P></TD></TR></TBODY></TABLE>
<P>5.UserInfo.hbm.xml</P>
<P>PO的hibernate O/R mapping定义文件，这里的ID我设置成了assigned程序获取</P>
<TABLE border=0>
<TBODY>
<TR>
<TD>
<P><!--l version="1.0" encoding="UTF-8--></P>
<P><!--CTYPE hibernate-mapping PUBLIC<br-->&nbsp;&nbsp;&nbsp; "-//Hibernate/Hibernate Mapping DTD 2.0//EN" <BR>&nbsp;&nbsp;&nbsp; "<A href="http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd</A>"&gt;</P>
<P><HIBERNATE-MAPPING><BR>&nbsp;<CLASS name="com.kacakong.hibernate.pojos.UserInfo" <br="" table="UserInfo">&nbsp;&nbsp;dynamic-update="false" dynamic-insert="false" <BR>&nbsp;&nbsp;select-before-update="false" optimistic-lock="version" &gt;<BR>&nbsp;&nbsp;<ID&NBSP; name="nid" unsaved-value="null" type="java.lang.Integer"><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <GENERATOR class=assigned><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </ID><BR>&nbsp;&nbsp;<property name="name" <br="" type="java.lang.String" update="true"></property>&nbsp;&nbsp;&nbsp;insert="true" access="property" column="name" length="50" <BR>&nbsp;&nbsp;&nbsp;not-null="true" /&gt;<BR>&nbsp;&nbsp;<property name="address" <br="" type="java.lang.String" update="true"></property>&nbsp;&nbsp;&nbsp;insert="true" access="property" column="address" length="50" <BR>&nbsp;&nbsp;&nbsp;not-null="true" /&gt;<BR>&nbsp;</CLASS><BR></HIBERNATE-MAPPING><BR></P></TD></TR></TBODY></TABLE>
<P>&nbsp;</P>
<P>6.UserInfoDAO</P>
<P>接口类，只定义了实现方法名称</P>
<TABLE border=0>
<TBODY>
<TR>
<TD>
<P>&nbsp;package com.kacakong.hibernate.dao;</P>
<P>import com.kacakong.hibernate.pojos.UserInfo;</P>
<P>public interface UserInfoDAO {<BR>&nbsp; public abstract UserInfo get(Integer integer);<BR>&nbsp; public abstract void save(UserInfo userinfo);<BR>}<BR></P></TD></TR></TBODY></TABLE>
<P>&nbsp;</P>
<P>7.UserInfoDAOImp</P>
<P>UserInfoDAO接口的实现，继承了HibernateDaoSupport </P>
<TABLE border=0>
<TBODY>
<TR>
<TD>
<P>&nbsp;package com.kacakong.hibernate.dao;</P>
<P>&nbsp;</P>
<P>import org.springframework.orm.hibernate.support.HibernateDaoSupport;</P>
<P>import com.kacakong.hibernate.pojos.UserInfo;</P>
<P>public class UserInfoDAOImp&nbsp; extends HibernateDaoSupport implements UserInfoDAO {</P>
<P>&nbsp;public UserInfo get(Integer id) {<BR>&nbsp;&nbsp;UserInfo userinfo=(UserInfo)this.getHibernateTemplate().get(UserInfo.class,id);<BR>&nbsp;&nbsp;return userinfo;<BR>&nbsp;}</P>
<P>&nbsp;public void save(UserInfo userinfo) {<BR>&nbsp;&nbsp;&nbsp;&nbsp; this.getHibernateTemplate().save(userinfo);<BR>&nbsp;}</P>
<P>}<BR></P></TD></TR></TBODY></TABLE>
<P>&nbsp;</P>
<P>8.Web.xml的配置</P>
<TABLE border=0>
<TBODY>
<TR>
<TD>
<P><!--l version="1.0"--><BR><!--CTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "<a href="http://java.sun.com/dtd/web-app_2_3.dt-->http://java.sun.com/dtd/web-app_2_3.dtd</A>"&gt;</P>
<P><!-- Copyright (c) 2002 by ObjectLearn. All Rights Reserved. --><BR><WEB-APP></P>
<P>&nbsp;&nbsp;&nbsp; <SERVLET><BR>&nbsp;&nbsp;<SERVLET-NAME>Dispatcher</SERVLET-NAME><BR>&nbsp;&nbsp;<SERVLET-CLASS>org.springframework.web.servlet.DispatcherServlet</SERVLET-CLASS><BR>&nbsp;&nbsp;<INIT-PARAM><BR>&nbsp;&nbsp;&nbsp;<PARAM-NAME>contextConfigLocation</PARAM-NAME><BR>&nbsp;&nbsp;&nbsp;<PARAM-VALUE>/WEB-INF/Config.xml /WEB-INF/Hibernate-Context.xml</PARAM-VALUE><BR>&nbsp;&nbsp;</INIT-PARAM><BR>&nbsp;</SERVLET><BR>&nbsp;<SERVLET-MAPPING><BR>&nbsp;&nbsp;<SERVLET-NAME>Dispatcher</SERVLET-NAME><BR>&nbsp;&nbsp;<URL-PATTERN>*.do</URL-PATTERN><BR>&nbsp;</SERVLET-MAPPING><BR>&nbsp;<WELCOME-FILE-LIST><BR>&nbsp;&nbsp;<WELCOME-FILE>index.jsp</WELCOME-FILE><BR>&nbsp;</WELCOME-FILE-LIST></P>
<P>&nbsp;<ERROR-PAGE><BR>&nbsp;&nbsp;<ERROR-CODE>404</ERROR-CODE><BR>&nbsp;&nbsp;<LOCATION>/error.jsp</LOCATION><BR>&nbsp;</ERROR-PAGE></P>
<P></WEB-APP><BR></P></TD></TR></TBODY></TABLE>
<P>&nbsp;</P>
<P>9.Config.xml的定义</P>
<P>
<TABLE border=0>
<TBODY>
<TR>
<TD><!--l version="1.0" encoding="UTF-8--><BR><!--CTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" <br-->&nbsp;"<A href="http://www.springframework.org/dtd/spring-beans.dtd">http://www.springframework.org/dtd/spring-beans.dtd</A>"&gt;<BR><BEANS><BR>&nbsp;<!--Definition of View Resolver --><BR>&nbsp;<BEAN id=viewResolver <br="">&nbsp;&nbsp;class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt;<BR>&nbsp;&nbsp;<property name="viewClass"><BR>&nbsp;&nbsp;&nbsp;<VALUE>org.springframework.web.servlet.view.JstlView</VALUE><BR>&nbsp;&nbsp;</property><BR>&nbsp;&nbsp;<property name="prefix"><BR>&nbsp;&nbsp;&nbsp;<VALUE></VALUE><BR>&nbsp;&nbsp;</property><BR>&nbsp;&nbsp;<property name="suffix"><BR>&nbsp;&nbsp;&nbsp;<VALUE>.jsp</VALUE><BR>&nbsp;&nbsp;</property><BR>&nbsp;</BEAN><BR>&nbsp;<!--Request Mapping --><BR>&nbsp;<BEAN id=urlMapping <br="">&nbsp;&nbsp;class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"&gt;<BR>&nbsp;&nbsp;<property name="mappings"><BR>&nbsp;&nbsp;&nbsp;<PROPS><BR>&nbsp;&nbsp;&nbsp;&nbsp;<PROP key="UserInfoAddAction.do">UserInfoAddAction</PROP><BR>&nbsp;&nbsp;&nbsp;</PROPS><BR>&nbsp;&nbsp;</property><BR>&nbsp;</BEAN><BR>&nbsp;<!---Action Definition--><BR>&nbsp;<BEAN id=UserInfoAddAction <br="">&nbsp;&nbsp;class="com.kacakong.spring.action.UserInfoAddAction"&gt;<BR>&nbsp;&nbsp;<property name="commandClass"><BR>&nbsp;&nbsp;&nbsp;<VALUE>com.kacakong.spring.vo.UserInfoVO</VALUE><BR>&nbsp;&nbsp;</property><BR>&nbsp;&nbsp;<property name="fail_view"><BR>&nbsp;&nbsp;&nbsp;<VALUE>fail</VALUE><BR>&nbsp;&nbsp;</property><BR>&nbsp;&nbsp;<property name="success_view"><BR>&nbsp;&nbsp;&nbsp;<VALUE>UserInfo</VALUE><BR>&nbsp;&nbsp;</property><BR>&nbsp;</BEAN><BR></BEANS><BR><!--l version="1.0" encoding="UTF-8--></TD></TR></TBODY></TABLE></P>
<P>10.Hibernate-Context.xml的定义</P>
<TABLE border=0>
<TBODY>
<TR>
<TD>
<P><!--l version="1.0" encoding="UTF-8--><BR><!--CTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"<br-->"<A href="http://www.springframework.org/dtd/spring-beans.dtd">http://www.springframework.org/dtd/spring-beans.dtd</A>"&gt;<BR><BEANS><BR>&nbsp;<BEAN class=org.apache.commons.dbcp.BasicDataSource id=dataSource &nbsp;destroy-method="close"><BR>&nbsp;&nbsp;<property name="driverClassName"><BR>&nbsp;&nbsp;&nbsp;<VALUE>oracle.jdbc.driver.OracleDriver</VALUE><BR>&nbsp;&nbsp;</property><BR>&nbsp;&nbsp;<property name="url"><BR>&nbsp;&nbsp;&nbsp;<VALUE>jdbc:oracle:thin:@192.168.100.8:1521:EASTPLUS</VALUE><BR>&nbsp;&nbsp;</property><BR>&nbsp;&nbsp;<property name="username"><BR>&nbsp;&nbsp;&nbsp;<VALUE>spring</VALUE><BR>&nbsp;&nbsp;</property><BR>&nbsp;&nbsp;<property name="password"><BR>&nbsp;&nbsp;&nbsp;<VALUE>spring</VALUE><BR>&nbsp;&nbsp;</property><BR>&nbsp;</BEAN><BR><property name="mappingResources"><BR>&nbsp;&nbsp;&nbsp;&nbsp;<VALUE>com/kacakong/hibernate/pojos/UserInfo.hbm.xml</VALUE><BR></LIST><BR>&nbsp;&nbsp;</property><BR>&nbsp;&nbsp;<property name="hibernateProperties"><BR>&nbsp;&nbsp;&nbsp;<PROPS><BR>&nbsp;&nbsp;&nbsp;&nbsp;<PROP key="hibernate.dialect">net.sf.hibernate.dialect.SQLServerDialect&nbsp;</PROP><BR>&nbsp;&nbsp;&nbsp;&nbsp;<PROP key="hibernate.show_sql">true</PROP><BR>&nbsp;&nbsp;&nbsp;</PROPS></property><property name="transactionAttributes"><BR>&nbsp;&nbsp;&nbsp;<PROPS><BR>&nbsp;&nbsp;&nbsp;&nbsp;<PROP key="insert*">PROPAGATION_REQUIRED</PROP><BR>&nbsp;&nbsp;&nbsp;&nbsp;<PROP key="get*">PROPAGATION_REQUIRED,readOnly</PROP><BR>&nbsp;&nbsp;&nbsp;</property></P></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/jelver/aggbug/32189.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-02-23 19:27 <a href="http://www.blogjava.net/jelver/articles/32189.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse中利用Spring的JDBC模板写DAO</title><link>http://www.blogjava.net/jelver/articles/32134.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Thu, 23 Feb 2006 09:37:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/32134.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/32134.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/32134.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/32134.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/32134.html</trackback:ping><description><![CDATA[&nbsp;
<P>DAO应该是现在比较流行的一种开发模式.不管是用什么更新的技术,hibernate或者其它的.DAO模式是应该遵循的.<BR>我写DAO大概是这样的:一个DAO接口,定义好要实现的方法名称;一个Impl实现类,主要控制连接及关闭数据库;<BR>接下来会有一个写具体方法的数据库实现类;还有一个工厂类,可以更灵活的取得不同的DAO.<BR>上面的写法感觉上不错,但是写起来比较麻烦,而且如果使用数据库连接池的活,利用JUnit做测试的时候会比较麻烦.<BR>下面我们利用Spring的JDBC模板写一个DAO测试实例,你会发现它是如此的简单且实用.<BR>使用的了DBCP的连接池.</P>
<P>下面是要引入的JAR包<BR>&nbsp;&nbsp;&nbsp; &lt;classpathentry kind="lib" path="D:/classes/spring.jar"/&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;classpathentry kind="lib" path="D:/classes/junit-3.8.1.jar"/&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;classpathentry kind="lib" path="D:/classes/spring-dao.jar"/&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;classpathentry kind="lib" path="D:/classes/mysql-connector-java-3.0.9-stable-bin.jar"/&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;classpathentry kind="lib" path="D:/classes/commons-dbcp-1.1.jar"/&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;classpathentry kind="lib" path="D:/classes/commons-pool-1.1.jar"/&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;classpathentry kind="lib" path="D:/classes/commons-collections.jar"/&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;classpathentry kind="lib" path="D:/classes/commons-beanutils.jar"/&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;classpathentry kind="lib" path="D:/classes/commons-lang-2.0.jar"/&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;classpathentry kind="lib" path="D:/classes/commons-logging-1.0.3.jar"/&gt;</P>
<P>SpringDao.java文件</P>
<P>package com.bcxy.spring.dao;</P>
<P>import java.sql.PreparedStatement;<BR>import java.sql.ResultSet;<BR>import java.sql.SQLException;<BR>import java.util.ArrayList;<BR>import java.util.List;</P>
<P>import javax.sql.DataSource;</P>
<P>import org.apache.commons.logging.Log;<BR>import org.apache.commons.logging.LogFactory;<BR>import org.springframework.jdbc.core.JdbcTemplate;<BR>import org.springframework.jdbc.core.PreparedStatementSetter;<BR>import org.springframework.jdbc.core.RowCallbackHandler;</P>
<P>import com.bcxy.spring.dao.model.TestModel;</P>
<P>public class SpringDao {</P>
<P>&nbsp;DataSource ds = null;<BR>&nbsp;<BR>&nbsp;JdbcTemplate jt = null;<BR>&nbsp;<BR>&nbsp;Log log = LogFactory.getLog(SpringDao.class);<BR>&nbsp;<BR>&nbsp;public List springQuery(){<BR>&nbsp;&nbsp;final List tests = new ArrayList();<BR>&nbsp;&nbsp;String sql = " select * from test ";<BR>&nbsp;&nbsp;jt = new JdbcTemplate(ds);<BR>&nbsp;&nbsp;jt.query(sql, new RowCallbackHandler(){</P>
<P>&nbsp;&nbsp;&nbsp;public void processRow(ResultSet rs) throws SQLException {<BR>&nbsp;&nbsp;&nbsp;&nbsp;// <BR>&nbsp;&nbsp;&nbsp;&nbsp;TestModel tm = new TestModel();<BR>&nbsp;&nbsp;&nbsp;&nbsp;tm.setId(rs.getInt("id"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;tm.setPw(rs.getString("pw"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;tm.setUn(rs.getString("un"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;//<BR>&nbsp;&nbsp;&nbsp;&nbsp;tests.add(tm);<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;});<BR>&nbsp;&nbsp;return tests;<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;public void springUpdate() {<BR>&nbsp;&nbsp;String sql = "update test set pw=? where id=?";<BR>&nbsp;&nbsp;jt = new JdbcTemplate(ds);<BR>&nbsp;&nbsp;jt.update(sql, new PreparedStatementSetter() {<BR>&nbsp;&nbsp;&nbsp;public void setValues(PreparedStatement ps) throws SQLException {<BR>&nbsp;&nbsp;&nbsp;&nbsp;// <BR>&nbsp;&nbsp;&nbsp;&nbsp;ps.setString(1, "maxcard");<BR>&nbsp;&nbsp;&nbsp;&nbsp;ps.setInt(2, 1);<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;});<BR>&nbsp;&nbsp;log.info("update test a record.");<BR>&nbsp;}</P>
<P>&nbsp;/**<BR>&nbsp; * @return<BR>&nbsp; */<BR>&nbsp;public DataSource getDs() {<BR>&nbsp;&nbsp;return ds;<BR>&nbsp;}</P>
<P>&nbsp;/**<BR>&nbsp; * @param source<BR>&nbsp; */<BR>&nbsp;public void setDs(DataSource source) {<BR>&nbsp;&nbsp;ds = source;<BR>&nbsp;}</P>
<P>}</P>
<P>Spring配置文件</P>
<P>&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;description&gt;Spring Quick Start&lt;/description&gt;<BR>&lt;!-- datasource --&gt;<BR>&lt;bean id="datasource" <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.commons.dbcp.BasicDataSource"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; destroy-method="close"&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;property name="driverClassName"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;com.mysql.jdbc.Driver&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/property&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;property name="url"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;jdbc:mysql://localhost/test&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/property&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;property name="username"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;root&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/property&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;property name="password"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/property&gt;<BR>&lt;/bean&gt;<BR>&lt;!-- test dao --&gt;<BR>&lt;bean id="testdao"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="com.bcxy.spring.dao.SpringDao"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &gt;<BR>&nbsp;&nbsp;&nbsp; &lt;property name="ds"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref local="datasource"/&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/property&gt;<BR>&lt;/bean&gt;</P>
<P>&lt;/beans&gt;</P>
<P>下面我们用JUnit测试一下:<BR>......</P>
<P>&nbsp;public void testSpringUpdate() throws FileNotFoundException {<BR>&nbsp;&nbsp;&nbsp;&nbsp; //<BR>&nbsp;&nbsp;InputStream is = new FileInputStream("bean.xml");<BR>&nbsp;&nbsp;XmlBeanFactory bean = new XmlBeanFactory(is);<BR>&nbsp;&nbsp;SpringDao sd = (SpringDao)bean.getBean("testdao");<BR>&nbsp;&nbsp;sd.springUpdate();<BR>&nbsp;}</P><img src ="http://www.blogjava.net/jelver/aggbug/32134.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-02-23 17:37 <a href="http://www.blogjava.net/jelver/articles/32134.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate和Spring对DAO处理的实例 </title><link>http://www.blogjava.net/jelver/articles/32133.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Thu, 23 Feb 2006 09:33:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/32133.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/32133.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/32133.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/32133.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/32133.html</trackback:ping><description><![CDATA[<FONT face=Arial>用spring处理的一个HibernateDAO实例,可以看到,代码量大大减少了.&nbsp;<BR><BR>java代码:&nbsp;&nbsp;<BR><BR>&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;2&nbsp;&nbsp;&nbsp;package&nbsp;infoweb.dao;&nbsp;<BR>&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;4&nbsp;&nbsp;&nbsp;import&nbsp;java.util.List;&nbsp;<BR>&nbsp;5&nbsp;&nbsp;&nbsp;import&nbsp;java.util.Iterator;&nbsp;<BR>&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;7&nbsp;&nbsp;&nbsp;import&nbsp;infoweb.pojo.Info;&nbsp;<BR>&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;10&nbsp;&nbsp;import&nbsp;net.sf.hibernate.HibernateException;&nbsp;<BR>&nbsp;11&nbsp;&nbsp;import&nbsp;net.sf.hibernate.Query;&nbsp;<BR>&nbsp;12&nbsp;&nbsp;import&nbsp;net.sf.hibernate.Session;&nbsp;<BR>&nbsp;13&nbsp;&nbsp;&nbsp;<BR>&nbsp;14&nbsp;&nbsp;import&nbsp;org.springframework.orm.hibernate.HibernateCallback;&nbsp;<BR>&nbsp;15&nbsp;&nbsp;import&nbsp;org.springframework.orm.hibernate.support.HibernateDaoSupport;&nbsp;<BR>&nbsp;16&nbsp;&nbsp;&nbsp;<BR>&nbsp;17&nbsp;&nbsp;&nbsp;<BR>&nbsp;18&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;19&nbsp;&nbsp;&nbsp;*&nbsp;&lt;p&gt;Title:&nbsp;&lt;/p&gt;&nbsp;<BR>&nbsp;20&nbsp;&nbsp;&nbsp;*&nbsp;&lt;p&gt;Description:&nbsp;&lt;/p&gt;&nbsp;<BR>&nbsp;21&nbsp;&nbsp;&nbsp;*&nbsp;&lt;p&gt;Copyright:&nbsp;Copyright&nbsp;(c)&nbsp;2004&lt;/p&gt;&nbsp;<BR>&nbsp;22&nbsp;&nbsp;&nbsp;*&nbsp;&lt;p&gt;Company:&nbsp;&lt;/p&gt;&nbsp;<BR>&nbsp;23&nbsp;&nbsp;&nbsp;*&nbsp;@author&nbsp;段洪杰&nbsp;<BR>&nbsp;24&nbsp;&nbsp;&nbsp;*&nbsp;@version&nbsp;1.0&nbsp;<BR>&nbsp;25&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>&nbsp;26&nbsp;&nbsp;&nbsp;<BR>27&nbsp;&nbsp;public&nbsp;class&nbsp;InfoDAOImpl&nbsp;extends&nbsp;HibernateDaoSupport&nbsp;implements&nbsp;IInfoDAO&nbsp;{&nbsp;<BR>...}<BR>&nbsp;28&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;29&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;构造函数&nbsp;<BR>&nbsp;30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>31&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;InfoDAOImpl()&nbsp;{&nbsp;<BR>...}<BR>&nbsp;32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super();&nbsp;<BR>&nbsp;33&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;34&nbsp;&nbsp;&nbsp;<BR>&nbsp;35&nbsp;&nbsp;&nbsp;<BR>&nbsp;36&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;37&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;增加记录&nbsp;<BR>&nbsp;38&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;info&nbsp;Info&nbsp;<BR>&nbsp;39&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>40&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setInfo(Info&nbsp;info)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;41&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getHibernateTemplate().save(info);&nbsp;<BR>&nbsp;42&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;43&nbsp;&nbsp;&nbsp;<BR>&nbsp;44&nbsp;&nbsp;&nbsp;<BR>&nbsp;45&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;46&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;通过ID取得记录&nbsp;<BR>&nbsp;47&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;id&nbsp;String&nbsp;<BR>&nbsp;48&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;Info&nbsp;<BR>&nbsp;49&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>50&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Info&nbsp;getInfoById(String&nbsp;id)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Info&nbsp;info&nbsp;=&nbsp;(Info)&nbsp;getHibernateTemplate().load(Info.class,&nbsp;id);&nbsp;<BR>&nbsp;52&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;info;&nbsp;<BR>&nbsp;53&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;54&nbsp;&nbsp;&nbsp;<BR>&nbsp;55&nbsp;&nbsp;&nbsp;<BR>&nbsp;56&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;57&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;修改记录&nbsp;<BR>&nbsp;58&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;Info&nbsp;info&nbsp;<BR>&nbsp;59&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>60&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;modifyInfo(Info&nbsp;info)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;61&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getHibernateTemplate().update(info);&nbsp;<BR>&nbsp;62&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;63&nbsp;&nbsp;&nbsp;<BR>&nbsp;64&nbsp;&nbsp;&nbsp;<BR>&nbsp;65&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;66&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;删除记录&nbsp;<BR>&nbsp;67&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;Info&nbsp;info&nbsp;<BR>&nbsp;68&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>69&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;removeInfo(Info&nbsp;info)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;70&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getHibernateTemplate().delete(info);&nbsp;<BR>&nbsp;71&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;72&nbsp;&nbsp;&nbsp;<BR>&nbsp;73&nbsp;&nbsp;&nbsp;<BR>&nbsp;74&nbsp;&nbsp;&nbsp;&nbsp;////////////////////////////////////////////////////////&nbsp;<BR>&nbsp;75&nbsp;&nbsp;&nbsp;&nbsp;/////&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;<BR>&nbsp;76&nbsp;&nbsp;&nbsp;&nbsp;/////以下部份不带审核功能&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;<BR>&nbsp;77&nbsp;&nbsp;&nbsp;&nbsp;/////&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;<BR>&nbsp;78&nbsp;&nbsp;&nbsp;&nbsp;////////////////////////////////////////////////////////&nbsp;<BR>&nbsp;79&nbsp;&nbsp;&nbsp;<BR>&nbsp;80&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;81&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;取记录总数&nbsp;<BR>&nbsp;82&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;int&nbsp;<BR>&nbsp;83&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>84&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;getInfosCount()&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;85&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;count&nbsp;=&nbsp;0;&nbsp;<BR>&nbsp;86&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;"select&nbsp;count(*)&nbsp;from&nbsp;Info";&nbsp;<BR>&nbsp;87&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count&nbsp;=&nbsp;((Integer)&nbsp;getHibernateTemplate().iterate(queryString).next()).&nbsp;<BR>&nbsp;88&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;intValue();&nbsp;<BR>&nbsp;89&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;count;&nbsp;<BR>&nbsp;90&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;91&nbsp;&nbsp;&nbsp;<BR>&nbsp;92&nbsp;&nbsp;&nbsp;<BR>&nbsp;93&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;94&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;取所有记录集合&nbsp;<BR>&nbsp;95&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;Iterator&nbsp;<BR>&nbsp;96&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>97&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Iterator&nbsp;getAllInfos()&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;98&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iterator&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;99&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;"&nbsp;select&nbsp;info&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;order&nbsp;by&nbsp;info.id&nbsp;desc";&nbsp;<BR>&nbsp;100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;=&nbsp;getHibernateTemplate().find(queryString);&nbsp;<BR>&nbsp;101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;=&nbsp;list.iterator();&nbsp;<BR>&nbsp;102&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;iterator;&nbsp;<BR>&nbsp;103&nbsp;&nbsp;&nbsp;}<BR>&nbsp;104&nbsp;&nbsp;<BR>&nbsp;105&nbsp;&nbsp;<BR>&nbsp;106&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;107&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;取记录集合&nbsp;<BR>&nbsp;108&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;Iterator&nbsp;<BR>&nbsp;109&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;int&nbsp;position,&nbsp;int&nbsp;length&nbsp;<BR>&nbsp;110&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>111&nbsp;&nbsp;&nbsp;public&nbsp;Iterator&nbsp;getInfos(int&nbsp;position,&nbsp;int&nbsp;length)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;112&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iterator&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;113&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;"&nbsp;select&nbsp;info&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;order&nbsp;by&nbsp;info.id&nbsp;desc";&nbsp;<BR>&nbsp;114&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Query&nbsp;query&nbsp;=&nbsp;getHibernateTemplate().createQuery(getSession(),&nbsp;queryString);&nbsp;<BR>&nbsp;115&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置游标的起始点&nbsp;<BR>&nbsp;116&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query.setFirstResult(position);&nbsp;<BR>&nbsp;117&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置游标的长度&nbsp;<BR>&nbsp;118&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query.setMaxResults(length);&nbsp;<BR>&nbsp;119&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//记录生成&nbsp;<BR>&nbsp;120&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;=&nbsp;query.list();&nbsp;<BR>&nbsp;121&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//把查询到的结果放入迭代器&nbsp;<BR>&nbsp;122&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;=&nbsp;list.iterator();&nbsp;<BR>&nbsp;123&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;iterator;&nbsp;<BR>&nbsp;124&nbsp;&nbsp;&nbsp;}<BR>&nbsp;125&nbsp;&nbsp;<BR>&nbsp;126&nbsp;&nbsp;<BR>&nbsp;127&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;128&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;取第一条记录&nbsp;<BR>&nbsp;129&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@throws&nbsp;Exception&nbsp;<BR>&nbsp;130&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;Station&nbsp;<BR>&nbsp;131&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>132&nbsp;&nbsp;&nbsp;public&nbsp;Info&nbsp;getFirstInfo()&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;133&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iterator&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;134&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Info&nbsp;info&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;135&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;"select&nbsp;info&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;order&nbsp;by&nbsp;info.id&nbsp;desc";&nbsp;<BR>&nbsp;136&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Query&nbsp;query&nbsp;=&nbsp;getHibernateTemplate().createQuery(getSession(),&nbsp;queryString);&nbsp;<BR>&nbsp;137&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//记录生成&nbsp;<BR>&nbsp;138&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;=&nbsp;query.list();&nbsp;<BR>&nbsp;139&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//把查询到的结果放入迭代器&nbsp;<BR>&nbsp;140&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;=&nbsp;list.iterator();&nbsp;<BR>141&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(iterator.hasNext())&nbsp;{&nbsp;<BR>...}<BR>&nbsp;142&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;info&nbsp;=&nbsp;(Info)&nbsp;iterator.next();&nbsp;<BR>&nbsp;143&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;144&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;info;&nbsp;<BR>&nbsp;145&nbsp;&nbsp;&nbsp;}<BR>&nbsp;146&nbsp;&nbsp;<BR>&nbsp;147&nbsp;&nbsp;<BR>&nbsp;148&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;149&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;取最后一条记录&nbsp;<BR>&nbsp;150&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@throws&nbsp;Exception&nbsp;<BR>&nbsp;151&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;Station&nbsp;<BR>&nbsp;152&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>153&nbsp;&nbsp;&nbsp;public&nbsp;Info&nbsp;getLastInfo()&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;154&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iterator&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;155&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Info&nbsp;info&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;156&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;"select&nbsp;info&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;order&nbsp;by&nbsp;info.id&nbsp;asc";&nbsp;<BR>&nbsp;157&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Query&nbsp;query&nbsp;=&nbsp;getHibernateTemplate().createQuery(getSession(),&nbsp;queryString);&nbsp;<BR>&nbsp;158&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//记录生成&nbsp;<BR>&nbsp;159&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;=&nbsp;query.list();&nbsp;<BR>&nbsp;160&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//把查询到的结果放入迭代器&nbsp;<BR>&nbsp;161&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;=&nbsp;list.iterator();&nbsp;<BR>162&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(iterator.hasNext())&nbsp;{&nbsp;<BR>...}<BR>&nbsp;163&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;info&nbsp;=&nbsp;(Info)&nbsp;iterator.next();&nbsp;<BR>&nbsp;164&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;165&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;info;&nbsp;<BR>&nbsp;166&nbsp;&nbsp;<BR>&nbsp;167&nbsp;&nbsp;&nbsp;}<BR>&nbsp;168&nbsp;&nbsp;<BR>&nbsp;169&nbsp;&nbsp;<BR>&nbsp;170&nbsp;&nbsp;&nbsp;////////////////////////////////////////////////////////&nbsp;<BR>&nbsp;171&nbsp;&nbsp;&nbsp;/////&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;<BR>&nbsp;172&nbsp;&nbsp;&nbsp;/////&nbsp;以下部份表中要有特定字段才能&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;<BR>&nbsp;173&nbsp;&nbsp;&nbsp;/////&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;<BR>&nbsp;174&nbsp;&nbsp;&nbsp;////////////////////////////////////////////////////////&nbsp;<BR>&nbsp;175&nbsp;&nbsp;<BR>&nbsp;176&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;177&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;取符合条件记录总数,&nbsp;[表中要有&nbsp;isperson&nbsp;字段]&nbsp;<BR>&nbsp;178&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;int&nbsp;<BR>&nbsp;179&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;int&nbsp;isPerson&nbsp;<BR>&nbsp;180&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>&nbsp;181&nbsp;&nbsp;<BR>182&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;getInfosCountByIsperson(int&nbsp;isPerson)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;183&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;count&nbsp;=&nbsp;0;&nbsp;<BR>&nbsp;184&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;<BR>&nbsp;185&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"select&nbsp;count(*)&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;where&nbsp;info.isperson&nbsp;="&nbsp;+&nbsp;isPerson;&nbsp;<BR>&nbsp;186&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count&nbsp;=&nbsp;((Integer)&nbsp;getHibernateTemplate().iterate(queryString).next()).&nbsp;<BR>&nbsp;187&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;intValue();&nbsp;<BR>&nbsp;188&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;count;&nbsp;<BR>&nbsp;189&nbsp;&nbsp;&nbsp;}<BR>&nbsp;190&nbsp;&nbsp;<BR>&nbsp;191&nbsp;&nbsp;<BR>&nbsp;192&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;193&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;取所有符合条件记录集合,&nbsp;模糊查询条件.[表中要有&nbsp;isperson&nbsp;字段]&nbsp;<BR>&nbsp;194&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;Iterator&nbsp;<BR>&nbsp;195&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;int&nbsp;isPerson&nbsp;<BR>&nbsp;196&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>&nbsp;197&nbsp;&nbsp;<BR>198&nbsp;&nbsp;&nbsp;public&nbsp;Iterator&nbsp;getAllInfosByIsperson(int&nbsp;isPerson)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;199&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iterator&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;200&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;"&nbsp;select&nbsp;info&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;where&nbsp;info.isperson&nbsp;="&nbsp;+&nbsp;<BR>&nbsp;201&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;isPerson&nbsp;+&nbsp;"&nbsp;order&nbsp;by&nbsp;info.id&nbsp;desc";&nbsp;<BR>&nbsp;202&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;=&nbsp;getHibernateTemplate().find(queryString);&nbsp;<BR>&nbsp;203&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//把查询到的结果放入迭代器&nbsp;<BR>&nbsp;204&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;=&nbsp;list.iterator();&nbsp;<BR>&nbsp;205&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;iterator;&nbsp;<BR>&nbsp;206&nbsp;&nbsp;&nbsp;}<BR>&nbsp;207&nbsp;&nbsp;<BR>&nbsp;208&nbsp;&nbsp;<BR>&nbsp;209&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;210&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;取符合条件记录集合,&nbsp;模糊查询条件.[表中要有&nbsp;isperson&nbsp;字段]&nbsp;<BR>&nbsp;211&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;Iterator&nbsp;<BR>&nbsp;212&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;int&nbsp;isPerson,int&nbsp;position,&nbsp;int&nbsp;length&nbsp;<BR>&nbsp;213&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>&nbsp;214&nbsp;&nbsp;<BR>&nbsp;215&nbsp;&nbsp;&nbsp;public&nbsp;Iterator&nbsp;getInfosByIsperson(int&nbsp;isPerson,&nbsp;int&nbsp;position,&nbsp;int&nbsp;length)&nbsp;throws&nbsp;<BR>216&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;217&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iterator&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;218&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;"&nbsp;select&nbsp;info&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;where&nbsp;info.isperson&nbsp;="&nbsp;+&nbsp;<BR>&nbsp;219&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;isPerson&nbsp;+&nbsp;"&nbsp;order&nbsp;by&nbsp;info.id&nbsp;desc";&nbsp;<BR>&nbsp;220&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//创建查询&nbsp;<BR>&nbsp;221&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Query&nbsp;query&nbsp;=&nbsp;getHibernateTemplate().createQuery(getSession(),&nbsp;queryString);&nbsp;<BR>&nbsp;222&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置游标的起始点&nbsp;<BR>&nbsp;223&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query.setFirstResult(position);&nbsp;<BR>&nbsp;224&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置游标的长度&nbsp;<BR>&nbsp;225&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query.setMaxResults(length);&nbsp;<BR>&nbsp;226&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//记录生成&nbsp;<BR>&nbsp;227&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;=&nbsp;query.list();&nbsp;<BR>&nbsp;228&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//把查询到的结果放入迭代器&nbsp;<BR>&nbsp;229&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;=&nbsp;list.iterator();&nbsp;<BR>&nbsp;230&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;iterator;&nbsp;<BR>&nbsp;231&nbsp;&nbsp;&nbsp;}<BR>&nbsp;232&nbsp;&nbsp;<BR>&nbsp;233&nbsp;&nbsp;<BR>&nbsp;234&nbsp;&nbsp;&nbsp;////////////////////////////////////////////////////////&nbsp;<BR>&nbsp;235&nbsp;&nbsp;&nbsp;/////&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;<BR>&nbsp;236&nbsp;&nbsp;&nbsp;/////&nbsp;以下部份表中要有特定字段才能&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;查询部份&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;<BR>&nbsp;237&nbsp;&nbsp;&nbsp;/////&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;<BR>&nbsp;238&nbsp;&nbsp;&nbsp;///////////////////////////////////////////////////////&nbsp;<BR>&nbsp;239&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;240&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;取符合条件记录总数,&nbsp;模糊查询条件.[表中要有&nbsp;title&nbsp;字段]&nbsp;<BR>&nbsp;241&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;int&nbsp;<BR>&nbsp;242&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;String&nbsp;text&nbsp;<BR>&nbsp;243&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>244&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;getInfosCount(String&nbsp;text)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;245&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;count&nbsp;=&nbsp;0;&nbsp;<BR>&nbsp;246&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count&nbsp;=&nbsp;((Integer)&nbsp;getHibernateTemplate().iterate(&nbsp;<BR>&nbsp;247&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"select&nbsp;count(*)&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;where&nbsp;info.title&nbsp;like&nbsp;'%"&nbsp;+&nbsp;text&nbsp;+&nbsp;<BR>&nbsp;248&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"%'").next()).intValue();&nbsp;<BR>&nbsp;249&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;count;&nbsp;<BR>&nbsp;250&nbsp;&nbsp;&nbsp;}<BR>&nbsp;251&nbsp;&nbsp;<BR>&nbsp;252&nbsp;&nbsp;<BR>&nbsp;253&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;254&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;取所有符合条件记录集合,&nbsp;模糊查询条件.[表中要有&nbsp;title&nbsp;字段]&nbsp;<BR>&nbsp;255&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;Iterator&nbsp;<BR>&nbsp;256&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;String&nbsp;text&nbsp;<BR>&nbsp;257&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>&nbsp;258&nbsp;&nbsp;<BR>259&nbsp;&nbsp;&nbsp;public&nbsp;Iterator&nbsp;getAllInfos(String&nbsp;text)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;260&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iterator&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;261&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;<BR>&nbsp;262&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"&nbsp;select&nbsp;info&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;where&nbsp;info.title&nbsp;like&nbsp;'%"&nbsp;+&nbsp;text&nbsp;+&nbsp;<BR>&nbsp;263&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"%'&nbsp;order&nbsp;by&nbsp;info.id&nbsp;desc";&nbsp;<BR>&nbsp;264&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//创建查询&nbsp;<BR>&nbsp;265&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Query&nbsp;query&nbsp;=&nbsp;getHibernateTemplate().createQuery(getSession(),&nbsp;queryString);&nbsp;<BR>&nbsp;266&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//记录生成&nbsp;<BR>&nbsp;267&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;=&nbsp;query.list();&nbsp;<BR>&nbsp;268&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//把查询到的结果放入迭代器&nbsp;<BR>&nbsp;269&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;=&nbsp;list.iterator();&nbsp;<BR>&nbsp;270&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;iterator;&nbsp;<BR>&nbsp;271&nbsp;&nbsp;&nbsp;}<BR>&nbsp;272&nbsp;&nbsp;<BR>&nbsp;273&nbsp;&nbsp;<BR>&nbsp;274&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;275&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;取符合条件记录集合,&nbsp;模糊查询条件.[表中要有&nbsp;title&nbsp;字段]&nbsp;<BR>&nbsp;276&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;Iterator&nbsp;<BR>&nbsp;277&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;String&nbsp;text,int&nbsp;position,&nbsp;int&nbsp;length&nbsp;<BR>&nbsp;278&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>&nbsp;279&nbsp;&nbsp;&nbsp;public&nbsp;Iterator&nbsp;getInfos(String&nbsp;text,&nbsp;int&nbsp;position,&nbsp;int&nbsp;length)&nbsp;throws&nbsp;<BR>280&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;281&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iterator&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;282&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;<BR>&nbsp;283&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"&nbsp;select&nbsp;info&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;where&nbsp;info.title&nbsp;like&nbsp;'%"&nbsp;+&nbsp;text&nbsp;+&nbsp;<BR>&nbsp;284&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"%'&nbsp;order&nbsp;by&nbsp;info.id&nbsp;desc";&nbsp;<BR>&nbsp;285&nbsp;&nbsp;<BR>&nbsp;286&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//创建查询&nbsp;<BR>&nbsp;287&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Query&nbsp;query&nbsp;=&nbsp;getHibernateTemplate().createQuery(getSession(),&nbsp;queryString);&nbsp;<BR>&nbsp;288&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置游标的起始点&nbsp;<BR>&nbsp;289&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query.setFirstResult(position);&nbsp;<BR>&nbsp;290&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置游标的长度&nbsp;<BR>&nbsp;291&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query.setMaxResults(length);&nbsp;<BR>&nbsp;292&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//记录生成&nbsp;<BR>&nbsp;293&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;=&nbsp;query.list();&nbsp;<BR>&nbsp;294&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//把查询到的结果放入迭代器&nbsp;<BR>&nbsp;295&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;=&nbsp;list.iterator();&nbsp;<BR>&nbsp;296&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;iterator;&nbsp;<BR>&nbsp;297&nbsp;&nbsp;&nbsp;}<BR>&nbsp;298&nbsp;&nbsp;<BR>&nbsp;299&nbsp;&nbsp;<BR>&nbsp;300&nbsp;&nbsp;&nbsp;////////////////////////////////////////////////////////&nbsp;<BR>&nbsp;301&nbsp;&nbsp;&nbsp;/////&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;<BR>&nbsp;302&nbsp;&nbsp;&nbsp;/////&nbsp;以下部份表中要有特定字段才能&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;<BR>&nbsp;303&nbsp;&nbsp;&nbsp;/////&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;<BR>&nbsp;304&nbsp;&nbsp;&nbsp;////////////////////////////////////////////////////////&nbsp;<BR>&nbsp;305&nbsp;&nbsp;<BR>&nbsp;306&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;307&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;取符合条件记录总数.[&nbsp;表中要有&nbsp;registername&nbsp;字段]&nbsp;<BR>&nbsp;308&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;int&nbsp;<BR>&nbsp;309&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;String&nbsp;text&nbsp;<BR>&nbsp;310&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>311&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;getInfosCountByRegisterName(String&nbsp;registerName)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;312&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;count&nbsp;=&nbsp;0;&nbsp;<BR>&nbsp;313&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count&nbsp;=&nbsp;((Integer)&nbsp;getHibernateTemplate().iterate(&nbsp;<BR>&nbsp;314&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"select&nbsp;count(*)&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;where&nbsp;info.registername&nbsp;=&nbsp;'"&nbsp;+&nbsp;<BR>&nbsp;315&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;registerName&nbsp;+&nbsp;"'").next()).intValue();&nbsp;<BR>&nbsp;316&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;count;&nbsp;<BR>&nbsp;317&nbsp;&nbsp;&nbsp;}<BR>&nbsp;318&nbsp;&nbsp;<BR>&nbsp;319&nbsp;&nbsp;<BR>&nbsp;320&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;321&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;通过注册名取得一条记录,如有多条,只取第一条.[表中要有&nbsp;registername字段]&nbsp;<BR>&nbsp;322&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;registername&nbsp;String&nbsp;<BR>&nbsp;323&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;Info&nbsp;<BR>&nbsp;324&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>325&nbsp;&nbsp;&nbsp;public&nbsp;Info&nbsp;getInfoByRegisterName(String&nbsp;registerName)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;326&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iterator&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;327&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Info&nbsp;info&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;328&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;<BR>&nbsp;329&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"&nbsp;select&nbsp;info&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;where&nbsp;info.registername='"&nbsp;+&nbsp;<BR>&nbsp;330&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;registerName&nbsp;+&nbsp;"'&nbsp;order&nbsp;by&nbsp;info.id&nbsp;desc";&nbsp;<BR>&nbsp;331&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//创建查询&nbsp;<BR>&nbsp;332&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Query&nbsp;query&nbsp;=&nbsp;getHibernateTemplate().createQuery(getSession(),&nbsp;queryString);&nbsp;<BR>&nbsp;333&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//记录生成&nbsp;<BR>&nbsp;334&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;=&nbsp;query.list();&nbsp;<BR>&nbsp;335&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//把查询到的结果放入迭代器&nbsp;<BR>&nbsp;336&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;=&nbsp;list.iterator();&nbsp;<BR>337&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(iterator.hasNext())&nbsp;{&nbsp;<BR>...}<BR>&nbsp;338&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;info&nbsp;=&nbsp;(Info)&nbsp;iterator.next();&nbsp;<BR>&nbsp;339&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;340&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;info;&nbsp;<BR>&nbsp;341&nbsp;&nbsp;&nbsp;}<BR>&nbsp;342&nbsp;&nbsp;<BR>&nbsp;343&nbsp;&nbsp;<BR>&nbsp;344&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;345&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;通过注册名取得所有记录集合.[表中要有&nbsp;registername字段]&nbsp;<BR>&nbsp;346&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;registername&nbsp;String&nbsp;<BR>&nbsp;347&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;Iterator&nbsp;<BR>&nbsp;348&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>&nbsp;349&nbsp;&nbsp;&nbsp;public&nbsp;Iterator&nbsp;getAllInfosByRegisterName(String&nbsp;registerName)&nbsp;throws&nbsp;<BR>350&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;351&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iterator&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;352&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;<BR>&nbsp;353&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"&nbsp;select&nbsp;info&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;where&nbsp;info.registername='"&nbsp;+&nbsp;<BR>&nbsp;354&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;registerName&nbsp;+&nbsp;"'&nbsp;order&nbsp;by&nbsp;info.id&nbsp;desc";&nbsp;<BR>&nbsp;355&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//创建查询&nbsp;<BR>&nbsp;356&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Query&nbsp;query&nbsp;=&nbsp;getHibernateTemplate().createQuery(getSession(),&nbsp;queryString);&nbsp;<BR>&nbsp;357&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//记录生成&nbsp;<BR>&nbsp;358&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;=&nbsp;query.list();&nbsp;<BR>&nbsp;359&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//把查询到的结果放入迭代器&nbsp;<BR>&nbsp;360&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;=&nbsp;list.iterator();&nbsp;<BR>&nbsp;361&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;iterator;&nbsp;<BR>&nbsp;362&nbsp;&nbsp;&nbsp;}<BR>&nbsp;363&nbsp;&nbsp;<BR>&nbsp;364&nbsp;&nbsp;<BR>&nbsp;365&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;366&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;通过注册名取得记录列表.[表中要有&nbsp;registername字段]&nbsp;<BR>&nbsp;367&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;registername&nbsp;String&nbsp;<BR>&nbsp;368&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;Iterator&nbsp;<BR>&nbsp;369&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>&nbsp;370&nbsp;&nbsp;&nbsp;public&nbsp;Iterator&nbsp;getInfosByRegisterName(String&nbsp;registerName,&nbsp;int&nbsp;position,&nbsp;<BR>371&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;length)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;372&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iterator&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;373&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;<BR>&nbsp;374&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"&nbsp;select&nbsp;info&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;where&nbsp;info.registername='"&nbsp;+&nbsp;<BR>&nbsp;375&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;registerName&nbsp;+&nbsp;"'&nbsp;order&nbsp;by&nbsp;info.id&nbsp;desc";&nbsp;<BR>&nbsp;376&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//创建查询&nbsp;<BR>&nbsp;377&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Query&nbsp;query&nbsp;=&nbsp;getHibernateTemplate().createQuery(getSession(),&nbsp;queryString);&nbsp;<BR>&nbsp;378&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置游标的起始点&nbsp;<BR>&nbsp;379&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query.setFirstResult(position);&nbsp;<BR>&nbsp;380&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置游标的长度&nbsp;<BR>&nbsp;381&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query.setMaxResults(length);&nbsp;<BR>&nbsp;382&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//记录生成&nbsp;<BR>&nbsp;383&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;=&nbsp;query.list();&nbsp;<BR>&nbsp;384&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//把查询到的结果放入迭代器&nbsp;<BR>&nbsp;385&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;=&nbsp;list.iterator();&nbsp;<BR>&nbsp;386&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;iterator;&nbsp;<BR>&nbsp;387&nbsp;&nbsp;&nbsp;}<BR>&nbsp;388&nbsp;&nbsp;<BR>&nbsp;389&nbsp;&nbsp;<BR>&nbsp;390&nbsp;&nbsp;&nbsp;////////////////////////////////////////////////////////&nbsp;<BR>&nbsp;391&nbsp;&nbsp;&nbsp;/////&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;<BR>&nbsp;392&nbsp;&nbsp;&nbsp;/////&nbsp;以下部份表中要有特定字段才能&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;<BR>&nbsp;393&nbsp;&nbsp;&nbsp;/////&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;<BR>&nbsp;394&nbsp;&nbsp;&nbsp;////////////////////////////////////////////////////////&nbsp;<BR>&nbsp;395&nbsp;&nbsp;<BR>&nbsp;396&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;397&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;取记录总数.[&nbsp;表中要有&nbsp;board_id&nbsp;字段]&nbsp;<BR>&nbsp;398&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;int&nbsp;<BR>&nbsp;399&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;String&nbsp;boardId&nbsp;<BR>&nbsp;400&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>401&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;getInfosCountByBoard(String&nbsp;boardId)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;402&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;count&nbsp;=&nbsp;0;&nbsp;<BR>&nbsp;403&nbsp;&nbsp;<BR>&nbsp;404&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count&nbsp;=&nbsp;((Integer)&nbsp;getHibernateTemplate().iterate(&nbsp;<BR>&nbsp;405&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"select&nbsp;count(*)&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;where&nbsp;info.boardId&nbsp;=&nbsp;'"&nbsp;+&nbsp;boardId&nbsp;+&nbsp;<BR>&nbsp;406&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"'").next()).intValue();&nbsp;<BR>&nbsp;407&nbsp;&nbsp;<BR>&nbsp;408&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;count;&nbsp;<BR>&nbsp;409&nbsp;&nbsp;&nbsp;}<BR>&nbsp;410&nbsp;&nbsp;<BR>&nbsp;411&nbsp;&nbsp;<BR>&nbsp;412&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;413&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;通过版块名取得所有记录集合.[表中要有&nbsp;board_id字段]&nbsp;<BR>&nbsp;414&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;BoardId&nbsp;String&nbsp;<BR>&nbsp;415&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;Iterator&nbsp;<BR>&nbsp;416&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>417&nbsp;&nbsp;&nbsp;public&nbsp;Iterator&nbsp;getAllInfosByBoard(String&nbsp;boardId)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;418&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iterator&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;419&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;"&nbsp;select&nbsp;info&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;where&nbsp;info.boardId='"&nbsp;+&nbsp;<BR>&nbsp;420&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boardId&nbsp;+&nbsp;"'&nbsp;order&nbsp;by&nbsp;info.id&nbsp;desc";&nbsp;<BR>&nbsp;421&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//创建查询&nbsp;<BR>&nbsp;422&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Query&nbsp;query&nbsp;=&nbsp;getHibernateTemplate().createQuery(getSession(),&nbsp;queryString);&nbsp;<BR>&nbsp;423&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//记录生成&nbsp;<BR>&nbsp;424&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;=&nbsp;query.list();&nbsp;<BR>&nbsp;425&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//把查询到的结果放入迭代器&nbsp;<BR>&nbsp;426&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;=&nbsp;list.iterator();&nbsp;<BR>&nbsp;427&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;iterator;&nbsp;<BR>&nbsp;428&nbsp;&nbsp;&nbsp;}<BR>&nbsp;429&nbsp;&nbsp;<BR>&nbsp;430&nbsp;&nbsp;<BR>&nbsp;431&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;432&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;通过版块名取得记录列表.[表中要有&nbsp;board_id字段]&nbsp;<BR>&nbsp;433&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;BoardId&nbsp;String&nbsp;<BR>&nbsp;434&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;Iterator&nbsp;<BR>&nbsp;435&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>&nbsp;436&nbsp;&nbsp;&nbsp;public&nbsp;Iterator&nbsp;getInfosByBoard(String&nbsp;boardId,&nbsp;int&nbsp;position,&nbsp;int&nbsp;length)&nbsp;throws&nbsp;<BR>437&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;438&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iterator&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;439&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;"&nbsp;select&nbsp;info&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;where&nbsp;info.boardId='"&nbsp;+&nbsp;<BR>&nbsp;440&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boardId&nbsp;+&nbsp;"'&nbsp;order&nbsp;by&nbsp;info.id&nbsp;desc";&nbsp;<BR>&nbsp;441&nbsp;&nbsp;<BR>&nbsp;442&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//创建查询&nbsp;<BR>&nbsp;443&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Query&nbsp;query&nbsp;=&nbsp;getHibernateTemplate().createQuery(getSession(),&nbsp;queryString);&nbsp;<BR>&nbsp;444&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置游标的起始点&nbsp;<BR>&nbsp;445&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query.setFirstResult(position);&nbsp;<BR>&nbsp;446&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置游标的长度&nbsp;<BR>&nbsp;447&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query.setMaxResults(length);&nbsp;<BR>&nbsp;448&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//记录生成&nbsp;<BR>&nbsp;449&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;=&nbsp;query.list();&nbsp;<BR>&nbsp;450&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//把查询到的结果放入迭代器&nbsp;<BR>&nbsp;451&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;=&nbsp;list.iterator();&nbsp;<BR>&nbsp;452&nbsp;&nbsp;<BR>&nbsp;453&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;iterator;&nbsp;<BR>&nbsp;454&nbsp;&nbsp;<BR>&nbsp;455&nbsp;&nbsp;&nbsp;}<BR>&nbsp;456&nbsp;&nbsp;<BR>&nbsp;457&nbsp;&nbsp;<BR>&nbsp;458&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;459&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;取符合条件记录总数.[&nbsp;表中要有&nbsp;board_id&nbsp;字段,title]&nbsp;&nbsp;模糊查询title&nbsp;<BR>&nbsp;460&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;int&nbsp;<BR>&nbsp;461&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;String&nbsp;boardId&nbsp;,String&nbsp;text&nbsp;<BR>&nbsp;462&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>463&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;getInfosCountByBoard(String&nbsp;boardId,&nbsp;String&nbsp;text)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;464&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;count&nbsp;=&nbsp;0;&nbsp;<BR>&nbsp;465&nbsp;&nbsp;<BR>&nbsp;466&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count&nbsp;=&nbsp;((Integer)&nbsp;getHibernateTemplate().iterate(&nbsp;<BR>&nbsp;467&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"select&nbsp;count(*)&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;where&nbsp;info.boardId='"&nbsp;+&nbsp;boardId&nbsp;+&nbsp;<BR>&nbsp;468&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"'&nbsp;and&nbsp;info.title&nbsp;like&nbsp;'%"&nbsp;+&nbsp;text&nbsp;+&nbsp;"%'").next()).intValue();&nbsp;<BR>&nbsp;469&nbsp;&nbsp;<BR>&nbsp;470&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;count;&nbsp;<BR>&nbsp;471&nbsp;&nbsp;<BR>&nbsp;472&nbsp;&nbsp;&nbsp;}<BR>&nbsp;473&nbsp;&nbsp;<BR>&nbsp;474&nbsp;&nbsp;<BR>&nbsp;475&nbsp;&nbsp;&nbsp;/**&nbsp;<BR>&nbsp;476&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;通过版块名取得记录列表.[表中要有&nbsp;board_id字段]&nbsp;&nbsp;模糊查询title&nbsp;<BR>&nbsp;477&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;String&nbsp;boardID,int&nbsp;position,&nbsp;int&nbsp;length&nbsp;<BR>&nbsp;478&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;Iterator&nbsp;<BR>&nbsp;479&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;<BR>&nbsp;480&nbsp;&nbsp;&nbsp;public&nbsp;Iterator&nbsp;getInfosByBoard(String&nbsp;boardId,&nbsp;int&nbsp;position,&nbsp;int&nbsp;length,&nbsp;<BR>481&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;text)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;<BR>...}<BR>&nbsp;482&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iterator&nbsp;=&nbsp;null;&nbsp;<BR>&nbsp;483&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;"&nbsp;select&nbsp;info&nbsp;from&nbsp;Info&nbsp;as&nbsp;info&nbsp;where&nbsp;info.boardId='"&nbsp;+&nbsp;<BR>&nbsp;484&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boardId&nbsp;+&nbsp;"'&nbsp;and&nbsp;info.title&nbsp;like&nbsp;'%"&nbsp;+&nbsp;text&nbsp;+&nbsp;<BR>&nbsp;485&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"%'&nbsp;order&nbsp;by&nbsp;info.id&nbsp;desc";&nbsp;<BR>&nbsp;486&nbsp;&nbsp;<BR>&nbsp;487&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//创建查询&nbsp;<BR>&nbsp;488&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Query&nbsp;query&nbsp;=&nbsp;getHibernateTemplate().createQuery(getSession(),&nbsp;queryString);&nbsp;<BR>&nbsp;489&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置游标的起始点&nbsp;<BR>&nbsp;490&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query.setFirstResult(position);&nbsp;<BR>&nbsp;491&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置游标的长度&nbsp;<BR>&nbsp;492&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query.setMaxResults(length);&nbsp;<BR>&nbsp;493&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//记录生成&nbsp;<BR>&nbsp;494&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;=&nbsp;query.list();&nbsp;<BR>&nbsp;495&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//把查询到的结果放入迭代器&nbsp;<BR>&nbsp;496&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator&nbsp;=&nbsp;list.iterator();&nbsp;<BR>&nbsp;497&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;iterator;&nbsp;<BR>&nbsp;498&nbsp;&nbsp;<BR>&nbsp;499&nbsp;&nbsp;&nbsp;}</FONT><BR><img src ="http://www.blogjava.net/jelver/aggbug/32133.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-02-23 17:33 <a href="http://www.blogjava.net/jelver/articles/32133.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>