﻿<?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-把永恒在一刹那间收藏-文章分类-spring</title><link>http://www.blogjava.net/gm_jing/category/13228.html</link><description>生活之点点滴滴</description><language>zh-cn</language><lastBuildDate>Fri, 15 Jan 2010 12:16:03 GMT</lastBuildDate><pubDate>Fri, 15 Jan 2010 12:16:03 GMT</pubDate><ttl>60</ttl><item><title>spring 的注释</title><link>http://www.blogjava.net/gm_jing/articles/309007.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Mon, 11 Jan 2010 05:24:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/309007.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/309007.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/309007.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/309007.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/309007.html</trackback:ping><description><![CDATA[<p>发现一篇好文 http://www.ibm.com/developerworks/cn/java/j-lo-spring25-ioc/ 它给出了比本文更详细的说明。</p>
<p>springframework 2.5引入了完整的annotaion配置注解，使用这些annotation可以大量的减少bean的定义，也使得程序开发更简单和容易维护。</p>
<p>当然你要使用annotation就需要使用java5以上版本。</p>
<p>使用annotaion定义一个bean<br />
@Component是一个通用注解，用于说明一个类是一个spring容器管理的类。<br />
除此之外，还有@Controller, @Service, @Repository是@Component的细化，这三个注解比@Component带有更多的语义，它们分别对应了表现层、服务层、持久层的类。<br />
如果你只是用它们定义bean，你可以仅使用@Component，但是既然spring提供这些细化的注解，那肯定有使用它们的好处，不过在以下的例子中体现不出。</p>
<p>定义了一个接口</p>
<p>package test1;</p>
<p>interface MovieFinder {<br />
&nbsp;&nbsp;&nbsp; String getData();<br />
}<br />
定义一个实现</p>
<p>package test1;</p>
<p>import org.springframework.stereotype.Repository;</p>
<p>@Repository<br />
public class JpaMovieFinder implements MovieFinder {</p>
<p>&nbsp;&nbsp;&nbsp; @Override<br />
&nbsp;&nbsp;&nbsp; public String getData() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "This is JpaMovieFinder implementation!";<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>}<br />
这里使用了注解@Repository，说明这是一个受spring容器管理的bean定义，这个注解没有指定bean的名字，默认为小写开头的类名，就是jpaMovieFinder，如果你要指定名字，可以这样写@Repository("myMovieFinder")。<br />
这里也可以使用＠Component这个注解，在这里例子中体现不出用@Repository的好处。<br />
这里没有指定这个bean的scope，缺省是singleton，如果你要其他scope，可以使用注解@Scope</p>
<p>@Scope("prototype")<br />
@Repository<br />
public class MovieFinderImpl implements MovieFinder {<br />
&nbsp;&nbsp;&nbsp; // ...<br />
}</p>
<p>spring扫描并注册注解的bean<br />
JpaMovieFinder只是添加了一个注解，这并不会自动被注册到spring容器中，我们需要告诉spring容器到那里去寻找这些bean。<br />
配置如下：</p>
<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;beans xmlns="http://www.springframework.org/schema/beans"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns:context="http://www.springframework.org/schema/context"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xsi:schemaLocation="http://www.springframework.org/schema/beans <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://www.springframework.org/schema/beans/spring-beans-2.5.xsd<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://www.springframework.org/schema/context<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://www.springframework.org/schema/context/spring-context-2.5.xsd"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;context:component-scan base-package="test1"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;/beans&gt;<br />
&lt;context:component-scan base-package="test1"/&gt;这个配置告诉spring容器到test1这个package下去扫描所有的类，从而找到被注解的类。<br />
由于并不是test1下的所有的类都有注解，全部遍历效率不高，所以spring定义了过滤器用于减小扫描范围，这里为了简单起见没有使用。</p>
<p>使用注解进行依赖注入</p>
<p>package test1;</p>
<p><br />
import org.springframework.beans.factory.annotation.Autowired;<br />
import org.springframework.stereotype.Service;</p>
<p><br />
@Service<br />
public class SimpleMovieLister {<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; ＠Autowired<br />
&nbsp;&nbsp;&nbsp; private MovieFinder movieFinder;</p>
<p><br />
&nbsp;&nbsp;&nbsp; public String getData(String name) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "Hi " + name + "! " + movieFinder.getData();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public MovieFinder getMovieFinder() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return movieFinder;<br />
&nbsp;&nbsp;&nbsp; }</p>
<p><br />
&nbsp;&nbsp;&nbsp; public void setMovieFinder(MovieFinder movieFinder) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.movieFinder = movieFinder;<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
SimpleMovieLister是一个服务类，它也使用了＠Service注解为了bean，这个类用到了MovieFinder，为了注入这个类的实现，这里使用了注解@Autowired，spring容器会自动找到合适的bean注入进去。注意这里并没有指定被注入bean的名字，因为spring根据只发现了一个实现，那就是jpaMovieFinder。后面，我们会看到有两个实现会怎样。</p>
<p>注意，上面代码使用＠Autowired时，public void setMovieFinder(MovieFinder movieFinder) 这个方法是不需要的，你可以把它删除了试一试。如果你使用xml的配置方式，该方法必须存在。我这里保留该方法，是为了后面测试注解和xml配置混合使用的方式。</p>
<p>测试1</p>
<p>package test1;</p>
<p><br />
import org.springframework.context.ApplicationContext;<br />
import org.springframework.context.support.ClassPathXmlApplicationContext;</p>
<p><br />
public class Main {</p>
<p><br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ApplicationContext context = new ClassPathXmlApplicationContext("test1/beans.xml");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SimpleMovieLister m = (SimpleMovieLister)context.getBean("simpleMovieLister");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(m.getData("Arthur"));<br />
&nbsp;&nbsp;&nbsp; }</p>
<p><br />
}</p>
<p><br />
控制台上会打印 Hi Arthur! This is JpaMovieFinder implementation!</p>
<p>增加MovieFinder的第二个实现</p>
<p>package test1;</p>
<p>import org.springframework.stereotype.Repository;</p>
<p>@Repository<br />
public class IbatisMovieFinder implements MovieFinder {</p>
<p>&nbsp;&nbsp;&nbsp; @Override<br />
&nbsp;&nbsp;&nbsp; public String getData() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "This is IbatisMovieFinder implementation!";<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>}</p>
<p><br />
这时运行Main，系统会报错：<br />
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'simpleMovieLister': Injection of resource fields failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [test1.MovieFinder] is defined: expected single matching bean but found 2: [jpaMovieFinder, ibatisMovieFinder]<br />
从错误信息中我们可以看到现在MovieFinder有两个bean实现了，一个是jpaMovieFinder，另一个是ibatisMovieFinder，spring容器不知道应该使用哪一个bean。这时可以使用注解@Qualifier指定具体的bean。<br />
//...<br />
@Service<br />
public class SimpleMovieLister {</p>
<p><br />
&nbsp;&nbsp;&nbsp; @Autowired<br />
&nbsp;&nbsp;&nbsp; @Qualifier("ibatisMovieFinder")<br />
&nbsp;&nbsp;&nbsp; private MovieFinder movieFinder;<br />
//...<br />
这里我们指定注入的是ibatisMovieFinder这个bean。<br />
运行Main, 控制台上会打印 Hi Arthur! This is IbatisMovieFinder implementation!</p>
<p>Java6提供的注入注解<br />
spring也可以使用java6提供的＠Resource注解来指定注入哪一个bean。</p>
<p>//...<br />
@Service<br />
public class SimpleMovieLister {</p>
<p>&nbsp;&nbsp;&nbsp; @Resource(name="ibatisMovieFinder")<br />
&nbsp;&nbsp;&nbsp; private MovieFinder movieFinder;<br />
//...<br />
这和@Autowired功能是一致的。</p>
<p>使用注解还是xml<br />
使用注解很方便，但从上面的例子我们也可以看出注解的问题，MovieFinder有两个实现，SimpleMovieLister是在程序中用注解指定了使用哪一个实现，如果要修改，需要修改源程序。所以，注解只适用于固定依赖的情况。如果依赖需要在部署的时候做调整，那还是使用xml的配置方式方便，毕竟只需要修改一下xml文件即可。</p>
<p>实际使用时，我们可以xml和注解两种方式混合使用。</p>
<p><br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;beans xmlns="http://www.springframework.org/schema/beans"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns:context="http://www.springframework.org/schema/context"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xsi:schemaLocation="http://www.springframework.org/schema/beans <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://www.springframework.org/schema/beans/spring-beans-2.5.xsd<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://www.springframework.org/schema/context<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://www.springframework.org/schema/context/spring-context-2.5.xsd"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;context:component-scan base-package="test1"/&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;bean id="simpleMovieLister1" class="test1.SimpleMovieLister"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="movieFinder" ref="jpaMovieFinder" /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&lt;/beans&gt;<br />
使用xml配置方式定义了另外一bean，注入了jpaMovieFinder这个实现。</p>
<p><br />
package test1;</p>
<p><br />
import org.springframework.context.ApplicationContext;<br />
import org.springframework.context.support.ClassPathXmlApplicationContext;</p>
<p><br />
public class Main {</p>
<p><br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ApplicationContext context = new ClassPathXmlApplicationContext("test1/beans.xml");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SimpleMovieLister m = (SimpleMovieLister)context.getBean("simpleMovieLister");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(m.getData("Arthur"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SimpleMovieLister m1 = (SimpleMovieLister)context.getBean("simpleMovieLister1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(m1.getData("Arthur"));<br />
&nbsp;&nbsp;&nbsp; }</p>
<p><br />
}<br />
simpleMovieLister是从注解来的，simpleMovieLister1是从xml配置来的。运行结果：<br />
Hi Arthur! This is IbatisMovieFinder implementation!<br />
Hi Arthur! This is JpaMovieFinder implementation!</p>
<p>证明混合使用是可行的，你可以继续测试，用xml重新配置simpleMovieLister。<br />
因此，即使我一开始使用了注解，之后我后悔了，没有关系，不用修改源程序，以前用xml怎么配置现在还是怎么配置。</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/dqatsh/archive/2008/12/08/3478000.aspx</p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/309007.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2010-01-11 13:24 <a href="http://www.blogjava.net/gm_jing/articles/309007.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring组件自动扫描机制</title><link>http://www.blogjava.net/gm_jing/articles/308709.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Fri, 08 Jan 2010 05:53:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/308709.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/308709.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/308709.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/308709.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/308709.html</trackback:ping><description><![CDATA[<div class="articalTitle"><span class="titName SG_txta" id="t_5c0522dd0100g3na"><a href="mailto:Spring@Component,@Service,@Controller,@Repository">Spring @Component,@Service,@Controller,@Repository</a></span></div>
<div class="articalContent">
<p><span style="font-size: 14px; line-height: 22px; font-family: Arial,Helvetica,sans-serif"><span>在一个稍大的项目中，通常会有上百个组件，如果这些组件采用xml的bean定义来配置，显然会增加配置文件的体积，查找以及维护起来也不太方便。Spring2.5为我们引入了组件自动扫描机制，他可以在类路径底下寻找标注了@Component,@Service,@Controller,@Repository注解的类，并把这些类纳入进<span><font style="background-color: #55ff55">spring</font></span>容器中管理。它的作用和在xml文件中使用bean节点配置组件时一样的。要使用自动扫描机制，我们需要打开以下配置信息</span></span></p>
<div>
<div>&nbsp;</div>
<ol>
    <li><span><span>&lt;?xml&nbsp;<wbr>version=</span><span><font color="#0000ff">"1.0"</font></span><span>&nbsp;<wbr>encoding=</span><span><font color="#0000ff">"UTF-8"</font></span><span>&nbsp;<wbr>?&gt;&nbsp;<wbr>&lt;beans&nbsp;<wbr>xmlns=</span><span><font color="#0000ff">"http://www.springframework.org/schema/beans"</font></span><span>&nbsp;<wbr>xmlns:xsi=</span><span><font color="#0000ff">"http://www.w3.org/2001/XMLSchema-instance"</font></span><span>&nbsp;<wbr>xmlns:context=</span><span><font color="#0000ff">"http://www.springframework.org/schema/context"</font></span><span>&nbsp;<wbr>xsi:schemaLocation=</span><span><font color="#0000ff">"http://www.springframework.org/schema/beans&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>http://www.springframework.org/schema/beans/</font><span><font style="background-color: #55ff55">spring</font></span><font color="#0000ff">-beans-2.5.xsd&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>http://www.springframework.org/schema/context&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>http://www.springframework.org/schema/context/</font><span><font style="background-color: #55ff55">spring</font></span><font color="#0000ff">-context-2.5.xsd"</font></span><span>&nbsp;<wbr>&nbsp;<wbr></span></span>
    <li><span>&gt; &nbsp;<wbr>&nbsp;<wbr></span>
    <li><span>&nbsp;<wbr>&nbsp;<wbr></span>
    <li><span>&lt;context:component-scan&nbsp;<wbr>base-</span><span><strong><font color="#7f0055">package</font></strong></span><span>=&#8221;com.eric.<span><font style="background-color: #55ff55">spring</font></span>&#8221;&gt;&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr></span>
    <li><span>&lt;/beans&gt;&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr></span>
    <li><span>其中base-</span><span><strong><font color="#7f0055">package</font></strong></span><span>为需要扫描的包（含所有子包）&nbsp;<wbr></span><span><font color="#646464">@Service</font></span><span>用于标注业务层组件，</span><span><font color="#646464">@Controller</font></span><span>用于标注控制层组件（如struts中的action）,</span><span><font color="#646464">@Repository</font></span><span>用于标注数据访问组件，即DAO组件，而</span><span><font color="#646464">@Component</font></span><span>泛指组件，当组件不好归类的时候，我们可以使用这个注解进行标注。&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr></span>
    <li><span><font color="#646464">@Service</font></span><span>&nbsp;<wbr></span><span><strong><font color="#7f0055">public</font></strong></span><span>&nbsp;<wbr></span><span><strong><font color="#7f0055">class</font></strong></span><span>&nbsp;<wbr>VentorServiceImpl&nbsp;<wbr></span><span><strong><font color="#7f0055">implements</font></strong></span><span>&nbsp;<wbr>iVentorService&nbsp;<wbr>{&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr></span>
    <li><span>}&nbsp;<wbr></span><span><font color="#646464">@Repository</font></span><span>&nbsp;<wbr></span><span><strong><font color="#7f0055">public</font></strong></span><span>&nbsp;<wbr></span><span><strong><font color="#7f0055">class</font></strong></span><span>&nbsp;<wbr>VentorDaoImpl&nbsp;<wbr></span><span><strong><font color="#7f0055">implements</font></strong></span><span>&nbsp;<wbr>iVentorDao&nbsp;<wbr>{ &nbsp;<wbr>&nbsp;<wbr></span>
    <li><span>}&nbsp;<wbr>getBean的默认名称是类名（头字母小写），如果想自定义，可以</span><span><font color="#646464">@Service</font></span><span>(&#8220;aaaaa&#8221;)这样来指定，这种bean默认是单例的，如果想改变，可以使用</span><span><font color="#646464">@Service</font></span><span>(&#8220;beanName&#8221;)&nbsp;<wbr></span><span><font color="#646464">@Scope</font></span><span>(&#8220;prototype&#8221;)来改变。可以使用以下方式指定初始化方法和销毁方法（方法名任意）：&nbsp;<wbr></span><span><font color="#646464">@PostConstruct</font></span><span>&nbsp;<wbr></span><span><strong><font color="#7f0055">public</font></strong></span><span>&nbsp;<wbr></span><span><strong><font color="#7f0055">void</font></strong></span><span>&nbsp;<wbr>init()&nbsp;<wbr>{ &nbsp;<wbr>&nbsp;<wbr></span>
    <li><span>} &nbsp;<wbr>&nbsp;<wbr></span>
    <li><span><font color="#646464">@PreDestroy</font></span><span>&nbsp;<wbr></span><span><strong><font color="#7f0055">public</font></strong></span><span>&nbsp;<wbr></span><span><strong><font color="#7f0055">void</font></strong></span><span>&nbsp;<wbr>destory()&nbsp;<wbr>{ &nbsp;<wbr>&nbsp;<wbr></span> </li>
</ol>
</div>
</div>
<img src ="http://www.blogjava.net/gm_jing/aggbug/308709.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2010-01-08 13:53 <a href="http://www.blogjava.net/gm_jing/articles/308709.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】IoC容器在Web容器中的启动 </title><link>http://www.blogjava.net/gm_jing/articles/296025.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Tue, 22 Sep 2009 06:48:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/296025.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/296025.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/296025.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/296025.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/296025.html</trackback:ping><description><![CDATA[<div class="blog_content">上面我们分析了IOC容器本身的实现，下面我们看看在典型的web环境中，Spring IOC容器是怎样被载入和起作用的。 <br />
简单的说，在web容器中，通过ServletContext为Spring的IOC容器提供宿主环境，对应的建立起一个IOC容器的体系。其中，首先需要建立的是根上下文，这个上下文持有的对象可以有业务对象，数据存取对象，资源，事物管理器等各种中间层对象。在这个上下文的基础上，和web MVC相关还会有一个上下文来保存控制器之类的MVC对象，这样就构成了一个层次化的上下文结构。在web容器中启动Spring应用程序就是一个建立这个上下文体系的过程。Spring为web应用提供了上下文的扩展接口 <br />
WebApplicationContext: <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">interface</span><span>&nbsp;WebApplicationContext&nbsp;</span><span class="keyword">extends</span><span>&nbsp;ApplicationContext&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里定义的常量用于在ServletContext中存取根上下文 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE&nbsp;=&nbsp;WebApplicationContext.</span><span class="keyword">class</span><span>.getName()&nbsp;+&nbsp;</span><span class="string">".ROOT"</span><span>; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;...... &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//对WebApplicationContext来说，需要得到Web容器的ServletContext </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;ServletContext&nbsp;getServletContext(); &nbsp;&nbsp;</span>
    <li class="alt"><span>} &nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
&lt;script&gt;&lt;/script&gt; <br />
而一般的启动过程，Spring会使用一个默认的实现，XmlWebApplicationContext - 这个上下文实现作为在web容器中的根上下文容器被建立起来，具体的建立过程在下面我们会详细分析。 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;XmlWebApplicationContext&nbsp;</span><span class="keyword">extends</span><span>&nbsp;AbstractRefreshableWebApplicationContext&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/**&nbsp;这是和web部署相关的位置信息，用来作为默认的根上下文bean定义信息的存放位置*/</span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;String&nbsp;DEFAULT_CONFIG_LOCATION&nbsp;=&nbsp;</span><span class="string">"/WEB-INF/applicationContext.xml"</span><span>; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;String&nbsp;DEFAULT_CONFIG_LOCATION_PREFIX&nbsp;=&nbsp;</span><span class="string">"/WEB-INF/"</span><span>; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;String&nbsp;DEFAULT_CONFIG_LOCATION_SUFFIX&nbsp;=&nbsp;</span><span class="string">".xml"</span><span>; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//我们又看到了熟悉的loadBeanDefinition,就像我们前面对IOC容器的分析中一样，这个加载工程在容器的refresh()的时候启动。 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;loadBeanDefinitions(DefaultListableBeanFactory&nbsp;beanFactory)&nbsp;</span><span class="keyword">throws</span><span>&nbsp;IOException&nbsp;{ &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//对于XmlWebApplicationContext,当然使用的是XmlBeanDefinitionReader来对bean定义信息来进行解析 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XmlBeanDefinitionReader&nbsp;beanDefinitionReader&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;XmlBeanDefinitionReader(beanFactory); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;beanDefinitionReader.setResourceLoader(</span><span class="keyword">this</span><span>); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;beanDefinitionReader.setEntityResolver(</span><span class="keyword">new</span><span>&nbsp;ResourceEntityResolver(</span><span class="keyword">this</span><span>)); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;initBeanDefinitionReader(beanDefinitionReader); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loadBeanDefinitions(beanDefinitionReader); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;initBeanDefinitionReader(XmlBeanDefinitionReader&nbsp;beanDefinitionReader)&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//使用XmlBeanDefinitionReader来读入bean定义信息 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;loadBeanDefinitions(XmlBeanDefinitionReader&nbsp;reader)&nbsp;</span><span class="keyword">throws</span><span>&nbsp;BeansException,&nbsp;IOException&nbsp;{ &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[]&nbsp;configLocations&nbsp;=&nbsp;getConfigLocations(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(configLocations&nbsp;!=&nbsp;</span><span class="keyword">null</span><span>)&nbsp;{ &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">int</span><span>&nbsp;i&nbsp;=&nbsp;</span><span class="number">0</span><span>;&nbsp;i&nbsp;&lt;&nbsp;configLocations.length;&nbsp;i++)&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reader.loadBeanDefinitions(configLocations[i]); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里取得bean定义信息位置，默认的地方是/WEB-INF/applicationContext.xml </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span>&nbsp;String[]&nbsp;getDefaultConfigLocations()&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(getNamespace()&nbsp;!=&nbsp;</span><span class="keyword">null</span><span>)&nbsp;{ &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;String[]&nbsp;{DEFAULT_CONFIG_LOCATION_PREFIX&nbsp;+&nbsp;getNamespace()&nbsp;+&nbsp;DEFAULT_CONFIG_LOCATION_SUFFIX}; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">else</span><span>&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;String[]&nbsp;{DEFAULT_CONFIG_LOCATION}; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>} &nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
&lt;script&gt;&lt;/script&gt; <br />
对于一个Spring激活的web应用程序，可以通过使用Spring代码声明式的指定在web应用程序启动时载入应用程序上下文（WebApplicationContext),Spring的ContextLoader是提供这样性能的类，我们可以使用 ContextLoaderServlet或者ContextLoaderListener的启动时载入的Servlet来实例化Spring IOC容器 - 为什么会有两个不同的类来装载它呢，这是因为它们的使用需要区别不同的Servlet容器支持的Serlvet版本。但不管是 ContextLoaderSevlet还是 ContextLoaderListener都使用ContextLoader来完成实际的WebApplicationContext的初始化工作。这个ContextLoder就像是Spring Web应用程序在Web容器中的加载器booter。当然这些Servlet的具体使用我们都要借助web容器中的部署描述符来进行相关的定义。 <br />
下面我们使用ContextLoaderListener作为载入器作一个详细的分析，这个Servlet的监听器是根上下文被载入的地方，也是整个 Spring　web应用加载上下文的第一个地方；从加载过程我们可以看到，首先从Servlet事件中得到ServletContext，然后可以读到配置好的在web.xml的中的各个属性值，然后ContextLoder实例化WebApplicationContext并完成其载入和初始化作为根上下文。当这个根上下文被载入后，它被绑定到web应用程序的ServletContext上。任何需要访问该ApplicationContext的应用程序代码都可以从WebApplicationContextUtils类的静态方法来得到： <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span>WebApplicationContext&nbsp;getWebApplicationContext(ServletContext&nbsp;sc) &nbsp;&nbsp;</span></span> </li>
</ol>
</div>
</div>
&lt;script&gt;&lt;/script&gt; <br />
以Tomcat作为Servlet容器为例，下面是具体的步骤： <br />
1.Tomcat 启动时需要从web.xml中读取启动参数，在web.xml中我们需要对ContextLoaderListener进行配置，对于在web应用启动入口是在ContextLoaderListener中的初始化部分；从Spring MVC上看，实际上在web容器中维护了一系列的IOC容器，其中在ContextLoader中载入的IOC容器作为根上下文而存在于 ServletContext中。 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//这里对根上下文进行初始化。 </span><span>&nbsp;&nbsp;</span></span>
    <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;contextInitialized(ServletContextEvent&nbsp;event)&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里创建需要的ContextLoader </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.contextLoader&nbsp;=&nbsp;createContextLoader(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里使用ContextLoader对根上下文进行载入和初始化 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.contextLoader.initWebApplicationContext(event.getServletContext()); &nbsp;&nbsp;</span>
    <li class="alt"><span>} &nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
&lt;script&gt;&lt;/script&gt; <br />
通过ContextLoader建立起根上下文的过程,我们可以在ContextLoader中看到： <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">public</span><span>&nbsp;WebApplicationContext&nbsp;initWebApplicationContext(ServletContext&nbsp;servletContext) &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throws</span><span>&nbsp;IllegalStateException,&nbsp;BeansException&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里先看看是不是已经在ServletContext中存在上下文,如果有说明前面已经被载入过，或者是配置文件有错误。 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE)&nbsp;!=&nbsp;</span><span class="keyword">null</span><span>)&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//直接抛出异常 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;......... &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;............... &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;这里载入根上下文的父上下文 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ApplicationContext&nbsp;parent&nbsp;=&nbsp;loadParentContext(servletContext); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里创建根上下文作为整个应用的上下文同时把它存到ServletContext中去,注意这里使用的ServletContext的属性值是 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE，以后的应用都是根据这个属性值来取得根上下文的&nbsp;-&nbsp;往往作为自己上下文的父上下文 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.context&nbsp;=&nbsp;createWebApplicationContext(servletContext,&nbsp;parent); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;servletContext.setAttribute( &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,&nbsp;</span><span class="keyword">this</span><span>.context); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.......... &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">this</span><span>.context; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;............ &nbsp;&nbsp;</span>
    <li><span>} &nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
&lt;script&gt;&lt;/script&gt; <br />
建立根上下文的父上下文使用的是下面的代码，取决于在web.xml中定义的参数：locatorFactorySelector，这是一个可选参数： <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">protected</span><span>&nbsp;ApplicationContext&nbsp;loadParentContext(ServletContext&nbsp;servletContext) &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throws</span><span>&nbsp;BeansException&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;ApplicationContext&nbsp;parentContext&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;locatorFactorySelector&nbsp;=&nbsp;servletContext.getInitParameter(LOCATOR_FACTORY_SELECTOR_PARAM); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;parentContextKey&nbsp;=&nbsp;servletContext.getInitParameter(LOCATOR_FACTORY_KEY_PARAM); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(locatorFactorySelector&nbsp;!=&nbsp;</span><span class="keyword">null</span><span>)&nbsp;{ &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BeanFactoryLocator&nbsp;locator&nbsp;=&nbsp;ContextSingletonBeanFactoryLocator.getInstance(locatorFactorySelector); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;........ &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//得到根上下文的父上下文的引用 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.parentContextRef&nbsp;=&nbsp;locator.useBeanFactory(parentContextKey); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里建立得到根上下文的父上下文 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parentContext&nbsp;=&nbsp;(ApplicationContext)&nbsp;</span><span class="keyword">this</span><span>.parentContextRef.getFactory(); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;parentContext; &nbsp;&nbsp;</span>
    <li class="alt"><span>} &nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
&lt;script&gt;&lt;/script&gt; <br />
得到根上下文的父上下文以后，就是根上下文的创建过程： <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">protected</span><span>&nbsp;WebApplicationContext&nbsp;createWebApplicationContext( &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServletContext&nbsp;servletContext,&nbsp;ApplicationContext&nbsp;parent)&nbsp;</span><span class="keyword">throws</span><span>&nbsp;BeansException&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里需要确定我们载入的根WebApplication的类型，由在web.xml中配置的contextClass中配置的参数可以决定我们需要载入什么样的ApplicationContext, </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//如果没有使用默认的。 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;Class&nbsp;contextClass&nbsp;=&nbsp;determineContextClass(servletContext); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;......... &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里就是上下文的创建过程 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;ConfigurableWebApplicationContext&nbsp;wac&nbsp;= &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ConfigurableWebApplicationContext)&nbsp;BeanUtils.instantiateClass(contextClass); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里保持对父上下文和ServletContext的引用到根上下文中 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;wac.setParent(parent); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;wac.setServletContext(servletContext); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里从web.xml中取得相关的初始化参数 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;configLocation&nbsp;=&nbsp;servletContext.getInitParameter(CONFIG_LOCATION_PARAM); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(configLocation&nbsp;!=&nbsp;</span><span class="keyword">null</span><span>)&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation, &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS)); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里对WebApplicationContext进行初始化，我们又看到了熟悉的refresh调用。 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;wac.refresh(); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;wac; &nbsp;&nbsp;</span>
    <li class="alt"><span>} &nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
&lt;script&gt;&lt;/script&gt; <br />
初始化根ApplicationContext后将其存储到SevletContext中去以后,这样就建立了一个全局的关于整个应用的上下文。这个根上下文会被以后的DispatcherServlet初始化自己的时候作为自己ApplicationContext的父上下文。这个在对 DispatcherServlet做分析的时候我们可以看看到。
<p>&nbsp;</p>
<p>3.完成对ContextLoaderListener的初始化以后， Tomcat开始初始化DispatchServlet，- 还记得我们在web.xml中队载入次序进行了定义。DispatcherServlet会建立自己的ApplicationContext,同时建立这个自己的上下文的时候会从ServletContext中得到根上下文作为父上下文,然后再对自己的上下文进行初始化，并最后存到 ServletContext中去供以后检索和使用。 <br />
可以从DispatchServlet的父类FrameworkServlet的代码中看到大致的初始化过程，整个ApplicationContext的创建过程和ContextLoder创建的过程相类似：</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;initServletBean()&nbsp;</span><span class="keyword">throws</span><span>&nbsp;ServletException,&nbsp;BeansException&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;......... &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;{ &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里是对上下文的初始化过程。 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.webApplicationContext&nbsp;=&nbsp;initWebApplicationContext(); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//在完成对上下文的初始化过程结束后，根据bean配置信息建立MVC框架的各个主要元素 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;initFrameworkServlet(); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;........ &nbsp;&nbsp;</span>
    <li><span>} &nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
&lt;script&gt;&lt;/script&gt; <br />
对initWebApplicationContext()调用的代码如下： <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">protected</span><span>&nbsp;WebApplicationContext&nbsp;initWebApplicationContext()&nbsp;</span><span class="keyword">throws</span><span>&nbsp;BeansException&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里调用WebApplicationContextUtils静态类来得到根上下文 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;WebApplicationContext&nbsp;parent&nbsp;=&nbsp;WebApplicationContextUtils.getWebApplicationContext(getServletContext()); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//创建当前DispatcherServlet的上下文，其上下文种类使用默认的在FrameworkServlet定义好的：DEFAULT_CONTEXT_CLASS&nbsp;=&nbsp;XmlWebApplicationContext.class; </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;WebApplicationContext&nbsp;wac&nbsp;=&nbsp;createWebApplicationContext(parent); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;........ &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(isPublishContext())&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//把当前建立的上下文存到ServletContext中去，注意使用的属性名是和当前Servlet名相关的。 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;attrName&nbsp;=&nbsp;getServletContextAttributeName(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getServletContext().setAttribute(attrName,&nbsp;wac); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;wac; &nbsp;&nbsp;</span>
    <li><span>} &nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
&lt;script&gt;&lt;/script&gt; <br />
其中我们看到调用了WebApplicationContextUtils的静态方法得到根ApplicationContext: <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;WebApplicationContext&nbsp;getWebApplicationContext(ServletContext&nbsp;sc)&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//很简单，直接从ServletContext中通过属性名得到根上下文 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;attr&nbsp;=&nbsp;sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;....... &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;(WebApplicationContext)&nbsp;attr; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class="alt"><span>然后创建DispatcherServlet自己的WebApplicationContext: &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span>&nbsp;WebApplicationContext&nbsp;createWebApplicationContext(WebApplicationContext&nbsp;parent) &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throws</span><span>&nbsp;BeansException&nbsp;{ &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;....... &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里使用了BeanUtils直接得到WebApplicationContext,ContextClass是前面定义好的DEFAULT_CONTEXT_CLASS&nbsp;=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//XmlWebApplicationContext.class; </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ConfigurableWebApplicationContext&nbsp;wac&nbsp;= &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ConfigurableWebApplicationContext)&nbsp;BeanUtils.instantiateClass(getContextClass()); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里配置父上下文，就是在ContextLoader中建立的根上下文 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wac.setParent(parent); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//保留ServletContext的引用和相关的配置信息。 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wac.setServletContext(getServletContext()); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wac.setServletConfig(getServletConfig()); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wac.setNamespace(getNamespace()); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里得到ApplicationContext配置文件的位置 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(getContextConfigLocation()&nbsp;!=&nbsp;</span><span class="keyword">null</span><span>)&nbsp;{ &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wac.setConfigLocations( &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringUtils.tokenizeToStringArray( &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getContextConfigLocation(),&nbsp;ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS)); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里调用ApplicationContext的初始化过程，同样需要使用refresh() </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wac.refresh(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;wac; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
&lt;script&gt;&lt;/script&gt; <br />
4. 然后就是DispatchServlet中对Spring MVC的配置过程，首先对配置文件中的定义元素进行配置 - 请注意这个时候我们的WebApplicationContext已经建立起来了，也意味着DispatcherServlet有自己的定义资源，可以需要从web.xml中读取bean的配置信息，通常我们会使用单独的xml文件来配置MVC中各个要素定义，这里和web容器相关的加载过程实际上已经完成了，下面的处理和普通的Spring应用程序的编写没有什么太大的差别，我们先看看MVC的初始化过程： <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;initFrameworkServlet()&nbsp;</span><span class="keyword">throws</span><span>&nbsp;ServletException,&nbsp;BeansException&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;initMultipartResolver(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;initLocaleResolver(); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;initThemeResolver(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;initHandlerMappings(); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;initHandlerAdapters(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;initHandlerExceptionResolvers(); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;initRequestToViewNameTranslator(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;initViewResolvers(); &nbsp;&nbsp;</span>
    <li><span>} &nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
&lt;script&gt;&lt;/script&gt; <br />
5. 这样MVC的框架就建立起来了，DispatchServlet对接受到的HTTP Request进行分发处理由doService()完成，具体的MVC处理过程我们在doDispatch()中完成，其中包括使用Command模式建立执行链，显示模型数据等，这些处理我们都可以在DispatcherServlet的代码中看到： <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;doService(HttpServletRequest&nbsp;request,&nbsp;HttpServletResponse&nbsp;response)&nbsp;</span><span class="keyword">throws</span><span>&nbsp;Exception&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;...... &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;{ &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;doDispatch(request,&nbsp;response); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;....... &nbsp;&nbsp;</span>
    <li class="alt"><span>} &nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
&lt;script&gt;&lt;/script&gt; <br />
实际的请求分发由doDispatch(request,response)来完成： <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;doDispatch(</span><span class="keyword">final</span><span>&nbsp;HttpServletRequest&nbsp;request,&nbsp;HttpServletResponse&nbsp;response)&nbsp;</span><span class="keyword">throws</span><span>&nbsp;Exception&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;....... &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;这是Spring定义的执行链，里面放了映射关系对应的handler和定义的相关拦截器。 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HandlerExecutionChain&nbsp;mappedHandler&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...... &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;{ &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//我们熟悉的ModelAndView在这里出现了。 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ModelAndView&nbsp;mv&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;processedRequest&nbsp;=&nbsp;checkMultipart(request); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里更具request中的参数和映射关系定义决定使用的handler </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mappedHandler&nbsp;=&nbsp;getHandler(processedRequest,&nbsp;</span><span class="keyword">false</span><span>); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...... &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里是handler的调用过程，类似于Command模式中的execute. </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HandlerAdapter&nbsp;ha&nbsp;=&nbsp;getHandlerAdapter(mappedHandler.getHandler()); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mv&nbsp;=&nbsp;ha.handle(processedRequest,&nbsp;response,&nbsp;mappedHandler.getHandler()); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;....... &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里将模型数据通过视图进行展现 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(mv&nbsp;!=&nbsp;</span><span class="keyword">null</span><span>&nbsp;&amp;&amp;&nbsp;!mv.wasCleared())&nbsp;{ &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;render(mv,&nbsp;processedRequest,&nbsp;response); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;........ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
&lt;script&gt;&lt;/script&gt; <br />
这样具体的MVC模型的实现就由bean配置文件里定义好的view resolver,handler这些类来实现用户代码的功能。 <br />
总结上面的过程，我们看到在web容器中，ServletContext可以持有一系列的web上下文，而在整个web上下文中存在一个根上下文来作为其它 Servlet上下文的父上下文。这个根上下文是由ContextLoader载入并进行初始化的，对于我们的web应用， DispatcherSerlvet载入并初始化自己的上下文,这个上下文的父上下文是根上下文，并且我们也能从ServletContext中根据 Servlet的名字来检索到我们需要的对应于这个Servlet的上下文，但是根上下文的名字是由Spring唯一确定的。这个 DispactcherServlet建立的上下文就是我们开发Spring MVC应用的IOC容器。 <br />
具体的web请求处理在上下文体系建立完成以后由DispactcherServlet来完成，上面对MVC的运作做了一个大致的描述，下面我们会具体就SpringMVC的框架实现作一个详细的分析。 </div>
<img src ="http://www.blogjava.net/gm_jing/aggbug/296025.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2009-09-22 14:48 <a href="http://www.blogjava.net/gm_jing/articles/296025.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring 初始化之旅(转)</title><link>http://www.blogjava.net/gm_jing/articles/252458.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Fri, 23 Jan 2009 07:50:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/252458.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/252458.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/252458.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/252458.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/252458.html</trackback:ping><description><![CDATA[<table cellspacing="1" cellpadding="4" width="100%" border="0">
    <tbody>
        <tr>
            <td valign="top">
            <div><strong>Spring源码学习</strong></div>
            </td>
        </tr>
        <tr>
            <td valign="top">
            <table width="200" align="right" border="0">
                <tbody>
                    <tr>
                        <td>&nbsp;</td>
                    </tr>
                </tbody>
            </table>
            <p><strong>一、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </strong><strong>概述 &lt;o:p&gt;&lt;/o:p&gt;</strong></p>
            <p><strong>二、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </strong><strong>Spring </strong><strong>初始化之旅 &lt;o:p&gt;&lt;/o:p&gt;</strong></p>
            <p>a)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Spring 初始化的时候首先要运行的类为： org.springframework.web.context. ContextLoaderListener 或 org.springframework.web.context. ContextLoaderServlet 。 </p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 它们在初始化函数里无一例外地实例化了 ContextLoader 类 , 然后调用了它的函数 &nbsp;&nbsp;&nbsp;&nbsp; public WebApplicationContext initWebApplicationContext(ServletContext ) 。 </p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接下来看一下在这个方法里干了写什么 </p>
            <p>b)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在他的方法体内，关键是&#8220; this.context = createWebApplicationContext(servletContext, parent); &#8221;新建了一个&#8220; ConfigurableWebApplicationContext &#8221;类型的对象，在这一步实例化中几乎完成了所有的 spring 初始化工作。读取了所有的 spring 配置文件。它的工作步骤如下所述。 </p>
            <p>c)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先，在将&#8220; ConfigurableWebApplicationContext &#8221;类型的对象实例化以后（这个对象实际的类型是这个包内的 XmlWebApplicationContext ），然后又给这个实例设置了三个属性，&#8220; wac.setParent(parent); &#8221;在默认的初始化过程中这一步设置了一个 null 值，然后又设置了一个&#8220; wac.setServletContext(servletContext); &#8221;，将系统默认的上下文设置进来，比较重要的是下面这一段： &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (configLocation != null) { </p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 读取 spring 的应用配置文件 </p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation,Configurabl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eWebApplicationContext.CONFIG_LOCATION_DELIMITERS)); </p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 它将我们的配置文件名放置到 wac 变量中，以待在后续的操作中使用。然后调用 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220; wac.refresh(); &#8221;完成主要的初始化 BeanFactory 的操作。如下。 </p>
            <p>d)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先我们应该看一下我们实例化的对象 </p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.springframework.web.context.support.XmlWebApplicationContext 的类图： </p>
            <p>&nbsp;<img alt="" src="http://wq-pro.javaeye.com/upload/picture/pic/1928/5314bc0e-b237-44af-b323-d2deb7815612.jpg" _counted="undefined" /></p>
            <p>&lt;o:p&gt;&nbsp;&lt;/o:p&gt; </p>
            <p>e)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220; wac.refresh(); &#8221;从类结构里我们能找到这个方法来自它的父类： AbstractApplicationContext 在它的 refresh() 方法内我们可以看到 spring 的复杂逻辑。 </p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先执行了 refreshBeanFactory(); （来自 AbstractRefreshableApplicationContext ）见 f), </p>
            <p>f)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; refreshBeanFactory(); 这个方法由负责维护变量 beanFactory 的子类 AbstractRefreshableApplicationContext 实现，默认情况下这个方法直接实例化一个新的 DefaultListableBeanFactory 类型的 BeanFacorty, 然后调用一个起缓冲作用的配置函数生成一个将 beanFacroty 包装起来的对象 beanDefinitionReader ，然后对这个对象进行属性配置，实际上该方法主要负责生成一个临时的操作对象，对应调用的函数为&#8220; loadBeanDefinitions(beanFactory); &#8221;该方法为初始化期间较为重要的一个。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 该方法来自其子类： AbstractRefreshableWebApplicationContext 对应的函数： </p>
            <p>protected void loadBeanDefinitions(DefaultListableBeanFactory) ，然后这里又调用了自己定义的 protected void loadBeanDefinitions(XmlBeanDefinitionReader) 方法。此时，它就使用到了在 c) 中设置了的（ wac.setConfigLocations(&#8230;&#8230;)) 我们开发中密切相关的配置文件。（同时也要记住此时这个函数的参数 beanDefinitionReader ，之前已经设置了&#8220; <strong>beanDefinitionReader.setResourceLoader(this); </strong>&#8221;这里的 this 是我们在前面见到的 <strong>XmlWebApplicationContext </strong>（一个定义好了的上下文））。接着往下： </p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220; reader.loadBeanDefinitions(configLocations[i]); &#8221; reader 开始加载我们配置文件内的东西了，不过真正复杂的实现此时才开始，我们继续往下走，在接下来的方法内默认情况下会执行： </p>
            <p>if (resourceLoader instanceof ResourcePatternResolver) （该判断条件为 true ） , 由于从上面我们知道： <strong>beanDefinitionReader.setResourceLoader(this); </strong>而 this 的类型为： <strong>XmlWebApplicationContext </strong>所以 <strong>((ResourcePatternResolver) resourceLoader).getResources(location); </strong>得到一个 Resource[] 数组，接下来调用： </p>
            <p><strong>int loadCount = loadBeanDefinitions(resources); </strong>该函数继续调用自己子类定义的一系列临时接口最终执行到 <strong>return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); </strong>在这个函数内初始化了处理 xml 文件的一些对象并将用户的配置文件解析为一个 Document 对象。然后又执行了一系列函数直到 </p>
            <p><strong>return parser.registerBeanDefinitions(this, doc, resource); </strong>这个函数来自我们新建的 DefaultXmlBeanDefinitionParser ，在这个类里最终执行了对 xml 文件的解析工作和对 beanFacroty 变量执行了设置工作。 </p>
            <p>g)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 终于我们从这些繁杂的逻辑中跳了出来，继续执行 AbstractApplicationContext.refresh() 下面的工作，后续的代码主要仍旧是往一些常量里面设值。 </p>
            <p>此时 spring 初始化过程就结束了</p>
            <p><br />
            评述：启动过程如下：<br />
            1.创建一个ApplicationContext的实例ac<br />
            2.读取配置文件，ac简单的设置（比如有多少bean）<br />
            3.所有的beanfactory后处理开始以此执行<br />
            4.开始创建bean的实例<br />
            5.进行注入（如果有其他bean，迭代执行）<br />
            6.如何实现一些接口（BeanFactoryAware, BeanNameAware）以此该bean执行相应方法<br />
            7.所有的bean后处理开始执行,中间如果实现InitializingBean，该bean执行相应方法）<br />
            </p>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/gm_jing/aggbug/252458.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2009-01-23 15:50 <a href="http://www.blogjava.net/gm_jing/articles/252458.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring中ContextLoaderListenter和ContextLoaderPlugIn的区别</title><link>http://www.blogjava.net/gm_jing/articles/137254.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Thu, 16 Aug 2007 06:39:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/137254.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/137254.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/137254.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/137254.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/137254.html</trackback:ping><description><![CDATA[<div class=date>&nbsp;</div>
<table style="TABLE-LAYOUT: fixed">
    <tbody>
        <tr>
            <td>
            <div class=cnt>
            <p><font face=verdana,arial,helvetica,sans-serif>spring中提供 </font><font face=新宋体><tt class=literal>ContextLoaderListenter类，用来加载context的xml文件。</tt></font></p>
            <p><tt class=literal><font face=新宋体>spring为struts提供<span class=bt>ContextLoaderPlugIn类，此类也可以加载context的xml文件。</span></font></tt></p>
            <p><font face=verdana,arial,helvetica,sans-serif><tt class=literal><span class=bt><font face=新宋体>区别在于，两种方式加载的WebApplicationContext，以不同的Key存放在ServletContext中。而如果你定义了HibernateFilter的话，spring会利用WebApplicationContextUtils来获取WebApplicationContext，</font><font face=verdana,arial,helvetica,sans-serif>而此类并不识别<span class=bt>ContextLoaderPlugIn类所加载的上下文，此时便会抛出异常： No WebApplicationContext found: no ContextLoaderListener registered?</span></font></span></tt></font></p>
            <p><font face=verdana,arial,helvetica,sans-serif><tt class=literal><span class=bt><font face=verdana,arial,helvetica,sans-serif><span class=bt></span></font></span></tt></font><font face=verdana,arial,helvetica,sans-serif><tt class=literal><span class=bt><font face=verdana,arial,helvetica,sans-serif><span class=bt>利用<font face=新宋体>ContextLoaderListenter来加载dao、service级别的context</font><font face=verdana,arial,helvetica,sans-serif>，而对于struts的action，用</font><font face=新宋体><span class=bt>ContextLoaderPlugIn加载。</span></font></span></font></span></tt></font></p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/gm_jing/aggbug/137254.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2007-08-16 14:39 <a href="http://www.blogjava.net/gm_jing/articles/137254.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>事务管理方式</title><link>http://www.blogjava.net/gm_jing/articles/133545.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Tue, 31 Jul 2007 04:19:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/133545.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/133545.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/133545.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/133545.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/133545.html</trackback:ping><description><![CDATA[<p>1． 依赖特定事务资源的事务处理<br>这是应用开发中最常见的模式，即通过特定资源提供的事务机制进行事务管理。<br>如通过JDBC、JTA 的rollback、commit方法；Hibernate Transaction 的rollback、commit方法等。<br>这种方法大家已经相当熟悉。</p>
<p><br>2． 依赖容器的参数化事务管理<br>通过容器提供的集约式参数化事务机制，实现事务的外部管理，如EJB 中的事务管理模式。<br>&nbsp;容器管理的参数化事务为程序开发提供了相当的灵活性，同时因为将事务委托给容器进行管理，<br>应用逻辑中无需再编写事务代码，大大节省了代码量（特别是针对需要同时操作多个事务资源的应用），从而提高了生产率。<br></p>
<br><br><br><br>
<hr>
<div class=postcontent><font size=2>【引用】</font> <a href="http://www.blogjava.net/georgehill/archive/2005/07/08/7374.html"><font color=#366900>http://www.blogjava.net/georgehill/archive/2005/07/08/7374.html</font></a>&nbsp;<br><br>事务的4个基本特性（ACID）：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. Atomic（原子性）：事务中包含的操作被看作一个逻辑单元，这个逻辑单元中的操作要么全部成功，要么全部失败。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. Consistency（一致性）：只有合法的数据可以被写入数据库，否则事务应该将其回滚到最初状态。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. Isolation（隔离性）：事务允许多个用户对同一个数据的并发访问，而不破坏数据的正确性和完整性。同时，并行事务的修改必须与其他并行事务的修改相互独立。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. Durability（持久性）：事务结束后，事务处理的结果必须能够得到固化。
<hr>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;数据库操作过程中可能出现的3种不确定情况：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. 脏读取（Dirty Reads）：一个事务读取了另一个并行事务未提交的数据。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. 不可重复读取（Non-repeatable Reads）：一个事务再次读取之前的数据时，得到的数据不一致，被另一个已提交的事务修改。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. 虚读（Phantom Reads）：一个事务重新执行一个查询，返回的记录中包含了因为其他最近提交的事务而产生的新记录。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;标准SQL规范中，为了避免上面3种情况的出现，定义了4个事务隔离等级：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. Read Uncommitted：最低等级的事务隔离，仅仅保证了读取过程中不会读取到非法数据。上诉3种不确定情况均有可能发生。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. Read Committed：大多数主流数据库的默认事务等级，保证了一个事务不会读到另一个并行事务已修改但未提交的数据，避免了&#8220;脏读取&#8221;。该级别适用于大多数系统。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. Repeatable Read：保证了一个事务不会修改已经由另一个事务读取但未提交（回滚）的数据。避免了&#8220;脏读取&#8221;和&#8220;不可重复读取&#8221;的情况，但是带来了更多的性能损失。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. Serializable：最高等级的事务隔离，上面3种不确定情况都将被规避。这个级别将模拟事务的串行执行。
<hr>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Hibernate将事务管理委托给底层的JDBC或者JTA，默认是基于JDBC Transaction的。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Hibernate支持&#8220;悲观锁（Pessimistic Locking）&#8221;和&#8220;乐观锁（Optimistic Locking）&#8221;。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;悲观锁对数据被外界修改持保守态度，因此，在整个数据处理过程中，将数据处于锁定状态。悲观锁的实现，往往依靠数据库提供的锁机制。Hibernate通过使用数据库的for update子句实现了悲观锁机制。Hibernate的加锁模式有：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. LockMode.NONE：无锁机制<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. LockMode.WRITE：Hibernate在Insert和Update记录的时候会自动获取<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. LockMode.READ：Hibernate在读取记录的时候会自动获取<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. LockMode.UPGRADE：利用数据库的for update子句加锁<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5. LockMode.UPGRADE_NOWAIT：Oracle的特定实现，利用Oracle的for update nowait子句实现加锁<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;乐观锁大多是基于数据版本（Version）记录机制实现。Hibernate在其数据访问引擎中内置了乐观锁实现，可以通过class描述符的optimistic-lock属性结合version描述符指定。optimistic-lock属性有如下可选取值：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. none：无乐观锁<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. version：通过版本机制实现乐观锁<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. dirty：通过检查发生变动过的属性实现乐观锁<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. all：通过检查所有属性实现乐观锁 </div>
<img src ="http://www.blogjava.net/gm_jing/aggbug/133545.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2007-07-31 12:19 <a href="http://www.blogjava.net/gm_jing/articles/133545.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring 配置——PropertyPlaceholderConfigurer，PropertyOverrideConfigurer</title><link>http://www.blogjava.net/gm_jing/articles/127893.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Tue, 03 Jul 2007 08:51:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/127893.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/127893.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/127893.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/127893.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/127893.html</trackback:ping><description><![CDATA[&nbsp;&lt;!-- 属性文件读入 --&gt;<br>&nbsp;&lt;bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt;<br>&nbsp;&nbsp;&lt;property name="locations"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;list&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;classpath*:config/jdbc.properties&lt;/value&gt;<br>&nbsp;&nbsp;&nbsp;&lt;/list&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&lt;/bean&gt;<br><br><br>&lt;!-- 数据源定义,使用Apache DBCP 连接池 --&gt;<br>&nbsp;&lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt;<br>&nbsp;&nbsp;&lt;property name="driverClassName" value="${jdbc.driverClassName}"/&gt;<br>&nbsp;&nbsp;&lt;property name="url" value="${jdbc.url}"/&gt;<br>&nbsp;&nbsp;&lt;property name="username" value="${jdbc.username}"/&gt;<br>&nbsp;&nbsp;&lt;property name="password" value="${jdbc.password}"/&gt;<br>&nbsp;&lt;/bean&gt;<br><br><br><span id=DataList1_ctl00_summary>PropertyPlaceholderConfigurer可以将${...}替换为指定的properties文件或system properties中的值。<br></span>${jdbc.username} 从jdbc.properties文件中找到相应的替换。 <br><br>
<hr>
<br>不同于PropertyPlaceholderConfigurer 替换context文件中的变量，PropertyOverrideConfigurer是在ApplicationContext 初始化的最后，强行将某些Bean的某些属性，替换成它的properties文件里的值。
<p>&nbsp;&nbsp;&nbsp; 比如生产环境的jdbc.properties里定义了jdbc连接为Oracle，并通过PlaceholderConfigurer设置到&lt;bean id="dataSource"&gt; 里，在测试时再载入下面的applicationContex-test.xml文件，就能透明的将配置更改为嵌入式数据库。</p>
<p><strong>applicationContext-test.xml:</strong> 定义载入的properties。</p>
<div class=preformatted>
<div class=preformattedContent>
<pre>&lt;bean id="testPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyOverrideConfigurer"&gt;
&lt;property name="location" value="classpath:spring/test/jdbc.properties"/&gt;
&lt;/bean&gt;
</pre>
</div>
</div>
<p><strong>spring/test/jdbc.properties</strong>: 将ApplicationContext 中id为dataSource的bean的url属性改为使用hsqldb。</p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/127893.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2007-07-03 16:51 <a href="http://www.blogjava.net/gm_jing/articles/127893.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring 问题</title><link>http://www.blogjava.net/gm_jing/articles/127801.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Tue, 03 Jul 2007 04:07:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/127801.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/127801.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/127801.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/127801.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/127801.html</trackback:ping><description><![CDATA[<p>1、如何学习Spring？ </p>
<p>你可以通过下列途径学习spring： </p>
<p>(1) spring下载包中doc目录下的MVC-step-by-step和sample目录下的例子都是比较好的spring开发的例子。 </p>
<p>(2) AppFuse集成了目前最流行的几个开源轻量级框架或者工具Ant,XDoclet,Spring,Hibernate(iBATIS),JUnit,Cactus,StrutsTestCase,Canoo's WebTest,Struts Menu,Display Tag Library,OSCache,JSTL,Struts 。 </p>
<p>你可以通过AppFuse源代码来学习spring。 </p>
<p>AppFuse网站：<a href="http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuse">http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuse</a> </p>
<p>(3)Spring 开发指南(夏昕)（<a href="http://www.xiaxin.net/Spring_Dev_Guide.rar">http://www.xiaxin.net/Spring_Dev_Guide.rar</a>） </p>
<p>一本spring的入门书籍,里面介绍了反转控制和依赖注射的概念，以及spring的bean管理，spring的MVC，spring和hibernte，iBatis的结合。 </p>
<p>(4) spring学习的中文论坛 </p>
<p>SpringFramework中文论坛(<a href="http://spring.jactiongroup.net/">http://spring.jactiongroup.net</a>) </p>
<p>Java视线论坛(<a href="http://forum.javaeye.com/">http://forum.javaeye.com</a>)的spring栏目 </p>
<p>&nbsp;</p>
<p>2、利用Spring框架编程，console打印出log4j:WARN Please initialize the log4j system properly？ </p>
<p>说明你的log4j.properties没有配置。请把log4j.properties放到工程的classpath中，eclipse的classpath为bin目录，由于编译后src目录下的文件会拷贝到bin目录下，所以你可以把log4j.properties放到src目录下。 </p>
<p>这里给出一个log4j.properties的例子： </p>
<p>log4j.rootLogger=DEBUG,stdout </p>
<p>log4j.appender.stdout=org.apache.log4j.ConsoleAppender </p>
<p>log4j.appender.stdout.layout=org.apache.log4j.PatternLayout </p>
<p>log4j.appender.stdout.layout.ConversionPattern=%d %5p (%F:%L) - %m%n </p>
<p>&nbsp;</p>
<p>3、出现 java.lang.NoClassDefFoundError? </p>
<p>一般情况下是由于你没有把必要的jar包放到lib中。 </p>
<p>比如你要采用spring和hibernate（带事务支持的话），你除了spring.jar外还需要hibernat.jar、aopalliance.jar、cglig.jar、jakarta-commons下的几个jar包。 </p>
<p><a href="http://www.springframework.org/download.html">http://www.springframework.org/download.html</a>下载spring开发包，提供两种zip包 <br>建议你下载开发包。这个zip解压缩后比后者多一个lib目录，其中有hibernate、j2ee、dom4j、aopalliance、jakarta-commons等常用包。 <br></p>
<p>4、java.io.FileNotFoundException: Could not open class path resource [....hbm.xml],提示找不到xml文件？ </p>
<p>原因一般有两个： </p>
<p>(1)该xml文件没有在classpath中。 </p>
<p>(2)applicationContext-hibernate.xml中的xml名字没有带包名。比如： </p>
<p>User.hbm.xml 错，改为： com/yz/spring/domain/User.hbm.xml </p>
<p>net.sf.hibernate.dialect.MySQLDialect true <br></p>
<p>5、org.springframework.beans.NotWritablePropertyException: Invalid property 'postDao' of bean class？ </p>
<p>出现异常的原因是在application-xxx.xml中property name的错误。 中name的名字是与bean的set方法相关的，而且要注意大小写。 </p>
<p>比如 </p>
<p>public class PostManageImpl extends BaseManage implements PostManage { </p>
<p>private PostDAO dao = null; </p>
<p>public void setPostDAO(PostDAO postDAO){ </p>
<p>this.dao = postDAO; </p>
<p>} </p>
<p>} </p>
<p>那么xml的定义应该是： </p>
<p>对 错 <br></p>
<p>6、Spring中如何实现事务管理？ </p>
<p>首先，如果使用mysql，确定mysql为InnoDB类型。 </p>
<p>事务管理的控制应该放到商业逻辑层。你可以写个处理商业逻辑的JavaBean，在该JavaBean中调用DAO，然后把该Bean的方法纳入spring的事务管理。 </p>
<p>比如：xml文件定义如下： </p>
<p>class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt; PROPAGATION_REQUIRED PROPAGATION_REQUIRED PROPAGATION_REQUIRED </p>
<p>com.yz.spring.service.implement.UserManageImpl就是我们的实现商业逻辑的JavaBean。我们通过parent元素声明其事务支持。 <br></p>
<p>7、如何管理Spring框架下更多的JavaBean？ </p>
<p>JavaBean越多，spring配置文件就越大，这样不易维护。为了使配置清晰，我们可以将JavaBean分类管理，放在不同的配置文件中。 应用启动时将所有的xml同时加载。 </p>
<p>比如： </p>
<p>DAO层的JavaBean放到applicationContext-hibernate.xml中，商业逻辑层的JavaBean放到applicationContext-service.xml中。然后启动类中调用以下代码载入所有的ApplicationContext。 <br>String[] paths = {"com/yz/spring/dao/hibernate/applicationContext-hibernate.xml", </p>
<p>"com/yz/spring/service/applicationContext-service.xml"}; </p>
<p>ctx = new ClassPathXmlApplicationContext(paths); <br></p>
<p>8、web应用中如何加载ApplicationContext？ </p>
<p>可以通过定义web.xml，由web容器自动加载。 </p>
<p>context </p>
<p>org.springframework.web.context.ContextLoaderServlet </p>
<p>1 </p>
<p>contextConfigLocation /WEB-INF/applicationContext-hibernate.xml /WEB-INF/applicationContext-service.xml <br></p>
<p>9、在spring中如何配置的log4j? </p>
<p>在web.xml中加入以下代码即可。 </p>
<p>log4jConfigLocation /WEB-INF/log4j.properties <br></p>
<p>10、Spring框架入门的编程问题解决了，我该如何更深地领会Spring框架呢？ </p>
<p>这两本书你该去看看。这两本书是由Spring的作者Rod Johnson编写的。 </p>
<p>Expert One on one J2EE Design and Development </p>
<p>Expert One on one J2EE Development Without EJB </p>
<p>你也该看看martinfowler的Inversion of Control Containers and the Dependency Injection pattern。 </p>
<p><a href="http://www.martinfowler.com/articles/injection.html">http://www.martinfowler.com/articles/injection.html</a> </p>
<p>再好好研读一下spring的文档。 </p>
<p><a href="http://www.jactiongroup.net/reference/html/">http://www.jactiongroup.net/reference/html/</a> </p>
<p><br>&nbsp;</p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/127801.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2007-07-03 12:07 <a href="http://www.blogjava.net/gm_jing/articles/127801.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring事务类型祥解</title><link>http://www.blogjava.net/gm_jing/articles/126022.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Mon, 25 Jun 2007 01:31:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/126022.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/126022.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/126022.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/126022.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/126022.html</trackback:ping><description><![CDATA[<h2><a id=viewpost1_TitleUrl href="http://www.blogjava.net/DenisLing/archive/2005/12/18/spring.html"><u><font color=#810081>Spring事务类型祥解</font></u></a> </h2>
<p>大家可能在spring中经常看到这样的定义：</p>
<p><br></p>
<p>&lt;prop key="load*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt;&lt;prop key="store*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;</p>
<p>估计有好多朋友还没有弄清楚里面的值的意思，仔细看完下面应该知道自己什么情况下面应该使用什么样的声明。^_^<br></p>
<p><br></p>
<p>Spring中常用事务类型：<br></p>
<ul>
    <li>PROPAGATION_REQUIRED--支持当前事务，如果当前没有事务，就新建一个事务。这是最常见的选择。
    <li>PROPAGATION_SUPPORTS--支持当前事务，如果当前没有事务，就以非事务方式执行。
    <li>PROPAGATION_MANDATORY--支持当前事务，如果当前没有事务，就抛出异常。
    <li>PROPAGATION_REQUIRES_NEW--新建事务，如果当前存在事务，把当前事务挂起。
    <li>PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作，如果当前存在事务，就把当前事务挂起。
    <li>PROPAGATION_NEVER--以非事务方式执行，如果当前存在事务，则抛出异常。
    <li>PROPAGATION_NESTED--如果当前存在事务，则在嵌套事务内执行。如果当前没有事务，则进行与PROPAGATION_REQUIRED类似的操作。<br></li>
</ul>
<p>EJB的事务类型：<br></p>
<p><br></p>
<p>Nerver&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;不参与事务,如果参与产生RemoteException<br>NotSupported:&nbsp;&nbsp;&nbsp;不能参与<br>Supports:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果调用者正在参与事务,相应的EJB调用也可以参与事务,否则不能<br>Mandatory&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果调用者有一个事务,相应的EJB可以参与事务,否则,Transaction<span>Required</span>Exception<br><span>Required</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果调用者有一个事务,相应的EJB可以参与事务,否则,容器将在调用相应的EJB之前,开始一个事务.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;当方法调用完成以后,即提交该事务.<br>RequiresNew&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在调用相应的EJB之前,开始一个新的事务,当方法调用返回时,即提交这个事务.<br><br></p>
<p><br></p>
<p>　　前六个策略类似于EJB CMT：常量名相同，因此，对EJB开发人员来说，应该立刻就感到熟悉。第七个（PROPAGATION_NESTED）是Spring所提供的一个特殊变量。它要求事务管理器或者使用JDBC 3.0 Savepoint API提供嵌套事务行为（如Spring的DataSourceTransactionManager），或者通过JTA支持嵌套事务。</p>
<p>　　事务属性中的readOnly标志表示对应的事务应该被最优化为只读事务。这是一个最优化提示。在一些情况下，一些事务策略能够起到显著的最优化效果，例如在使用Object/Relational映射工具（如：Hibernate或TopLink）时避免dirty checking（试图&#8220;刷新&#8221;）。</p>
<p>　　在事务属性中还有定义&#8220;timeout&#8221;值的选项，指定事务超时为几秒。在JTA中，这将被简单地传递到J2EE服务器的事务协调程序，并据此得到相应的解释。</p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/126022.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2007-06-25 09:31 <a href="http://www.blogjava.net/gm_jing/articles/126022.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> spring 持久层封装</title><link>http://www.blogjava.net/gm_jing/articles/71162.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Thu, 21 Sep 2006 09:12:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/71162.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/71162.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/71162.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/71162.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/71162.html</trackback:ping><description><![CDATA[<p>&nbsp;spring 持久层封装<br><font color=#0000ff size=5>&nbsp;(1) jdbc in spring</font><br>&nbsp;Spring对JDBC进行了良好的封装，通过提供相应的模板和辅助类，在相当程度上降低了JDBC操作的复杂性。<br>&nbsp;并且得益于Spring良好的隔离设计，JDBC封装类库可以脱离Spring Context独立使用，也就是说，<br>&nbsp;即使系统并没有采用Spring作为结构性框架，我们也可以单独使用Spring的JDBC部分（spring-dao.jar）<br>&nbsp;来改善我们的代码。<br>&nbsp;<br>JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);<br>//jdbcTemplate.update("UPDATE user SET age = 10 WHERE id = 'erica'");<br>jdbcTemplate.update(<br>&nbsp;"UPDATE user SET age = ? WHERE id = ?",<br>&nbsp;new PreparedStatementSetter() {<br>&nbsp;&nbsp;public void setValues(PreparedStatementSetter ps)<br>&nbsp;&nbsp;throws SQLException {<br>&nbsp;&nbsp;&nbsp;ps.setInt(1, 18);<br>&nbsp;&nbsp;&nbsp;ps.setString(2, "erica");<br>&nbsp;&nbsp;}<br>&nbsp;}<br>); </p>
<p>大量采用了callback的机制.<br>jdbcTemplate.update(...)<br>jdbcTemplate.query(...)<br>jdbcTemplate.call(...)</p>
<p>1． 代码控制的事务管理<br>简单配置事务,然后在代码中使用TransactionTemplate.</p>
<p><br>2． 参数化配置的事务管理<br>采用proxy模式,简单!!!!</p>
<p><font color=#0000ff size=5>(2)hibernate in spring</font> <br>与上面JDBC中的配置相对比，区别主要在于：<br>1． SessionFactory的引入<br>Hibernate中通过SessionFactory创建和维护Session。Spring对<br>SessionFactory的配置也进行了整合，无需再通过Hibernate.cfg.xml对<br>SessionFactory进行设定。<br>SessionFactory节点的mappingResources属性包含了映射文件的路径，list<br>节点下可配置多个映射文件。<br>hibernateProperties节点则容纳了所有的属性配置。<br>可以对应传统的Hibernate.cfg.xml文件结构对这里的SessionFactory配置<br>进行解读。<br>2． 采用面向Hibernate的TransactionManager实现：<br>org.springframework.orm.hibernate.HibernateTransactionManag<br>er<br><br>public class UserDAO extends HibernateDaoSupport implements IUserDAO<br>{<br>&nbsp;&nbsp;&nbsp;public void insertUser(User user) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getHibernateTemplate().saveOrUpdate(user);<br>&nbsp;&nbsp;&nbsp;}<br>}<br><font color=#0000ff size=5>(3)ibatis in spring</font><br>对比之前的JDBC和Hibernate配置，可以看到：<br>1． sqlMapClient节点<br>SpringFrameWork Developer&#8217;s Guide Version 0.6<br>类似SessionFactory之与Hibernate，这里我们引入了针对ibatis SqlMap的<br>SqlMapClientFactoryBean配置。SqlMapClient对于ibatis的意义类似于Session<br>与Hibernate以及Connection与JDBC，这里的sqlMapClient节点实际上配置了一<br>个sqlMapClient的创建工厂类。<br>configLocation属性配置了ibatis映射文件的名称。<br>2． transactionManager节点<br>这里我们的transactionManager配置与之前JDBC示例中相同，都采用了<br>DataSourceTransactionManager，这与Hibernate有些差异。<br>3． userDAO节点<br>对应的，UserDAO需要配置两个属性，sqlMapClient和DataSource，<br>sqlMapClient将从指定的DataSource中获取数据库连接。<br>其他配置基本上与JDBC示例中相同，这里就不加赘述</p>
<br><br>public class UserDAO extends SqlMapClientDaoSupport implements<br>IUserDAO {<br>&nbsp;&nbsp;&nbsp;public void insertUser(User user) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getSqlMapClientTemplate().update("insertUser", user);<br>&nbsp;&nbsp;&nbsp;}<br>}
<img src ="http://www.blogjava.net/gm_jing/aggbug/71162.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-09-21 17:12 <a href="http://www.blogjava.net/gm_jing/articles/71162.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring mvc/webwork 区别</title><link>http://www.blogjava.net/gm_jing/articles/68198.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Thu, 07 Sep 2006 02:37:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/68198.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/68198.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/68198.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/68198.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/68198.html</trackback:ping><description><![CDATA[
		<p>spring mvc/webwork</p>
		<p>(1)与Spring MVC中的Command对象不同，Webwork 中的Model对象，扮演着承上启下<br />的角色，它既是Action的输入参数，又包含了Action处理的结果数据。<br />换句话说，输入的Http请求参数，将被存储在Model对象传递给Action进行处理，Action<br />处理完毕之后，也将结果数据放置到Model 对象中，之后，Model 对象与返回界面融合生<br />成最后的反馈页面。</p>
		<p>(2)注意这里与Spring MVC 不同，Spring MVC 会自动为逻辑处理单元创建<br />Command Class实例，但Webwork不会自动为Action创建Model对象实例，<br />Model 对象实例的创建需要我们在Action 代码中完成（如LoginAction 中<br />LoginInfo对象实例的创建）。</p>
		<p>(3)</p>
		<p>
				<br />(4)<br /></p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/68198.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-09-07 10:37 <a href="http://www.blogjava.net/gm_jing/articles/68198.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring mvc 学习</title><link>http://www.blogjava.net/gm_jing/articles/67957.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Wed, 06 Sep 2006 02:20:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/67957.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/67957.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/67957.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/67957.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/67957.html</trackback:ping><description><![CDATA[
		<p>
				<font color="#ff1493" size="5">web.xml<br /></font>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;web-app version="2.4" xmlns="<a href="http://java.sun.com/xml/ns/j2ee">http://java.sun.com/xml/ns/j2ee</a>" <br />      xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>"<br />         xsi:schemaLocation="<a href="http://java.sun.com/xml/ns/j2ee">http://java.sun.com/xml/ns/j2ee</a><br /> <a href="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd</a>"&gt;<br /> &lt;servlet&gt;<br />  &lt;servlet-name&gt;Dispatcher&lt;/servlet-name&gt;<br />  &lt;servlet-class&gt; org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt;<br />  &lt;init-param&gt;<br />   &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;<br />   &lt;param-value&gt;/WEB-INF/config.xml&lt;/param-value&gt;<br />  &lt;/init-param&gt;<br />  &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br /> &lt;/servlet&gt;<br /> &lt;servlet-mapping&gt;<br />  &lt;servlet-name&gt;Dispatcher&lt;/servlet-name&gt;<br />  &lt;url-pattern&gt;*.do&lt;/url-pattern&gt;<br /> &lt;/servlet-mapping&gt;<br /> <br /> &lt;jsp-config&gt;<br />        &lt;taglib&gt;<br />            &lt;taglib-uri&gt;/WEB-INF/c.tld&lt;/taglib-uri&gt;<br />            &lt;taglib-location&gt;/WEB-INF/c.tld&lt;/taglib-location&gt;<br />        &lt;/taglib&gt;<br />        &lt;jsp-property-group&gt;<br />            &lt;url-pattern&gt;*.jsp&lt;/url-pattern&gt;<br />            &lt;page-encoding&gt;UTF-8&lt;/page-encoding&gt;<br />        &lt;/jsp-property-group&gt;<br />    &lt;/jsp-config&gt;</p>
		<p> &lt;welcome-file-list&gt;<br />        &lt;welcome-file&gt;/web/login/index.jsp&lt;/welcome-file&gt;<br />    &lt;/welcome-file-list&gt;<br />&lt;/web-app&gt;</p>
		<p>
		</p>
		<hr />
		<br />
		<font color="#ff1493" size="5">config.xml</font>
		<br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;!DOCTYPE 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 />&lt;beans&gt;<br /> &lt;!--Definition of View Resolver --&gt;<br /> &lt;bean id="viewResolver"<br />  class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt;<br />  &lt;property name="viewClass"&gt;<br />   &lt;value&gt;org.springframework.web.servlet.view.InternalResourceView&lt;/value&gt; <br />  &lt;/property&gt;<br />  &lt;property name="prefix"&gt;<br />   &lt;value&gt;/web/login/&lt;/value&gt;<br />  &lt;/property&gt;<br />  &lt;property name="suffix"&gt;<br />   &lt;value&gt;.jsp&lt;/value&gt;<br />  &lt;/property&gt;<br /> &lt;/bean&gt;<br /> &lt;!--Request Mapping --&gt;<br /> &lt;bean id="urlMapping"<br />  class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"&gt;<br />  &lt;property name="mappings"&gt; <br />            &lt;props&gt; <br />                &lt;prop key="/login.do"&gt;LoginAction&lt;/prop&gt; <br />            &lt;/props&gt; <br />        &lt;/property&gt; <br /> &lt;/bean&gt; 
<p> &lt;!---Action Definition--&gt;<br /> &lt;bean id="LoginAction" class="com.jason.action.LoginAction"&gt;<br />  &lt;property name="commandClass"&gt;<br />   &lt;value&gt;com.jason.form.LoginInfo&lt;/value&gt;<br />  &lt;/property&gt;<br />  &lt;property name="fail_view"&gt;<br />   &lt;value&gt;loginfail&lt;/value&gt;<br />  &lt;/property&gt;<br />  &lt;property name="success_view"&gt;<br />   &lt;value&gt;main&lt;/value&gt;<br />  &lt;/property&gt;<br /> &lt;/bean&gt;<br />&lt;/beans&gt;</p><p></p><hr /><font color="#ff1493" size="5">index.jsp</font><br />&lt;%@ page contentType="text/html; charset=utf-8" %&gt;<br />&lt;%@ taglib prefix="c" uri="<a href="http://java.sun.com/jsp/jstl/core">http://java.sun.com/jsp/jstl/core</a>" %&gt;<br />&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "<a href="http://www.w3.org/TR/html4/loose.dtd">http://www.w3.org/TR/html4/loose.dtd</a>"&gt; 
<p>&lt;html&gt;<br />&lt;body&gt;<br /> &lt;form method="POST" action="<font color="#ffa500">./login.do</font>"&gt;          //这个地方. 指向当前路径<br />  &lt;p align="center"&gt;登录&lt;/p&gt;&lt;br&gt;<br />   用户名:&lt;input type="text" name="username" &gt;<br />  &lt;br&gt;<br />   密   码:&lt;input type="password" name="password" &gt;<br />  &lt;br&gt;<br />  &lt;p&gt;<br />   &lt;input type="submit" value="提交" name="B1"&gt;<br />   &lt;input type="reset" value="重置" name="B2"&gt;<br />  &lt;/p&gt;<br /> &lt;/form&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;</p><p></p><hr /><br /><font color="#ff1493" size="5">main.jsp</font><br />&lt;%@ page contentType="text/html; charset=utf-8" %&gt;<br />&lt;%@ taglib prefix="c" uri="<a href="http://java.sun.com/jsp/jstl/core">http://java.sun.com/jsp/jstl/core</a>" %&gt;<br />&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "<a href="http://www.w3.org/TR/html4/loose.dtd">http://www.w3.org/TR/html4/loose.dtd</a>"&gt;<br />&lt;html&gt;<br />&lt;body&gt;<br /> &lt;p&gt;Login Success!!!&lt;/p&gt;<br /> &lt;p&gt;Current User:&lt;c:out value="${logininfo.username}"/&gt;&lt;br&gt;&lt;/p&gt;<br /> &lt;p&gt;Your current messages:&lt;/p&gt;<br /> &lt;c:forEach items="${messages}"<br />  var="item"<br />  begin="0"<br />  end="9"<br />  step="1"<br />  varStatus="var"&gt;<br />  &lt;c:if test="${var.index % 2 == 0}"&gt;*&lt;/c:if&gt;<br /> ${item}&lt;br&gt;<br /> &lt;/c:forEach&gt;<br />&lt;/body&gt;<br />&lt;/html&gt; 
<p></p><hr /><p><font color="#ff1493" size="5">LoginAction</font><br />package com.jason.action;</p><p>import java.util.HashMap;<br />import java.util.LinkedList;<br />import java.util.List;</p><p><font color="#006400">//导入的时候，之前选择错误<br />import org.springframework.validation.BindException;<br />import org.springframework.web.servlet.ModelAndView;<br />import org.springframework.web.servlet.mvc.SimpleFormController;                       <br /><br /></font>import com.jason.form.LoginInfo;</p><p>public class LoginAction extends SimpleFormController {<br /> <br /> private String fail_view;<br /> private String success_view;<br /> <br /> protected ModelAndView onSubmit(Object cmd, BindException ex)<br /> throws Exception {<br />  LoginInfo loginInfo = (LoginInfo) cmd; <br />  if (login(loginInfo) == 0) {<br />   HashMap result_map = new HashMap();<br />   result_map.put("logininfo", loginInfo);<br />   List msgList = new LinkedList();<br />   msgList.add("msg1");<br />   msgList.add("msg2");<br />   msgList.add("msg3");<br />   result_map.put("messages", msgList);<br />   return new ModelAndView(this.getSuccess_view(), result_map); <br />  } else {<br />   return new ModelAndView(this.getFail_view());<br />  }<br />  //return new ModelAndView(new RedirectView(“/redirected.jsp”));<br /> }<br /> private int login(LoginInfo loginInfo) {<br />  if ("Erica".equalsIgnoreCase(loginInfo.getUsername())<br />    &amp;&amp; "mypass".equals(loginInfo.getPassword())) {<br />   return 0;<br />  }<br />  return 1;<br /> }<br /> public String getFail_view() {<br />  return fail_view;<br /> }<br /> public String getSuccess_view() {<br />  return success_view;<br /> }<br /> public void setFail_view(String string) {<br />  fail_view = string;<br /> }<br /> public void setSuccess_view(String string) {<br />  success_view = string;<br /> }<br /> <br />}</p><p></p><hr /><p><font color="#ff1493" size="5">LoginInfo</font><br />package com.jason.form;</p><p>import java.io.Serializable;</p><p>public class LoginInfo implements Serializable {<br /> private String username;<br /> private String password;<br /> public String getPassword() {<br />  return password;<br /> }<br /> public void setPassword(String password) {<br />  this.password = password;<br /> }<br /> public String getUsername() {<br />  return username;<br /> }<br /> public void setUsername(String username) {<br />  this.username = username;<br /> }<br />}<br /><br /><br />【注】调试的时候因为导入的类选择错误引起问题，要注意！！！</p><img src ="http://www.blogjava.net/gm_jing/aggbug/67957.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-09-06 10:20 <a href="http://www.blogjava.net/gm_jing/articles/67957.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>依赖注入的几种实现类型</title><link>http://www.blogjava.net/gm_jing/articles/66871.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Thu, 31 Aug 2006 07:18:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/66871.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/66871.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/66871.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/66871.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/66871.html</trackback:ping><description><![CDATA[
		<p>依赖注入的几种实现类型</p>
		<p>
				<font size="4">
						<font color="#0000ff">(1)Type1 接口注入</font>
						<br />
				</font>
				<font color="#ff1493">加载接口实现并创建其实例的工作由容器完成。在运行期，***实例将由容器提供。</font>
		</p>
		<p>public class MyServlet extends HttpServlet {<br />    public void doGet(<br />    HttpServletRequest request,<br />    HttpServletResponse response)<br />    throws ServletException, IOException {<br />       ……<br />    }<br />}<br />这也是一个Type1 型注入，HttpServletRequest和HttpServletResponse实例由Servlet Container在运行期动态注入。</p>
		<p>
				<br />
				<font color="#0000ff" size="4">(2)Type2 设值注入</font>
		</p>
		<p>
				<font color="#0000ff" size="4">(3)Type3 构造子注入<br /></font>构造子注入，即通过构造函数完成依赖关系的设定，如：</p>
		<p>public class DIByConstructor {<br />   private final DataSource dataSource;<br />   private final String message;<br />   public DIByConstructor(DataSource ds, String msg) {<br />    this.dataSource = ds;<br />    this.message = msg;<br />    }<br />……<br />}</p>
		<p>
				<br />Type2 设值注入的优势<br /> 1． 对于习惯了传统JavaBean开发的程序员而言，通过setter方法设定依赖关系显得更加直<br /> 观，更加自然。<br /> 2． 如果依赖关系（或继承关系）较为复杂，那么Type3模式的构造函数也会相当庞大（我们需<br /> 要在构造函数中设定所有依赖关系），此时Type2模式往往更为简洁。<br /> 3． 对于某些第三方类库而言，可能要求我们的组件必须提供一个默认的构造函数（如Struts<br /> 中的Action），此时Type3类型的依赖注入机制就体现出其局限性，难以完成我们期望的功<br /> 能。</p>
		<p>
				<br />Type3 构造子注入的优势：<br /> 1． “在构造期即创建一个完整、合法的对象”，对于这条Java设计原则，Type3无疑是最好的<br /> 响应者。<br /> 2． 避免了繁琐的setter方法的编写，所有依赖关系均在构造函数中设定，依赖关系集中呈现，<br /> 更加易读。<br /> 3． 由于没有setter方法，依赖关系在构造时由容器一次性设定，因此组件在被创建之后即处于<br /> 相对“不变”的稳定状态，无需担心上层代码在调用过程中执行setter方法对组件依赖关系<br /> 产生破坏，特别是对于Singleton模式的组件而言，这可能对整个系统产生重大的影响。<br /> 4． 同样，由于关联关系仅在构造函数中表达，只有组件创建者需要关心组件内部的依赖关系。<br /> 对调用者而言，组件中的依赖关系处于黑盒之中。对上层屏蔽不必要的信息，也为系统的<br /> 层次清晰性提供了保证。<br /> 5． 通过构造子注入，意味着我们可以在构造函数中决定依赖关系的注入顺序，对于一个大量<br /> 依赖外部服务的组件而言，依赖关系的获得顺序可能非常重要，比如某个依赖关系注入的<br /> 先决条件是组件的DataSource及相关资源已经被设定。</p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/66871.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-31 15:18 <a href="http://www.blogjava.net/gm_jing/articles/66871.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>