﻿<?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/i369/category/16872.html</link><description>北极心空</description><language>zh-cn</language><lastBuildDate>Fri, 14 Mar 2008 03:37:13 GMT</lastBuildDate><pubDate>Fri, 14 Mar 2008 03:37:13 GMT</pubDate><ttl>60</ttl><item><title>谈谈Spring 2.x中简化配置的问题</title><link>http://www.blogjava.net/i369/articles/186191.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Fri, 14 Mar 2008 01:44:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/186191.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/186191.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/186191.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/186191.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/186191.html</trackback:ping><description><![CDATA[Spring 2.x在配置文件的简化的方面做了很多工作，原来1.x中比较麻烦的配置都已经拥有了比较完美的解决方案。最近刚看完《精通Spring 2.x --企业应用开发精解》的书，结合自己的经验整理一下简化配置的内容。 <br />
<br />
<strong>一、关于集合的配置</strong> <br />
<em>1.List</em> <br />
&gt;1.x版本的 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;bean&nbsp;id=</span><span class="string">"parentBoss"</span><span>&nbsp;</span><span class="keyword">abstract</span><span>=</span><span class="string">"true"</span><span class="keyword">class</span><span>=</span><span class="string">"com.baobaotao.attr.Boss"</span><span>&gt;&nbsp;&lt;--父&lt;bean&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"favorites"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;set&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;看报&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;赛车&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;高尔夫&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/set&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/bean&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;bean id="parentBoss" abstract="true"class="com.baobaotao.attr.Boss"&gt; &lt;--父&lt;bean&gt;
&lt;property name="favorites"&gt;
&lt;set&gt;
&lt;value&gt;看报&lt;/value&gt;
&lt;value&gt;赛车&lt;/value&gt;
&lt;value&gt;高尔夫&lt;/value&gt;
&lt;/set&gt;
&lt;/property&gt;
&lt;/bean&gt;
</pre>
<br />
<br />
&gt;2.x版本的 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;util:list&nbsp;id=</span><span class="string">"favoriteList1"</span><span>&nbsp;list-</span><span class="keyword">class</span><span>=</span><span class="string">"java.util.LinkedList"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;看报&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;赛车&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;高尔夫&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/util:list&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;util:list id="favoriteList1" list-class="java.util.LinkedList"&gt;
&lt;value&gt;看报&lt;/value&gt;
&lt;value&gt;赛车&lt;/value&gt;
&lt;value&gt;高尔夫&lt;/value&gt;
&lt;/util:list&gt;</pre>
<br />
<br />
<em>2.Set</em> <br />
&gt; 1.x <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;bean&nbsp;id=</span><span class="string">"boss1"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.baobaotao.attr.Boss"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"favorites"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;set&gt;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;看报&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;赛车&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;高尔夫&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/set&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/bean&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;bean id="boss1" class="com.baobaotao.attr.Boss"&gt;
&lt;property name="favorites"&gt;
&lt;set&gt;
&lt;value&gt;看报&lt;/value&gt;
&lt;value&gt;赛车&lt;/value&gt;
&lt;value&gt;高尔夫&lt;/value&gt;
&lt;/set&gt;
&lt;/property&gt;
&lt;/bean&gt;</pre>
<br />
&gt; 2.x <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;util:set&nbsp;id=</span><span class="string">"favoriteSet1"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&lt;value&gt;看报&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&lt;value&gt;赛车&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&lt;value&gt;高尔夫&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/util:set&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">
&lt;util:set id="favoriteSet1"&gt;
&lt;value&gt;看报&lt;/value&gt;
&lt;value&gt;赛车&lt;/value&gt;
&lt;value&gt;高尔夫&lt;/value&gt;
&lt;/util:set&gt;
</pre>
<br />
<em>3.Map</em> <br />
&gt; 1.x <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;bean&nbsp;id=</span><span class="string">"boss1"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.baobaotao.attr.Boss"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"jobs"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;map&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--Map第一个元素--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;entry&gt;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;key&gt;&lt;value&gt;AM&lt;/value&gt;&lt;/key&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;会见客户&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/entry&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--Map第二个元素--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;entry&gt;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;key&gt;&lt;value&gt;PM&lt;/value&gt;&lt;/key&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;公司内部会议&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/entry&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/map&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/bean&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;bean id="boss1" class="com.baobaotao.attr.Boss"&gt;
&lt;property name="jobs"&gt;
&lt;map&gt;
&lt;!--Map第一个元素--&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;AM&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;会见客户&lt;/value&gt;
&lt;/entry&gt;
&lt;!--Map第二个元素--&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;PM&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;公司内部会议&lt;/value&gt;
&lt;/entry&gt;
&lt;/map&gt;
&lt;/property&gt;
&lt;/bean&gt;</pre>
<br />
&gt; 2.x <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;util:map&nbsp;id=</span><span class="string">"emails1"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;entry&nbsp;key=</span><span class="string">"AM"</span><span>&nbsp;value=</span><span class="string">"会见客户"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;entry&nbsp;key=</span><span class="string">"PM"</span><span>&nbsp;value=</span><span class="string">"公司内部会议"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;/util:map&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;util:map id="emails1"&gt;
&lt;entry key="AM" value="会见客户" /&gt;
&lt;entry key="PM" value="公司内部会议" /&gt;
&lt;/util:map&gt;
</pre>
<br />
<br />
<em>4. Properties</em> <br />
<br />
&gt; 1.x <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;bean&nbsp;id=</span><span class="string">"boss1"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.baobaotao.attr.Boss"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"mails"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;props&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop&nbsp;key=</span><span class="string">"jobMail"</span><span>&gt;john-office</span><span class="annotation">@baobaotao</span><span>.com&lt;/prop&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop&nbsp;key=</span><span class="string">"lifeMail"</span><span>&gt;john-life</span><span class="annotation">@baobaotao</span><span>.com&lt;/prop&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/props&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/bean&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;bean id="boss1" class="com.baobaotao.attr.Boss"&gt;
&lt;property name="mails"&gt;
&lt;props&gt;
&lt;prop key="jobMail"&gt;john-office@baobaotao.com&lt;/prop&gt;
&lt;prop key="lifeMail"&gt;john-life@baobaotao.com&lt;/prop&gt;
&lt;/props&gt;
&lt;/property&gt;
&lt;/bean&gt;
</pre>
<br />
<br />
&gt; 2.x <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;util:properties&nbsp;id=</span><span class="string">"emailProps1"</span><span>&nbsp;location=</span><span class="string">"classpath:com/baobaotao/fb/mails.properties"</span><span>/&gt;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">  &lt;util:properties id="emailProps1" location="classpath:com/baobaotao/fb/mails.properties"/&gt;
</pre>
<br />
可以在一个属性文件中直接配置属性，这比较符合一般的项目习惯。 <br />
<br />
<strong>二、 关于事务配置</strong> <br />
<br />
<br />
1.1.x <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&nbsp;&lt;bean&nbsp;id=</span><span class="string">"bbtForum"</span><span>&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.transaction.interceptor.TransactionProxyFactoryBean"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;property&nbsp;name=</span><span class="string">"transactionManager"</span><span>&nbsp;ref=</span><span class="string">"txManager"</span><span>&nbsp;/&gt;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;property&nbsp;name=</span><span class="string">"target"</span><span>&nbsp;ref=</span><span class="string">"bbtForumTarget"</span><span>/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;property&nbsp;name=</span><span class="string">"transactionAttributes"</span><span>&gt;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;props&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop&nbsp;key=</span><span class="string">"get*"</span><span>&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop&nbsp;key=</span><span class="string">"*"</span><span>&gt;PROPAGATION_REQUIRED&lt;/prop&gt;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/props&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&lt;/bean&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">  &lt;bean id="bbtForum"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;
&lt;property name="transactionManager" ref="txManager" /&gt;
&lt;property name="target" ref="bbtForumTarget"/&gt;
&lt;property name="transactionAttributes"&gt;
&lt;props&gt;
&lt;prop key="get*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt;
&lt;prop key="*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;
&lt;/props&gt;
&lt;/property&gt;
&lt;/bean&gt;
</pre>
<br />
<br />
2.2.x <br />
<br />
有两种新方法 <br />
a)使用@Transactional注解 <br />
在需要的服务类或服务方法处直接打上@Transactional注解，然后在Spring配置文件中启用注解事务驱动就可以了： <br />
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="annotation">@Transactional</span><span>&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;BbtForumImpl&nbsp;</span><span class="keyword">implements</span><span>&nbsp;BbtForum&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="annotation">@Transactional</span><span>(readOnly=</span><span class="keyword">true</span><span>)&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;Forum&nbsp;getForum(</span><span class="keyword">int</span><span>&nbsp;forumId)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;forumDao.getForum(forumId); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;。。。。 &nbsp;&nbsp;</span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">@Transactional
public class BbtForumImpl implements BbtForum {
@Transactional(readOnly=true)
public Forum getForum(int forumId) {
return forumDao.getForum(forumId);
}
。。。。
}
</pre>
<br />
在Spring配置文件中相应添加上： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;bean&nbsp;id=</span><span class="string">"txManager"</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.jdbc.datasource.DataSourceTransactionManager"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"dataSource"</span><span>&nbsp;ref=</span><span class="string">"dataSource"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;tx:annotation-driven&nbsp;transaction-manager=</span><span class="string">"txManager"</span><span>/&gt;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt;
&lt;property name="dataSource" ref="dataSource" /&gt;
&lt;/bean&gt;
&lt;tx:annotation-driven transaction-manager="txManager"/&gt;
</pre>
<br />
这样就OK了，简单吧：） <br />
<br />
b)使用aop/tx <br />
<br />
如果你的Service服务类都很规范，我觉得使用aop/tx更方面，因为不用到处打注解，在一处集中配置就OK了，可谓运筹帷幄之中，决胜于千里之外：） <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;aop:config&gt;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>t;aop:pointcut&nbsp;id=</span><span class="string">"serviceMethod"</span><span>&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;expression=</span><span class="string">"execution(*&nbsp;com.baobaotao.service.*Forum.*(..))"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>t;aop:advisor&nbsp;pointcut-ref=</span><span class="string">"serviceMethod"</span><span>&nbsp;advice-ref=</span><span class="string">"txAdvice"</span><span>&nbsp;/&gt;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&lt;/aop:config&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;tx:advice&nbsp;id=</span><span class="string">"txAdvice"</span><span>&nbsp;transaction-manager=</span><span class="string">"txManager"</span><span>&gt;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&lt;tx:attributes&gt;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tx:method&nbsp;name=</span><span class="string">"get*"</span><span>&nbsp;read-only=</span><span class="string">"false"</span><span>/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tx:method&nbsp;name=</span><span class="string">"add*"</span><span>&nbsp;rollback-</span><span class="keyword">for</span><span>=</span><span class="string">"Exception"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tx:method&nbsp;name=</span><span class="string">"update*"</span><span>/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&lt;/tx:attributes&gt; &nbsp;&nbsp;</span></li>
    <li><span>lt;/tx:advice&gt; &nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">
&lt;aop:config&gt;
&lt;aop:pointcut id="serviceMethod"
expression="execution(* com.baobaotao.service.*Forum.*(..))" /&gt;
&lt;aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" /&gt;
&lt;/aop:config&gt;
&lt;tx:advice id="txAdvice" transaction-manager="txManager"&gt;
&lt;tx:attributes&gt;
&lt;tx:method name="get*" read-only="false"/&gt;
&lt;tx:method name="add*" rollback-for="Exception" /&gt;
&lt;tx:method name="update*"/&gt;
&lt;/tx:attributes&gt;
&lt;/tx:advice&gt;
</pre>
<br />
<br />
<strong>三、关于AOP配置</strong> <br />
<br />
原来1.x的AOP太麻烦了，提都不想提，直接说一下2.x的AOP。 <br />
Spring 2.x使用@AspectJ来描述切面，由于@AspectJ的语法描述能力超强，因此在Spring 2.x中使用AOP真的非常方便。 <br />
<br />
在使用@AspectJ之前，首先你得保证你所使用的JDK的版本是5.0及以上版本，否则无法使用注解技术。 <br />
Spring在处理@Aspect注解表达式时，需要使用位于spring/lib/asm下asm关联类库，将该类库的三个类包加入到类路径中：asm-2.2.2.jar、asm-commons-2.2.2.jar和asm-util-2.2.2.jar。我们在第一章中了解了asm类库的用途，它是轻量级的字节码处理框架，因为Java的反射机制无法获取入参名，Spring就利用asm处理@AspectJ中所描述的方法入参名。 <br />
<br />
此外，Spring采用AspectJ提供的@AspectJ注解类库及相应的解析类库，它位于spring/lib/aspectj目录下，将目录下的aspectjrt.jar和aspectjweaver.jar类包加入类路径中。 <br />
在做好上节中所提到的前置工作后，我们就可以开始编写一个基于@AspectJ的切面了，首先来看一个简单的例子，以便对@AspectJ有一个切身的认识。 <br />
<br />
@AspectJ采用不同的方式对AOP进行描述， 我们使用NaiveWaiter的例子来说明，这是一个希望引入切面的目标类： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="keyword">package</span><span>&nbsp;com.baobaotao; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;NaiveWaiter&nbsp;</span><span class="keyword">implements</span><span>&nbsp;Waiter&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;greetTo(String&nbsp;clientName)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"NaiveWaiter:greet&nbsp;to&nbsp;"</span><span>+clientName+</span><span class="string">"..."</span><span>); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;serveTo(String&nbsp;clientName){ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"NaiveWaiter:serving&nbsp;"</span><span>+clientName+</span><span class="string">"..."</span><span>); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">package com.baobaotao;
public class NaiveWaiter implements Waiter {
public void greetTo(String clientName) {
System.out.println("NaiveWaiter:greet to "+clientName+"...");
}
public void serveTo(String clientName){
System.out.println("NaiveWaiter:serving "+clientName+"...");
}
}
</pre>
<br />
<br />
下面使用@AspectJ来定义一下切面： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="keyword">package</span><span>&nbsp;com.baobaotao.aspectj.aspectj; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;org.aspectj.lang.annotation.Aspect; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;org.aspectj.lang.annotation.Before; &nbsp;&nbsp;</span></span></li>
    <li><span class="comment">//通过该注解将PreGreetingAspect标识为一个切面 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span class="annotation">@Aspect</span><span>&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;PreGreetingAspect{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="annotation">@Before</span><span>(</span><span class="string">"execution(*&nbsp;greetTo(..))"</span><span>)&nbsp;</span><span class="comment">//&lt;---定义切点和增强类型 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;beforeGreeting(){&nbsp;</span><span class="comment">//&lt;----增强的横切逻辑 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"How&nbsp;are&nbsp;you"</span><span>); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">package com.baobaotao.aspectj.aspectj;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
//通过该注解将PreGreetingAspect标识为一个切面
@Aspect
public class PreGreetingAspect{
@Before("execution(* greetTo(..))") //&lt;---定义切点和增强类型
public void beforeGreeting(){ //&lt;----增强的横切逻辑
System.out.println("How are you");
}
}
</pre>
<br />
<br />
然后启动@AspectJ的注解切面驱动就可以了！ <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;?xml&nbsp;version=</span><span class="string">"1.0"</span><span>&nbsp;encoding=</span><span class="string">"UTF-8"</span><span>&nbsp;?&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;beans&nbsp;xmlns=</span><span class="string">"http://www.springframework.org/schema/beans"</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;xmlns:xsi=</span><span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;xmlns:aop=</span><span class="string">"http://www.springframework.org/schema/aop"</span><span>&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;xsi:schemaLocation="http:</span><span class="comment">//www.springframework.org/schema/beans </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&lt;A&nbsp;href=</span><span class="string">"http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"</span><span>&nbsp;target=_blank&gt;http://www.springframework.org/schema/beans/spring-beans-</span><span class="number">2.0</span><span>.xsd&lt;/A&gt; &nbsp;&nbsp;</span></span></li>
    <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;http:</span><span class="comment">//www.springframework.org/schema/aop&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&lt;A&nbsp;href=</span><span class="string">"http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"</span><span>&nbsp;target=_blank&gt;http://www.springframework.org/schema/aop/spring-aop-</span><span class="number">2.0</span><span>.xsd&lt;/A&gt;"&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--基于</span><span class="annotation">@AspectJ</span><span>切面的驱动器--&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;aop:aspectj-autoproxy&nbsp;/&gt;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"waiter"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.baobaotao.NaiveWaiter"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.baobaotao.aspectj.example.PreGreetingAspect"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;/beans&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
<a href="http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" target="_blank">http://www.springframework.org/schema/beans/spring-beans-2.0.xsd</a>
http://www.springframework.org/schema/aop
<a href="http://www.springframework.org/schema/aop/spring-aop-2.0.xsd" target="_blank">http://www.springframework.org/schema/aop/spring-aop-2.0.xsd</a>"&gt;
&lt;!--基于@AspectJ切面的驱动器--&gt;
&lt;aop:aspectj-autoproxy /&gt;
&lt;bean id="waiter" class="com.baobaotao.NaiveWaiter" /&gt;
&lt;bean class="com.baobaotao.aspectj.example.PreGreetingAspect" /&gt;
&lt;/beans&gt;
</pre>
<br />
<br />
<strong>四、关于Spring 2.1添加的新功能</strong> <br />
<br />
1.原来引入一个外面属性配置文件需要使用以下的方式： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;bean&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"locations"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;list&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--指定属性文件地址，可以在这里定义多个属性文件--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;classpath:com/baobaotao/place/car.properties&lt;/value&gt;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/list&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"fileEncoding"</span><span>&nbsp;value=</span><span class="string">"utf-8"</span><span>/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&lt;!--引用外部属性的值，对car属性进行配置--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;bean&nbsp;id=</span><span class="string">"car"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.baobaotao.place.Car"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"brand"</span><span>&nbsp;value=</span><span class="string">"${brand}"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"maxSpeed"</span><span>&nbsp;value=</span><span class="string">"${maxSpeed}"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"price"</span><span>&nbsp;value=</span><span class="string">"${price}"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;/bean&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt;
&lt;property name="locations"&gt;
&lt;list&gt;
&lt;!--指定属性文件地址，可以在这里定义多个属性文件--&gt;
&lt;value&gt;classpath:com/baobaotao/place/car.properties&lt;/value&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;property name="fileEncoding" value="utf-8"/&gt;
&lt;/bean&gt;
&lt;!--引用外部属性的值，对car属性进行配置--&gt;
&lt;bean id="car" class="com.baobaotao.place.Car"&gt;
&lt;property name="brand" value="${brand}" /&gt;
&lt;property name="maxSpeed" value="${maxSpeed}" /&gt;
&lt;property name="price" value="${price}" /&gt;
&lt;/bean&gt;
</pre>
<br />
<br />
使用Spring 2.1后，你只需要象下面这样配置就可以了： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/148519#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;context:property-placeholder&nbsp;location=</span><span class="string">"&nbsp;classpath:com/baobaotao/place/car.properties&nbsp;"</span><span>/&gt;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;context:property-placeholder location=" classpath:com/baobaotao/place/car.properties "/&gt;
</pre>
<br />
<br />
3.注解驱动的Bean注入 <br />
<br />
大家看看这段E文就OK了， <br />
&lt;context:component-scan&gt;: scans classpath using one or more "include"/"exclude" filters, and automatically registers beans <br />
In essence, this is a third way to define beans (1: classic xml, 2:javaconfig (code), 3:&lt;context:component-scan&gt;, matching on annotations or types) <br />
Default naming strategy is based on short classname of discovered bean <br />
@Component and @Repository annotations, when used, can optionally specify a bean name to use <br />
For filter type "annotation", the value of "expression" attribute should resolve to a Java annotation type <br />
For filter type "assignable", the value of "expression" attribute should resolve to a Java type <br />
For filter type "aspectj", the value of "expression" should be an "type expression" (in Pointcut language, perhaps it could be injected?) <br />
Relevant documentation can be found in preliminary spring 2.1 manual, sections 3.10 and 3.11 <br />
In addition, this last JIRA comment for http://www.jetbrains.net/jira/browse/IDEADEV-16886#action_163502 contains two links to articles showing example usage of &lt;context:component-scan&gt; <br />
&lt;context:annotation-config&gt; (described in 3.10 in spring 2.1 manual linked above): allows autowiring to be defined using @Resource or @Autowired annotations. <br />
<br />
<br />
<strong>五、关于Spring 2.5添加的新功能</strong> <br />
Spring 2.5继续对context命名空间进行了扩充，添加了好用而强大的context:load-time-weaver，可以让我们更方便地应用AspectJ。大家可以看TSS上的这篇文章，它全面讲解了Spring 2.5的新特性。 <br />
<a href="http://www.theserverside.com/tt/articles/article.tss?l=IntrotoSpring25" target="_blank">http://www.theserverside.com/tt/articles/article.tss?l=IntrotoSpring25</a> <br />
<br />
<span style="color: red">注：以上大部分代码来直接引用自 《精通Spring 2.x--企业应用开发精解》</span> <br />
文章来源于:javaeye的stamen
<img src ="http://www.blogjava.net/i369/aggbug/186191.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2008-03-14 09:44 <a href="http://www.blogjava.net/i369/articles/186191.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACEGI杂项记录[全部转载]</title><link>http://www.blogjava.net/i369/articles/170224.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Tue, 25 Dec 2007 01:35:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/170224.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/170224.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/170224.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/170224.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/170224.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 对ACEGI中FilterChainProxy进行性能调优一般情况下，在ACEGI中队filterChainProxy如下配置 &nbsp;&nbsp;&nbsp; &lt;bean id="filterChainProxy" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.acegisec...&nbsp;&nbsp;<a href='http://www.blogjava.net/i369/articles/170224.html'>阅读全文</a><img src ="http://www.blogjava.net/i369/aggbug/170224.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-12-25 09:35 <a href="http://www.blogjava.net/i369/articles/170224.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Acegi安全系统扩展 </title><link>http://www.blogjava.net/i369/articles/165458.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Wed, 05 Dec 2007 04:51:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/165458.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/165458.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/165458.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/165458.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/165458.html</trackback:ping><description><![CDATA[相信side对Acegi的扩展会给你耳目一新的感觉,提供完整的扩展功能,管理界面,中文注释和靠近企业的安全策略。side只对Acegi不符合企业应用需要的功能进行扩展,尽量不改动其余部分来实现全套权限管理功能,以求能更好地适应Acegi升级。
<p>&nbsp;</p>
<h2>3.1 基于角色的权限控制(RBAC)</h2>
<p>&nbsp;&nbsp;&nbsp; Acegi 自带的 sample 表设计很简单: users表{username,password,enabled} authorities表{username,authority},这样简单的设计无法适应复杂的权限需求,故SpringSide选用RBAC模型对 权限控制数据库表进行扩展。&nbsp;RBAC引入了ROLE的概念,使User(用户)和Permission(权限)分离,一个用户拥有多个角色,一个角色拥 有有多个相应的权限,从而减少了权限管理的复杂度,可更灵活地支持安全策略。 </p>
<p><img alt="" src="http://www.springside.org.cn/docs/reference/images/acegi/RBAC.jpg" /></p>
<p>&nbsp;&nbsp;&nbsp; 同时,我们也引入了resource(资源)的概念,一个资源对应多个权限，资源分为ACL,URL,和FUNTION三种。注意，URL和FUNTION的权限命名需要以AUTH_开头才会有资格参加投票, 同样的ACL权限命名需要ACL_开头。</p>
<br />
<h2>3.2&nbsp;管理和使用EhCache</h2>
<h3>3.2.1 设立缓存</h3>
<p>在SpringSide里的 Acegi 扩展使用 <a href="http://ehcache.sourceforge.net/">EhCache</a><span style="font-family: 宋体">&nbsp;就作为一种缓存解决方案,以缓存用户和资源的信息和相对应的权限信息。</span></p>
<p><span style="font-family: 宋体">首先需要一个在classpath的<span style="font-family: Arial"> <span lang="EN-US">ehcache.xml </span></span><span style="font-family: 宋体">文件，用于配置</span><span style="font-family: Arial"> <span lang="EN-US">EhCache。</span></span></span></p>
<pre><span style="font-family: 宋体"><span style="font-family: Arial"><span lang="EN-US">&lt;ehcache&gt;<br />
</span></span></span><span style="font-family: 宋体"><span style="font-family: Arial"><span lang="EN-US">&nbsp;&nbsp;&nbsp;</span></span></span><span style="font-family: 宋体"><span style="font-family: Arial"><span lang="EN-US">&nbsp;&nbsp;&nbsp; &lt;defaultCache<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxElementsInMemory="10000"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eternal="false"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overflowToDisk="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToIdleSeconds="0"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToLiveSeconds="0"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; diskPersistent="false"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diskExpiryThreadIntervalSeconds= "120"/&gt; <br />
&nbsp;&nbsp;&nbsp; &lt;!-- acegi cache--&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;cache name="<font color="#000080">userCache</font>"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxElementsInMemory="10000"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eternal="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;overflowToDisk= "true"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;!-- acegi cache--&gt;   <br />
&nbsp;&nbsp;&nbsp; &lt;cache name="<font color="#000080">resourceCache</font>"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxElementsInMemory="10000"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eternal="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overflowToDisk="true"/&gt;<br />
&lt;/ehcache&gt;</span></span></span></pre>
<p><span lang="EN-US" style="font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp; maxElementsInMemory设定了允许在Cache中存放的数据数目，eternal设定Cache是否会过期， overflowToDisk设定内存不足的时候缓存到硬盘，timeToIdleSeconds和timeToLiveSeconds设定缓存游离时间 和生存时间，diskExpiryThreadIntervalSeconds设定缓存在硬盘上的生存时间，注意当eternal="true"时， timeToIdleSeconds，timeToLiveSeconds和diskExpiryThreadIntervalSeconds都是无效 的。</span></p>
<p><span lang="EN-US" style="font-family: Arial">&lt;defaultCache&gt;是除制定的Cache外其余所有Cache的设置，针对Acegi 的情况, 专门设置了userCache和resourceCache，都设为永不过期。在applicationContext-acegi-security.xml中相应的调用是</span></p>
<pre><span lang="EN-US" style="font-family: Arial">&lt;bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="cacheManager" ref="cacheManager"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="<font color="#000080">cacheName</font>" value="<font color="#000080">  userCache</font>"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;bean id="userCache" class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache" autowire="byName"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="cache" ref="userCacheBackend"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;bean id="resourceCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="cacheManager" ref="cacheManager"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="<font color="#000080">cacheName</font>" value="<font color="#000080">  resourceCache</font>"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;bean id="resourceCache" class="org.springside.modules.security.service.acegi.cache.ResourceCache" autowire="byName"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="cache" ref="resourceCacheBackend"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
&lt;bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/&gt;<br />
</span></pre>
<p><span lang="EN-US" style="font-family: Arial">"cacheName" 就是设定在<span lang="EN-US">ehcache.xml </span>中相应Cache的名称。</span></p>
<p><span lang="EN-US" style="font-family: Arial">userCache使用的是Acegi 的EhCacheBasedUserCache(实现了UserCache接口), resourceCache是SpringSide的扩展类</span></p>
<pre><span lang="EN-US" style="font-family: Arial">public interface <font color="#000080">UserCache</font>   {</span><span lang="EN-US" style="font-family: Arial"><br />
&nbsp;&nbsp;&nbsp; public UserDetails <font color="#800080">getUserFromCache</font>   (String username);</span><span lang="EN-US" style="font-family: Arial"><br />
&nbsp;&nbsp;&nbsp; public void <font color="#800080">putUserInCache</font>   (UserDetails user);</span><span lang="EN-US" style="font-family: Arial"><br />
&nbsp;&nbsp;&nbsp; public void <font color="#800080">removeUserFromCache</font>   (String username);<br />
}</span></pre>
<pre><span lang="EN-US" style="font-family: Arial">public class <font color="#000080">ResourceCache</font>   {<br />
</span><span lang="EN-US" style="font-family: Arial">&nbsp;&nbsp;&nbsp; public ResourceDetails <font color="#800080">getAuthorityFromCache</font>   (String resString) {...</span><span lang="EN-US" style="font-family: Arial">&nbsp;&nbsp; }<br />
</span><span lang="EN-US" style="font-family: Arial">&nbsp;&nbsp;&nbsp; public void <font color="#800080">putAuthorityInCache</font>   (ResourceDetails resourceDetails) {...&nbsp; }<br />
&nbsp;</span><span lang="EN-US" style="font-family: Arial">&nbsp;&nbsp; public void <font color="#800080">removeAuthorityFromCache</font>   (String resString) {... }<br />
</span><span lang="EN-US" style="font-family: Arial">&nbsp;&nbsp;&nbsp; public List getUrlResStrings() {... }<br />
</span><span lang="EN-US" style="font-family: Arial">&nbsp;&nbsp;&nbsp; public List getFunctions() {.. }</span><span lang="EN-US" style="font-family: Arial"><br />
}</span></pre>
<p><span lang="EN-US" style="font-family: Arial">UserCache 就是通过EhCache对UserDetails 进行缓存管理, 而ResourceCache 是对ResourceDetails 类进行缓存管理</span></p>
<pre><span lang="EN-US" style="font-family: Arial">public interface <font color="#000080">UserDetails</font>   extends Serializable {<br />
</span><span lang="EN-US" style="font-family: Arial">&nbsp;&nbsp;&nbsp; public boolean isAccountNonExpired();</span><span lang="EN-US" style="font-family: Arial"><br />
&nbsp;&nbsp;&nbsp; public boolean isAccountNonLocked();</span><span lang="EN-US" style="font-family: Arial"><br />
&nbsp;&nbsp;&nbsp; public GrantedAuthority[] <font color="#800080">getAuthorities</font>();</span><span lang="EN-US" style="font-family: Arial"><br />
&nbsp;&nbsp;&nbsp; public boolean isCredentialsNonExpired();</span><span lang="EN-US" style="font-family: Arial"><br />
&nbsp;&nbsp;&nbsp; public boolean isEnabled();</span><span lang="EN-US" style="font-family: Arial"><br />
&nbsp;&nbsp;&nbsp; public String getPassword();</span><span lang="EN-US" style="font-family: Arial"><br />
&nbsp;&nbsp;&nbsp; public String getUsername();<br />
}</span></pre>
<pre><span lang="EN-US" style="font-family: Arial">public interface <font color="#000080">ResourceDetails</font>   extends Serializable {</span><span lang="EN-US" style="font-family: Arial"><br />
&nbsp;&nbsp;&nbsp; public String getResString();</span><span lang="EN-US" style="font-family: Arial"><br />
&nbsp;&nbsp;&nbsp; public String getResType();</span><span lang="EN-US" style="font-family: Arial"><br />
&nbsp;&nbsp;&nbsp; public GrantedAuthority[] <font color="#800080">getAuthorities</font>();<br />
</span><span lang="EN-US" style="font-family: Arial">}</span></pre>
<p><span lang="EN-US" style="font-family: Arial">UserDetails 包含用户信息和相应的权限，ResourceDetails 包含资源信息和相应的权限。</span></p>
<pre><span lang="EN-US" style="font-family: Arial">public interface <font color="#000080">GrantedAuthority</font>     {<br />
&nbsp;&nbsp;&nbsp; public String <font color="#800080">getAuthority</font>   ();<br />
}</span></pre>
<p><span lang="EN-US" style="font-family: Arial"><font face="Tahoma">&nbsp;&nbsp;&nbsp;&nbsp; </font>GrantedAuthority 就是权限信息，在Acegi 的 sample 里<span lang="EN-US" style="font-family: Arial">GrantedAuthority 的信息如</span>ROLE_USER, ROLE_SUPERVISOR, ACL_CONTACT_DELETE, ACL_CONTACT_ADMIN等等，网上也有很多例子把角色作为<span lang="EN-US" style="font-family: Arial">GrantedAuthority ，但事实上看看ACL 就知道， Acegi本身根本就没有角色这个概念，<span lang="EN-US" style="font-family: Arial">GrantedAuthority 包含的信息应该是权限，对于非ACL的权限用 AUTH_ 开头更为合理, 如SpringSide里的 AUTH_ADMIN_LOGIN, AUTH_BOOK_MANAGE 等等。</span></span> </span></p>
<h3>3.2.2 管理缓存</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 使用AcegiCacheManager对<span lang="EN-US" style="font-family: Arial">userCache和resourceCache进行统一缓存管理。<font face="Tahoma">当在后台对用户信息进行修改或赋权的时候, 在更新数据库同时就会调用acegiCacheManager相应方法, 从数据库中读取数据并替换cache中相应部分,使cache与数据库同步。</font></span></p>
<pre><span lang="EN-US" style="font-family: Arial">public class AcegiCacheManager extends BaseService {<br />
</span><span lang="EN-US" style="font-family: Arial">&nbsp;&nbsp;&nbsp; private ResourceCache <font color="#800080">resourceCache</font>   ;<br />
</span><span lang="EN-US" style="font-family: Arial">&nbsp;&nbsp;&nbsp; private UserCache <font color="#800080">userCache</font>   ;</span><span lang="EN-US" style="font-family: Arial"><br />
<font color="#800000">&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * 修改User时更改userCache  <br />
&nbsp;&nbsp;&nbsp;&nbsp; */</font> <br />
&nbsp;&nbsp;&nbsp; public void <font color="#800080">modifyUserInCache</font>   (User user, String orgUsername) {...&nbsp;&nbsp;&nbsp; }<br />
<font color="#800000">&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * 修改Resource时更改resourceCache  <br />
&nbsp;&nbsp;&nbsp;&nbsp; */</font> <br />
&nbsp;&nbsp;&nbsp; public void <font color="#800080">modifyResourceInCache</font>   (Resource resource, String orgResourcename) {...&nbsp;&nbsp;&nbsp; }<br />
<font color="#800000">&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; *   修改权限时同时修改userCache和resourceCache<br />
&nbsp;&nbsp;&nbsp;&nbsp; */</font> <br />
&nbsp;&nbsp;&nbsp; public void <font color="#800080">modifyPermiInCache</font>   (Permission permi, String orgPerminame) {...&nbsp; }<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * <font color="#800000">User授予角色时更改userCache</font>  <br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; public void <font color="#800080">authRoleInCache</font>   (User user) {...&nbsp;&nbsp;&nbsp; }<br />
<font color="#800000">&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * Role授予权限时更改userCache和resourceCache  <br />
&nbsp;&nbsp;&nbsp;&nbsp; */</font> <br />
&nbsp;&nbsp;&nbsp; public void <font color="#800080">authPermissionInCache</font>   (Role role) {...&nbsp; }<br />
&nbsp;<font color="#800000">&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * Permissioni授予资源时更改resourceCache  <br />
&nbsp;&nbsp;&nbsp;&nbsp; */</font> <br />
&nbsp;&nbsp;&nbsp; public void <font color="#800080">authResourceInCache</font>   (Permission permi) {...&nbsp; }<br />
<font color="#800000">&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; *   初始化userCache<br />
&nbsp;&nbsp;&nbsp;&nbsp; */</font> <br />
&nbsp;&nbsp;&nbsp; public void <font color="#800080">initUserCache</font>   () {...&nbsp; }<br />
<font color="#800000">&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; *   初始化resourceCache<br />
&nbsp;&nbsp;&nbsp;&nbsp; */</font> <br />
&nbsp;&nbsp;&nbsp; public void <font color="#800080">initResourceCache</font>   () {... }<br />
<font color="#800000">&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; *  获取所有的url资源<br />
&nbsp;&nbsp;&nbsp;&nbsp; */</font> <br />
&nbsp;&nbsp;&nbsp; public List <font color="#800080">getUrlResStrings</font>   () {... &nbsp;}<br />
<font color="#800000">&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * 获取所有的Funtion资源  <br />
&nbsp;&nbsp;&nbsp;&nbsp; */</font> <br />
&nbsp;&nbsp;&nbsp; public List <font color="#800080">getFunctions</font>   () {...&nbsp; }<br />
<font color="#800000">&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * 根据资源串获取资源  <br />
&nbsp;&nbsp;&nbsp;&nbsp; */</font> <br />
&nbsp;&nbsp;&nbsp; public ResourceDetails <font color="#800080">getAuthorityFromCache</font>   (String resString) {...&nbsp; }<br />
&nbsp;&nbsp;<br />
&nbsp;......<br />
<br />
<br />
}</span></pre>
<p>&nbsp;</p>
<h2>3.3 资源权限定义扩展</h2>
<p><span lang="EN-US" style="font-family: Arial"><font face="Tahoma">&nbsp;&nbsp;&nbsp;&nbsp; </font></span>Acegi给出的sample里,资源权限对照关系是配置在xml中的,试想一下如果你的企业安全应用有500个用户,100个角色权限的时候,维护这个xml将是个繁重无比的工作,如何动态更改用户权限更是个头痛的问题。</p>
<pre>&nbsp;&nbsp; &lt;bean id="contactManagerSecurity" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="accessDecisionManager"&gt;&lt;ref local="businessAccessDecisionManager"/&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="afterInvocationManager"&gt;&lt;ref local="afterInvocationManager"/&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="objectDefinitionSource"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sample.contact.ContactManager.create=ROLE_USER<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sample.contact.ContactManager.getAllRecipients=ROLE_USER<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sample.contact.ContactManager.getAll=ROLE_USER,AFTER_ACL_COLLECTION_READ<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sample.contact.ContactManager.getById=ROLE_USER,AFTER_ACL_READ<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sample.contact.ContactManager.delete=ACL_CONTACT_DELETE<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sample.contact.ContactManager.deletePermission=ACL_CONTACT_ADMIN<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sample.contact.ContactManager.addPermission=ACL_CONTACT_ADMIN<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp; &lt;/bean&gt;</pre>
<pre>&nbsp;&nbsp;&lt;bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="accessDecisionManager"&gt;&lt;ref local="httpRequestAccessDecisionManager"/&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="objectDefinitionSource"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PATTERN_TYPE_APACHE_ANT<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /index.jsp=ROLE_ANONYMOUS,ROLE_USER<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /hello.htm=ROLE_ANONYMOUS,ROLE_USER<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /logoff.jsp=ROLE_ANONYMOUS,ROLE_USER<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /switchuser.jsp=ROLE_SUPERVISOR<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /j_acegi_switch_user=ROLE_SUPERVISOR<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /acegilogin.jsp*=ROLE_ANONYMOUS,ROLE_USER<br />
&nbsp;&nbsp;&nbsp;&nbsp;   /**=ROLE_USER<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp; &lt;/bean&gt;</pre>
<p>&nbsp;对如此不Pragmatic的做法,SpringSide进行了扩展, 让Acegi 能动态读取数据库中的权限资源关系。</p>
<h3>3.3.1 Aop Invocation Authorization</h3>
<pre>&nbsp;&nbsp;&nbsp; &lt;bean id="methodSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="authenticationManager" ref="authenticationManager"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="objectDefinitionSource" ref="methodDefinitionSource"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;bean id="methodDefinitionSource" class="org.springside.security.service.acegi.DBMethodDefinitionSource"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="acegiCacheManager" ref="acegiCacheManager"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;</pre>
<p><span lang="EN-US" style="font-family: Arial"><font face="Tahoma">&nbsp;&nbsp;&nbsp;&nbsp; </font></span>研究下Aceig的源码,<strong>ObjectDefinitionSource</strong>的实际作用是返回一个<strong>ConfigAttributeDefinition</strong>对象，而Acegi Sample 的方式是用<strong>MethodDefinitionSourceEditor</strong>把xml中的文本Function资源权限对应关系信息加载到<strong>MethodDefinitionMap </strong>( MethodDefinitionSource&nbsp;的实现类 )中, 再组成ConfigAttributeDefinition，而我们的扩展目标是从缓存中读取信息来组成ConfigAttributeDefinition。</p>
<p><span lang="EN-US" style="font-family: Arial"><font face="Tahoma">&nbsp;&nbsp;&nbsp;&nbsp; </font></span><strong>MethodSecurityInterceptor</strong>是通过调用AbstractMethodDefinitionSource的<strong>lookupAttributes(method)</strong>方法获取ConfigAttributeDefinition。所以我们需要实现自己的O<span lang="EN-US" style="font-family: Arial"><font face="Tahoma">bjectDefinitionSource，</font></span>继承<strong>AbstractMethodDefinitionSource</strong>并实现其lookupAttributes方法,从缓存中读取资源权限对应关系组成并返回ConfigAttributeDefinition即可。SpringSide中的<strong>DBMethodDefinitionSource</strong>类的部分实现如下 :</p>
<pre>public class DBMethodDefinitionSource <font color="#000080">extends</font> <font color="#000080">AbstractMethodDefinitionSource</font> {<br />
......<br />
&nbsp;&nbsp;&nbsp; protected <font color="#008080">ConfigAttributeDefinition</font> <font color="#800080">lookupAttributes</font>(Method mi) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Assert.notNull(mi, "lookupAttrubutes in the DBMethodDefinitionSource is null");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String methodString = mi.getDeclaringClass().getName() + "." + mi.getName();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!acegiCacheManager.isCacheInitialized()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#800000">//初始化Cache<br />
</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; acegiCacheManager.initResourceCache();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#800000">//获取所有的function<br />
</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List methodStrings = acegiCacheManager.getFunctions();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Set auths = new HashSet();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#800000">//取权限的合集</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (Iterator iter = methodStrings.iterator(); iter.hasNext();) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String mappedName = (String) iter.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (methodString.equals(mappedName)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; || <font color="#800080">isMatch</font>(methodString, mappedName)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ResourceDetails resourceDetails = acegiCacheManager.getAuthorityFromCache(mappedName);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (resourceDetails == null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GrantedAuthority[] authorities = resourceDetails.getAuthorities();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (authorities == null || authorities.length == 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auths.addAll(Arrays.asList(authorities));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (auths.size() == 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ConfigAttributeEditor configAttrEditor = new ConfigAttributeEditor();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String authoritiesStr = " ";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (Iterator iter = auths.iterator(); iter.hasNext();) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GrantedAuthority authority = (GrantedAuthority) iter.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; authoritiesStr += authority.getAuthority() + ",";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String authStr = authoritiesStr.substring(0, authoritiesStr.length() - 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; configAttrEditor.setAsText(authStr);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#800000">//组装并返回ConfigAttributeDefinition</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (ConfigAttributeDefinition) configAttrEditor.getValue();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; ......<br />
}</pre>
<p>要注意几点的是: <br />
1) 初始化Cache是比较浪费资源的，所以SpringSide中除第一次访问外的Cache的更新是针对性更新。</p>
<p>2) 因为method采用了匹配方式(详见 isMatch() 方法) , 即对于*Book和save*这两个资源来说，只要当前访问方法是Book结尾或以save开头都算匹配得上，所以应该取这些能匹配上的资源的相对应的权限的合集。</p>
<p>3) 使用ConfigAttributeEditor 能更方便地组装ConfigAttributeDefinition。 </p>
<h3>3.3.2 Filter Invocation Authorization</h3>
<pre>&nbsp;&nbsp;&nbsp; &lt;bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="authenticationManager" ref="authenticationManager"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="objectDefinitionSource" ref="filterDefinitionSource"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
<br />
&nbsp;&nbsp;&nbsp; &lt;bean id="filterDefinitionSource" class="org.springside.security.service.acegi.DBFilterInvocationDefinitionSource"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="convertUrlToLowercaseBeforeComparison" value="true"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="useAntPath" value="true"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="acegiCacheManager" ref="acegiCacheManager"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;</pre>
<p><span lang="EN-US" style="font-family: Arial"><font face="Tahoma">&nbsp;&nbsp;&nbsp;&nbsp; </font></span>PathBasedFilterInvocationDefinitionMap和RegExpBasedFilterInvocationDefinitionMap都是 <strong>FilterInvocationDefinitionSource</strong>的实现类,当PATTERN_TYPE_APACHE_ANT字符串匹配上时时,<strong>FilterInvocationDefinitionSourceEditor </strong>选用PathBasedFilterInvocationDefinitionMap 把xml中的文本URL资源权限对应关系信息加载。</p>
<p><span lang="EN-US" style="font-family: Arial"><font face="Tahoma">&nbsp;&nbsp;&nbsp;&nbsp; </font></span><strong>FilterSecurityInterceptor</strong>通过FilterInvocationDefinitionSource的<strong>lookupAttributes(url)</strong>方法获取ConfigAttributeDefinition。 所以，我们可以通过继承FilterInvocationDefinitionSource的抽象类<strong>AbstractFilterInvocationDefinitionSource</strong>，并实现其lookupAttributes方法,从缓存中读取URL资源权限对应关系即可。SpringSide的<strong>DBFilterInvocationDefinitionSource</strong>类部分实现如下:</p>
<pre>public class DBFilterInvocationDefinitionSource <font color="#000080">extends&nbsp;AbstractFilterInvocationDefinitionSource</font> {<br />
<br />
......<br />
&nbsp;&nbsp;&nbsp; public ConfigAttributeDefinition lookupAttributes(String url) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!acegiCacheManager.isCacheInitialized()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; acegiCacheManager.initResourceCache();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (isUseAntPath()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Strip anything after a question mark symbol, as per SEC-161.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int firstQuestionMarkIndex = url.lastIndexOf("?");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (firstQuestionMarkIndex != -1) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; url = url.substring(0, firstQuestionMarkIndex);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List urls = acegiCacheManager.getUrlResStrings();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#800000">//URL资源倒叙排序</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Collections.sort(urls);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Collections.reverse(urls);<br />
<font color="#800000">//是否先全部转为小写再比较</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (convertUrlToLowercaseBeforeComparison) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; url = url.toLowerCase();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GrantedAuthority[] authorities = new GrantedAuthority[0];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (Iterator iterator = urls.iterator(); iterator.hasNext();) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String resString = (String) iterator.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean matched = false;<br />
<font color="#800000">              //可选择使用AntPath和Perl5两种不同匹配模式  </font> <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (isUseAntPath()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; matched = pathMatcher.match(resString, url);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Pattern compiledPattern;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Perl5Compiler compiler = new Perl5Compiler();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; compiledPattern = compiler.compile(resString,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Perl5Compiler.READ_ONLY_MASK);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (MalformedPatternException mpe) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new IllegalArgumentException(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Malformed regular expression: " + resString);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; matched = matcher.matches(url, compiledPattern);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (matched) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ResourceDetails rd = acegiCacheManager.getAuthorityFromCache(resString);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; authorities = rd.getAuthorities();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (authorities.length &gt; 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String authoritiesStr = " ";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; authorities.length; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; authoritiesStr += authorities[i].getAuthority() + ",";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String authStr = authoritiesStr.substring(0, authoritiesStr<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .length() - 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ConfigAttributeEditor configAttrEditor = new ConfigAttributeEditor();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; configAttrEditor.setAsText(authStr);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (ConfigAttributeDefinition) configAttrEditor.getValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
......<br />
&nbsp;}</pre>
<p>继承<font color="#000000">AbstractFilterInvocationDefinitionSource</font>注意几点：<br />
1)&nbsp; 需要先把获取回来的URL资源按倒序派序，以达到 a/b/c/d.* 在 a/.* 之前的效果(详见 Acegi sample 的applicationContext-acegi-security.xml 中的filterInvocationInterceptor的注释)，为的是更具体的URL可以先匹配上，而获取具体URL的权限，如a/b/c/d.*权限AUTH_a, AUTH_b 才可查看,&nbsp; a/.* 需要权限AUTH_a 才可查看，则如果当前用户只拥有权限AUTH_b,则他只可以查看a/b/c/d.jsp 而不能察看a/d.jsp。</p>
<p>2)&nbsp;基于上面的原因，故第一次匹配上的就是当前所需权限，而不是取权限的合集。</p>
<p>3) 可以选用AntPath 或 Perl5 的资源匹配方式，感觉AntPath匹配方式基本足够。</p>
<p>4) Filter 权限控制比较适合于较粗颗粒度的权限，如设定某个模块下的页面是否能访问等，对于具体某个操作如增删修改，是否能执行，用Method&nbsp;&nbsp;Invocation 会更佳些，所以注意两个方面一起控制效果更好</p>
<p>&nbsp;</p>
<h2>3.4 授权操作</h2>
<p><span lang="EN-US" style="font-family: Arial"><font face="Tahoma">&nbsp;&nbsp;&nbsp;&nbsp; </font></span>RBAC模型中有不少多对多的关系，这些关系都能以一个中间表的形式来存放，而Hibernate中可以不建这中间表对应的hbm.xml , 以资源与权限的配置为例，如下:</p>
<pre>&lt;hibernate-mapping package="org.springside.modules.security.domain"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;class name="Permission" table="PERMISSIONS" dynamic-insert="true" dynamic-update="true"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;cache usage="nonstrict-read-write"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;id name="id" column="ID"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;generator class="native"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/id&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="name" column="NAME" not-null="true"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="descn" column="DESCN"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="operation" column="OPERATION"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="status" column="STATUS"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;set name="roles" table="ROLE_PERMIS" lazy="true" inverse="true" cascade="save-update" batch-size="5"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;key&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;column name="PERMIS_ID" not-null="true"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/key&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;many-to-many class="Role" column="ROLE_ID" outer-join="auto"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/set&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;set name="resources" table="PERMIS_RESC" lazy="true" inverse="false" cascade="save-update" batch-size="5"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;key&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;column name="PERMIS_ID" not-null="true"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/key&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;many-to-many class="Resource" column="RESC_ID"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/set&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/class&gt;<br />
&lt;/hibernate-mapping&gt;</pre>
<pre>&lt;hibernate-mapping package="org.springside.modules.security.domain"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;class name="Resource" table="RESOURCES" dynamic-insert="true" dynamic-update="true"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;cache usage="nonstrict-read-write"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;id name="id" column="ID"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;generator class="native"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/id&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="name" column="NAME" not-null="true"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="resType" column="RES_TYPE" not-null="true"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="resString" column="RES_STRING" not-null="true"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="descn" column="DESCN"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;set name="permissions" table="PERMIS_RESC" lazy="true" inverse="true" cascade="save-update" batch-size="5"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;key&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;column name="RESC_ID" not-null="true"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/key&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;many-to-many class="Permission" column="PERMIS_ID" outer-join="auto"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/set&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/class&gt;<br />
&lt;/hibernate-mapping&gt;</pre>
<p>配置时注意几点:</p>
<p>1) 因为是分配某个权限的资源，所以权限是主控方，把inverse设为false，资源是被控方inverse设为true</p>
<p>2) cascade是"save-update"，千万别配成delete</p>
<p>3) 只需要 permission.getResources().add(resource)， permission.getResources()..remove(resource) 即可很方便地完成授权和取消授权操作</p>
&nbsp;<br />
<br />
<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1753827</p>
<img src ="http://www.blogjava.net/i369/aggbug/165458.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-12-05 12:51 <a href="http://www.blogjava.net/i369/articles/165458.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACEGI标签及其扩展</title><link>http://www.blogjava.net/i369/articles/165457.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Wed, 05 Dec 2007 04:50:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/165457.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/165457.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/165457.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/165457.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/165457.html</trackback:ping><description><![CDATA[ACEGI标签
<p style="text-indent: 21pt">虽然Acegi的安全强制过滤器能够阻止用户浏览他们没有权限看到的页面，但最好的做法是从一开始就不提供指向受限制页面的链接。&lt;authz:authorize&gt;标签能够根据当前用户是否拥有恰当权限来决定显示或隐藏Web页面的内容。</p>
<p style="text-indent: 21pt">&lt;authz:authorize&gt;是一个流程控制标签，能够在满足特定安全需求的条件下显示它的内容体。它有三个互斥的参数：</p>
<p>n&nbsp;&nbsp; ifAllGranted——是一个由逗号分隔的权限列表，用户必须拥有所有列出的权限才能渲染标签体；</p>
<p>n&nbsp;&nbsp; ifAnyGranted——是一个由逗号分隔的权限列表，用户必须至少拥有其中的一个才能渲染标签体；</p>
<p>n&nbsp;&nbsp; ifNotGranted——是一个由逗号分隔的权限列表，用户必须不拥有其中的任何一个才能渲染标签体。</p>
<p style="text-indent: 21pt">你可以轻松地想像在JSP中如何使用&lt; authz:authorize&gt;标签根据用户的权限来限制他们的行为。例如，Spring培训应用有一个向用户显示课程有关信息的课程明细页面。 对管理员来说，如果能够从课程明细页面直接跳转到课程编辑页面从而可以更新课程信息是很方便的。但你不希望这个链接对除了管理员之外的其他用户可见。</p>
<p style="text-indent: 21pt">使用&lt;authz:authorize&gt;标签，在用户没有管理员权限的情况下，你可以避免渲染到课程编辑页面的链接：</p>
<p>&nbsp; &lt;authz:authorize ifAllGranted="ROLE_ADMINISTRATOR"&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;a href="admin/editCourse.htm?courseId=${course.id}"&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Edit Course</p>
<p>&nbsp;&nbsp;&nbsp; &lt;/a&gt;</p>
<p>&nbsp; &lt;/authz:authorize&gt;</p>
<p style="text-indent: 21pt">这里，我们使用了ifAllGranted参数，由于这里只需要检查一个授权，所以ifAllGranted标签也是可以使用的。Web应用的安全性只是Acegi功能的一个方面。现在让我们考察它的另一面——保护方法调用。</p>
<br />
<h2>扩展acegi标签实现动态定位方法对应的权限列表</h2>
<p style="text-indent: 21pt">实现如下： <br />
<br />
package com.wonder.cdc.oa.webapp.taglib;<br />
<br />
import java.util.List;<br />
import javax.servlet.ServletContext;<br />
import javax.servlet.jsp.JspException;<br />
import org.acegisecurity.GrantedAuthority;<br />
import org.acegisecurity.taglibs.authz.AuthorizeTag;<br />
import org.apache.commons.lang.StringUtils;<br />
import org.springframework.context.ApplicationContext;<br />
import org.springframework.web.context.support.WebApplicationContextUtils;<br />
import com.wonder.cdc.oa.service.security.AcegiCacheManager;<br />
import com.wonder.cdc.oa.service.security.ResourceDetails;<br />
/**<br />
* 根据当前指定方法名称，判断当前用户是否有权限访问该标签方法体<br />
* @author sudi<br />
*/<br />
public class AuthorizeFuncTag extends AuthorizeTag {<br />
/**<br />
&nbsp; * 扩展acegi标签，实现指定方法名称自动根据名称生成对应的权限字符序列传递给acegi对应的标签<br />
&nbsp; */<br />
private static final long serialVersionUID = 1L;<br />
private String funcString;<br />
public String getFuncString() {<br />
&nbsp; return funcString;<br />
}<br />
public void setFuncString(String funcString) {<br />
&nbsp; this.funcString = funcString;<br />
}<br />
<br />
&nbsp;&nbsp;&nbsp; public int doStartTag() throws JspException {<br />
&nbsp;&nbsp;&nbsp;&nbsp; //如果设置的funcString为空则显示标签体<br />
&nbsp;&nbsp;&nbsp;&nbsp; if(StringUtils.isBlank(getFuncString())){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return EVAL_BODY_INCLUDE;<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp; ServletContext context = pageContext.getServletContext();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context); <br />
&nbsp;&nbsp;&nbsp;&nbsp; AcegiCacheManager acegiCacheManager = (AcegiCacheManager) ctx.getBean("acegiCacheManager");<br />
&nbsp;&nbsp;&nbsp;&nbsp; GrantedAuthority[] authorities = new GrantedAuthority[0];<br />
&nbsp;&nbsp;&nbsp;&nbsp; String roles = " ";<br />
&nbsp;&nbsp;&nbsp;&nbsp; List functions = acegiCacheManager.getFunctions();<br />
&nbsp;&nbsp;&nbsp;&nbsp; String funcString;<br />
&nbsp;&nbsp;&nbsp;&nbsp; boolean findFlag = false;<br />
&nbsp;&nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; functions.size(); i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; funcString = ((String)functions.get(i)).trim();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(funcString.equals(getFuncString())){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; findFlag = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; //如果设置的funcString没有在acegi的权限控制范围内则显示标签体<br />
&nbsp;&nbsp;&nbsp;&nbsp; if(!findFlag){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return EVAL_BODY_INCLUDE;<br />
&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; //如果在acegi的权限控制范围则取出该资源相对应的权限设置到setIfAnyGranted()方法中<br />
&nbsp;&nbsp;&nbsp;&nbsp; ResourceDetails rd = acegiCacheManager.getAuthorityFromCache(getFuncString());&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; if(rd != null){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; authorities = rd.getAuthorities();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (authorities.length &gt; 0) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; authorities.length; i++) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; roles += authorities.getAuthority() + ",";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; roles = roles.substring(0, roles.length() - 1);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; this.setIfAnyGranted(roles);<br />
&nbsp;&nbsp;&nbsp;&nbsp; return super.doStartTag();<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
<br />
标签描述文件：<br />
&nbsp;&nbsp; &lt;tag&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;isVisualable&lt;/name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tag-class&gt;com.wonder.cdc.oa.webapp.taglib.AuthorizeFuncTag&lt;/tag-class&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;info&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 根据当前指定方法名称，判断当前用户是否有权限访问该标签方法体<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/info&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;attribute&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;funcString&lt;/name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;required&gt;true&lt;/required&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;rtexprvalue&gt;false&lt;/rtexprvalue&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/attribute&gt;<br />
&nbsp;&nbsp; &lt;/tag&gt;<br />
<br />
其中的acegiCacheManager,是由spring来维护的，用来管理用户，角色，权限，资源的缓存管理类，<br />
其与持久层是同步更新的，用以获得尽可能的性能提升。<br />
acegi的url和method的访问控制都是基于数据库的，这样要比在xml中配置更灵活。<br />
<br />
扩展前：<br />
&lt;authz:authorize ifAnyGranted="AUTH_ADMIN,AUTH_USER"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;input type="button" style="margin-right: 5px"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; onclick="location.href='&lt;c:url value="/editRole.html?method=Add&amp;from=list"/&gt;'"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value="&lt;fmt:message key="button.add"/&gt;"/&gt;<br />
&lt;/authz:authorize&gt;<br />
扩展后：<br />
&lt;CDC:isVisualable funcString="RoleManager.saveRole"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;input type="button" style="margin-right: 5px"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; onclick="location.href='&lt;c:url value="/editRole.html?method=Add&amp;from=list"/&gt;'"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value="&lt;fmt:message key="button.add"/&gt;"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/CDC:isVisualable&gt;<br />
<br />
可以看到，扩展前必须通过硬编码的方式指定当前用户是否有权限看到该按钮，而且一旦增加新的权限，就要对应修改所有的相关页面，要死人的阿...</p>
<br />
<p style="text-indent: 21pt"><br />
</p>
<br />
<br />
<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1752951</p>
<img src ="http://www.blogjava.net/i369/aggbug/165457.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-12-05 12:50 <a href="http://www.blogjava.net/i369/articles/165457.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>幼学琼林-对比Spring 1.0与2.0的事务配置方式 </title><link>http://www.blogjava.net/i369/articles/157731.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Fri, 02 Nov 2007 04:58:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/157731.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/157731.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/157731.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/157731.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/157731.html</trackback:ping><description><![CDATA[<table width="100%">
    <tbody>
        <tr>
            <td>
            <p>Spring 2.0 的重头戏之一就是AspectJ 式 AOP 配置。 但是一定要通过对比，才能看到2.0式的AOP配置是如何跳出一片新天空的。</p>
            <p><strong>1. 对比</strong> <br />
            先看1.0的标准事务配置:</p>
            <p>Spring 2.0 的重头戏之一就是AspectJ 式 AOP 配置。 但是一定要通过对比，才能看到2.0式的AOP配置是如何跳出一片新天空的。</p>
            <p>1. 对比 <br />
            <strong>先看1.0的标准事务配置:</strong></p>
            <p>
            <div class="code_title">代码</div>
            <div class="code_div">
            <div class="dp-highlighter">
            <div class="bar"></div>
            <ol class="dp-xml">
                <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"baseTxService"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.springframework.transaction.interceptor.TransactionProxyFactoryBean"</span><span>&nbsp;&nbsp;</span></span></li>
                <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="attribute">abstract</span><span>=</span><span class="attribute-value">"true"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"transactionManager"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"transactionManager"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"proxyTargetClass"</span><span>&nbsp;</span><span class="attribute">value</span><span>=</span><span class="attribute-value">"true"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"transactionAttributes"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">props</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">prop</span><span>&nbsp;</span><span class="attribute">key</span><span>=</span><span class="attribute-value">"get*"</span><span class="tag">&gt;</span><span>PROPAGATION_REQUIRED,readOnly</span><span class="tag">&lt;/</span><span class="tag-name">prop</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">prop</span><span>&nbsp;</span><span class="attribute">key</span><span>=</span><span class="attribute-value">"find*"</span><span class="tag">&gt;</span><span>PROPAGATION_REQUIRED,readOnly</span><span class="tag">&lt;/</span><span class="tag-name">prop</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">prop</span><span>&nbsp;</span><span class="attribute">key</span><span>=</span><span class="attribute-value">"save*"</span><span class="tag">&gt;</span><span>PROPAGATION_REQUIRED</span><span class="tag">&lt;/</span><span class="tag-name">prop</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">prop</span><span>&nbsp;</span><span class="attribute">key</span><span>=</span><span class="attribute-value">"remove*"</span><span class="tag">&gt;</span><span>PROPAGATION_REQUIRED</span><span class="tag">&lt;/</span><span class="tag-name">prop</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">props</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">property</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"preInterceptors"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">list</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">ref</span><span>&nbsp;</span><span class="attribute">bean</span><span>=</span><span class="attribute-value">"methodSecurityInterceptor"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">list</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">property</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class=""><span>&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class="alt"><span>&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"bookManager"</span><span>&nbsp;</span><span class="attribute">parent</span><span>=</span><span class="attribute-value">"baseTxService"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"target"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.springside.bookstore.admin.manager.BookManager"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">property</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class="alt"><span>&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
            </ol>
            </div>
            </div>
            <script>render_code();</script>
            <p>&nbsp;</p>
            <p><strong>再看2.0的新配置：</strong></p>
            <p>
            <div class="code_title">代码</div>
            <div class="code_div">
            <div class="dp-highlighter">
            <div class="bar"></div>
            <ol class="dp-xml">
                <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">aop:config</span><span>&nbsp;</span><span class="attribute">proxy-target-class</span><span>=</span><span class="attribute-value">"true"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">aop:advisor</span><span>&nbsp;</span><span class="attribute">pointcut</span><span>=</span><span class="attribute-value">"execution(*&nbsp;yourpackagename..*Manager.*(..))"</span><span>&nbsp;</span><span class="attribute">advice-ref</span><span>=</span><span class="attribute-value">"txAdvice"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">aop:advisor</span><span>&nbsp;</span><span class="attribute">pointcut</span><span>=</span><span class="attribute-value">"execution(*&nbsp;yourpackagename..*Manager.save(..))"</span><span>&nbsp;</span><span class="attribute">advice-ref</span><span>=</span><span class="attribute-value">"fooAdvice"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class=""><span class="tag">&lt;/</span><span class="tag-name">aop:config</span><span class="tag">&gt;</span><span class="tag">&lt;</span><span class="tag-name">tx:advice</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"txAdvice"</span><span>&nbsp;</span><span class="attribute">transaction-manager</span><span>=</span><span class="attribute-value">"transactionManager"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">tx:attributes</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">tx:method</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"save*"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">tx:method</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"remove*"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">tx:method</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"*"</span><span>&nbsp;</span><span class="attribute">read-only</span><span>=</span><span class="attribute-value">"true"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class="alt"><span>&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">tx:attributes</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class=""><span class="tag">&lt;/</span><span class="tag-name">tx:advice</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
                <li class="alt"><span>&nbsp;&nbsp;</span></li>
                <li class=""><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"bookManager"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.springside.bookstore.commons.service.BookManager"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
            </ol>
            </div>
            </div>
            <script>render_code();</script>
            <p>&nbsp;</p>
            <p><strong>2.进步</strong> <br />
            <strong>1. AOP的配置方式也AOP了。</strong> <br />
            对比1.0的配置文件，因为下面2提到的限制，事关安全acegi methodSecurityInterceptor 拦截器要配置在关于事务的TransactionProxyFactoryBean的preInterceptors属性里，这样子就一点不AOP了，而2.0使用ponintcut expression，很AOP的配置一切Aspect。 <br />
            <br />
            <strong>2. 1.0时，一个已经AOP过的object不能再次被AOP。</strong> <br />
            在Spring 1.0的文档里Rod说，比如&lt;bean id="bookManager" parent="baseTxService"&gt;已经进行了一次AOP，如果想在这个Bean上再配一层AOP，比如要对方法执行结果缓存，无论以1.0 还是2.0的方式定义，cglib方式是会报错的，而基于接口的方式，结果不确定。 <br />
            <br />
            <strong>3. BookManager能直接定义自己，而不是像1.0那样作匿名内部target。</strong></p>
            <p>虽然在1.0时代的BeanNameAutoProxyCreator 达到类似作用，但只能用BeanName来匹配比较危险，没有AspectJ的pointcut语法细致。</p>
            <p><strong>3. 语法</strong> <br />
            满江红翻译的Spring参考文档 6.3 schema-based AOP support 提供了aspect,advisor,advide三种组装方法的解释，其中aspect是aspectJ原装，但稍复杂.</p>
            <p>唯一有点难懂的是pointcut里的语法，其实也很好学，Spring<a href="http://www.redsaga.com/spring_ref/2.0RC2/html/aop.html#d0e6939" target="blank">参考文档6.2.3.4里</a>有完整说明 ，其实一排子过去是</p>
            <p>
            <div class="code_title">代码</div>
            <div class="code_div">
            <div class="dp-highlighter">
            <div class="bar"></div>
            <ol class="dp-j">
                <li class="alt"><span><span>execution(modifiers-pattern?&nbsp;ret-type-pattern&nbsp;declaring-type-pattern?&nbsp;name-pattern(param-pattern)&nbsp;</span><span class="keyword">throws</span><span>-pattern?)&nbsp;&nbsp;</span></span></li>
            </ol>
            </div>
            </div>
            <script>render_code();</script>其中带问号的modifiers-pattern?(public/protected) 和 declaring-type-pattern? throws-pattern? 可以不填
            <p>&nbsp;</p>
            <p>可见execution(* *..BookManager.save(..))</p>
            <p>第一颗* 代表ret-type-pattern 返回值可任意， <br />
            *..BookManager 代表任意Pacakge里的BookManager类。 <br />
            如果写成com.xyz.service.* 则代表com.xyz.service下的任意类 <br />
            com.xyz.service..* com.xyz.service则代表com.xyz.service及其子package下的任意类 <br />
            save代表save方法，也可以写save* 代表saveBook()等方法 <br />
            (..) 匹配0个参数或者多个参数的，任意类型 <br />
            (x,..) 第一个参数的类型必须是X <br />
            (x,,,s,..) 匹配至少4个参数，第一个参数必须是x类型，第二个和第三个参数可以任意，第四个必须是s类型。 </p>
            <p>注意name-pattern千万不要写成*..*Manager ，这样子的话会把所有第三方类库的Manager比如Spring的PlatformTranstationManager 也加入aop，非常危险。所以最好还是加上项目的package前缀，如org.springside <br />
            </p>
            </td>
        </tr>
    </tbody>
</table>
<br />
<span class="graytag">声明：JavaEye文章版权属于作者，受法律保护。没有作者书面许可不得转载。若作者同意转载，必须以超链接形式标明文章原始出处和作者。</span> <br />
<hr />
<span class="graytag">相关文章：</span></a> &nbsp;&nbsp;<a href="http://www.javaeye.com/topic/24425">selenium参考手册中文翻译</a> <br />
<br />
转载自:JavaEye文章(http://www.javaeye.com/topic/27099)
<img src ="http://www.blogjava.net/i369/aggbug/157731.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-11-02 12:58 <a href="http://www.blogjava.net/i369/articles/157731.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于spring 2.0自定义xml 标记 </title><link>http://www.blogjava.net/i369/articles/157730.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Fri, 02 Nov 2007 04:56:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/157730.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/157730.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/157730.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/157730.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/157730.html</trackback:ping><description><![CDATA[<span style="color: red">关于spring 2.0自定义xml 标记 （一 主要的相关类）</span> <br />
<br />
<p>在spring 2.0 中，增加了自定义xml标记这一重大的功能。下面主要看一下spring 2.0实现这一功能的主要相关类：</p>
<p><strong>NamespaceHandlerResolver（接口）</strong> <br />
由DefaultBeanDefinitionDocumentReader使用，用于定位NamespaceHandler，指定特定的命名空间uri</p>
<p>实现类： <br />
<strong>DefaultNamespaceHandlerResolver</strong> <br />
<br />
通过map 保存所有的对应关系 <br />
默认使用spring.handlers文件来保存所有的handlers <br />
可以定义其他的location 如：</p>
<p>String location = "org/springframework/beans/factory/xml/support/customNamespace.properties"; <br />
NamespaceHandlerResolver resolver = new DefaultNamespaceHandlerResolver(getClass().getClassLoader(), location); <br />
<br />
<strong>NamespaceHandler（接口）</strong> <br />
<br />
基础接口，用于DefaultBeanDefinitionDocumentReader处理自定义命名空间。 <br />
方法： <br />
void init(); <br />
由DefaultBeanDefinitionDocumentReader调用在构造完后但在解析自定义元素前。 <br />
<br />
BeanDefinition parse(Element element, ParserContext parserContext); <br />
解析指定的元素。 <br />
<br />
BeanDefinitionHolder decorate(Node element, <br />
BeanDefinitionHolder definition, <br />
ParserContext parserContext); <br />
执行相应的修饰。</p>
<p>实现类： <br />
<br />
<strong>NamespaceHandlerSupport（抽象类）</strong> <br />
<br />
主要的三个方法： <br />
protected final void registerBeanDefinitionDecorator( <br />
String elementName, <br />
BeanDefinitionDecorator decorator) <br />
注册decorator，通过element <br />
<br />
protected final void registerBeanDefinitionDecoratorForAttribute( <br />
String attributeName, <br />
BeanDefinitionDecorator decorator) <br />
注册decorator，通过attr <br />
<br />
protected final void registerBeanDefinitionParser( <br />
String elementName, <br />
BeanDefinitionParser parser) <br />
注册BeanDefinitionParser，通过element</p>
<p>实际的操作由具体的BeanDefinitionDecorator 或者BeanDefinitionParser 执行</p>
<p><strong>BeanDefinitionDecorator(接口)</strong></p>
<p>装饰相关的自定义属性。</p>
<p>AbstractInterceptorDrivenBeanDefinitionDecorator <br />
用于注册相应的Interceptor bean 定义，使用aop代理</p>
<p><strong>其他类：</strong></p>
<p>PluggableSchemaResolver，用于自定义相关的schema,默认的schema 保存于spring.schemas文件中</p>
<p>可以通过覆盖resolveEntity方法来装载相应的自定义xsd文件</p>
<p><strong>主要的执行类：</strong> <br />
<br />
XmlBeanDefinitionReader <br />
<br />
用于处理相应的读取工作，其实主要的工作委派给BeanDefinitionDocumentReader</p>
<p>实际的类，就介绍到这，下一节通过实例来说明如何定义自定义xml 元素</p>
<br />
<span style="color: red">关于spring 2.0自定义xml 标记 （二 如何实现）</span> <br />
<p>看了spring test 用例，其实实现这一功能还算比较简单，主要分以下的步骤，具体的实例可以去参考spring 自带的testcase</p>
<p>首先定义相关xsd文件，用于验证相应的行为： <br />
<br />
主要增加了4个自定义元素和1个属性：</p>
<p>&lt;?xml version="1.0" encoding="UTF-8" standalone="no"?&gt;</p>
<p>&lt;xsd:schema xmlns="http://www.springframework.org/schema/beans/test" <br />
xmlns:xsd="http://www.w3.org/2001/XMLSchema" <br />
targetNamespace="http://www.springframework.org/schema/beans/test" <br />
elementFormDefault="qualified"&gt;</p>
<p>&lt;xsd:element name="testBean"&gt; <br />
&lt;xsd:complexType&gt; <br />
&lt;xsd:attribute name="id" type="xsd:string" use="required" form="unqualified"/&gt; <br />
&lt;xsd:attribute name="name" type="xsd:string" use="required" form="unqualified"/&gt; <br />
&lt;xsd:attribute name="age" type="xsd:integer" use="required" form="unqualified"/&gt; <br />
&lt;/xsd:complexType&gt; <br />
&lt;/xsd:element&gt;</p>
<p>&lt;xsd:element name="set"&gt; <br />
&lt;xsd:complexType&gt; <br />
&lt;xsd:attribute name="name" type="xsd:string" use="required" form="unqualified"/&gt; <br />
&lt;xsd:attribute name="age" type="xsd:integer" use="required" form="unqualified"/&gt; <br />
&lt;/xsd:complexType&gt; <br />
&lt;/xsd:element&gt;</p>
<p>&lt;xsd:element name="debug"/&gt; <br />
&lt;xsd:element name="nop"/&gt;</p>
<p>&lt;xsd:attribute name="object-name" type="xsd:string"/&gt;</p>
<p>&lt;/xsd:schema&gt;</p>
<p>接着定义handler映射文件：customNamespace.properties</p>
<p><a href="http://www.javaeye.com/topic/http/://www.springframework.org/schema/beans/test=org.springframework.beans.factory.xml.support.TestNamespaceHandler" target="blank">http\://www.springframework.org/schema/beans/test=org.springframework.beans.factory.xml.support.TestNamespaceHandler</a></p>
<p>定义Handler:</p>
<p>主要注册相应的解析类和装饰类</p>
<p>&nbsp;</p>
<p>publicclass TestNamespaceHandler extends NamespaceHandlerSupport {</p>
<p>publicvoid init() {</p>
<p>//相对于每个xsd中定义的元素</p>
<p>registerBeanDefinitionParser("testBean", new TestBeanDefinitionParser());</p>
<p>registerBeanDefinitionDecorator("set", new PropertyModifyingBeanDefinitionDecorator());</p>
<p>registerBeanDefinitionDecorator("debug", new DebugBeanDefinitionDecorator());</p>
<p>registerBeanDefinitionDecorator("nop", new NopInterceptorBeanDefinitionDecorator());</p>
<p>registerBeanDefinitionDecoratorForAttribute("object-name", new ObjectNameBeanDefinitionDecorator());</p>
<p>}</p>
<p>}</p>
<p>&nbsp;</p>
<p>定义各个解析类：</p>
<p>privatestaticclass TestBeanDefinitionParser implements BeanDefinitionParser {</p>
<p>public BeanDefinition parse(Element element, ParserContext parserContext) {</p>
<p>RootBeanDefinition definition = new RootBeanDefinition();</p>
<p>definition.setBeanClass(TestBean.class);</p>
<p>&nbsp;</p>
<p>MutablePropertyValues mpvs = new MutablePropertyValues();</p>
<p>mpvs.addPropertyValue("name", element.getAttribute("name"));</p>
<p>mpvs.addPropertyValue("age", element.getAttribute("age"));</p>
<p>definition.setPropertyValues(mpvs);</p>
<p>&nbsp;</p>
<p>parserContext.getRegistry().registerBeanDefinition(element.getAttribute("id"), definition);</p>
<p>&nbsp;</p>
<p>returnnull;</p>
<p>}</p>
<p>}</p>
<p>privatestaticclassPropertyModifyingBeanDefinitionDecorator implements BeanDefinitionDecorator {</p>
<p>public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition,</p>
<p>ParserContext parserContext) {</p>
<p>Element element = (Element)node;</p>
<p>BeanDefinition def = definition.getBeanDefinition();</p>
<p>&nbsp;</p>
<p>MutablePropertyValues mpvs = (def.getPropertyValues() == null) ?</p>
<p>new MutablePropertyValues() : def.getPropertyValues();</p>
<p>mpvs.addPropertyValue("name", element.getAttribute("name"));</p>
<p>mpvs.addPropertyValue("age", element.getAttribute("age"));</p>
<p>&nbsp;</p>
<p>((AbstractBeanDefinition) def).setPropertyValues(mpvs);</p>
<p>return definition;</p>
<p>}</p>
<p>}</p>
<p>privatestaticclassDebugBeanDefinitionDecorator extends AbstractInterceptorDrivenBeanDefinitionDecorator {</p>
<p>&nbsp;</p>
<p>protected BeanDefinition createInterceptorDefinition(Node node) {</p>
<p>returnnew RootBeanDefinition(DebugInterceptor.class);</p>
<p>}</p>
<p>}</p>
<p>privatestaticclassNopInterceptorBeanDefinitionDecorator extends</p>
<p>AbstractInterceptorDrivenBeanDefinitionDecorator {</p>
<p>&nbsp;</p>
<p>protected BeanDefinition createInterceptorDefinition(Node node) {</p>
<p>returnnew RootBeanDefinition(NopInterceptor.class);</p>
<p>}</p>
<p>}</p>
<p>privatestaticclassObjectNameBeanDefinitionDecorator implements BeanDefinitionDecorator {</p>
<p>public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition,</p>
<p>ParserContext parserContext) {</p>
<p>Attr objectNameAttribute = (Attr)node;</p>
<p>definition.getBeanDefinition().setAttribute("objectName", objectNameAttribute.getValue());</p>
<p>return definition;</p>
<p>}</p>
<p>}</p>
<p>&nbsp;</p>
<p>可以定义EntityResolver，用于验证相应的xsd</p>
<p>privateclass DummySchemaResolver extends PluggableSchemaResolver {</p>
<p>&nbsp;</p>
<p>public DummySchemaResolver() {</p>
<p>super(CustomNamespaceHandlerTests.this.getClass().getClassLoader());</p>
<p>}</p>
<p>&nbsp;</p>
<p>public InputSource resolveEntity(String publicId, String systemId) throws IOException {</p>
<p>InputSource source = super.resolveEntity(publicId, systemId);</p>
<p>if (source == null) {</p>
<p>Resource resource = <br />
new ClassPathResource("org/springframework/beans/factory/xml/support/spring-test.xsd");</p>
<p>source = new InputSource(resource.getInputStream());</p>
<p>source.setPublicId(publicId);</p>
<p>source.setSystemId(systemId);</p>
<p>}</p>
<p>return source;</p>
<p>}</p>
<p>}</p>
<p>关键的一步，如何生效：</p>
<p>String location = "org/springframework/beans/factory/xml/support/customNamespace.properties";</p>
<p>NamespaceHandlerResolver resolver = new DefaultNamespaceHandlerResolver( <br />
getClass().getClassLoader(), location);</p>
<p>DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();</p>
<p>XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);</p>
<p>reader.setNamespaceHandlerResolver(resolver);</p>
<p>reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD);</p>
<p>reader.setEntityResolver(new DummySchemaResolver());</p>
<p>reader.loadBeanDefinitions(getResource());</p>
<p>写一个测试xml文件：</p>
<p>&lt;?xmlversion="1.0"encoding="UTF-8"?&gt;</p>
<p>&lt;beansxmlns="http://www.springframework.org/schema/beans"</p>
<p>xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"</p>
<p>xmlns:test="http://www.springframework.org/schema/beans/test"</p>
<p>xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd</p>
<p><a href='http://www.springframework.org/schema/beans/testhttp://www.springframework.org/schema/beans/factory/xml/support/spring-test.xsd">' target=blank href_cetemp='http://www.springframework.org/schema/beans/testhttp://www.springframework.org/schema/beans/factory/xml/support/spring-test.xsd">'>http://www.springframework.org/schema/beans/testhttp://www.springframework.org/schema/beans/factory/xml/support/spring-test.xsd"&gt;</a></p>
<p>&lt;test:testBeanid="testBean"name="Rob Harrop"age="23"/&gt;</p>
<p>&lt;beanid="customisedTestBean"class="org.springframework.beans.TestBean"&gt;</p>
<p>&lt;test:setname="Rob Harrop"age="23"/&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&lt;beanid="debuggingTestBean"class="org.springframework.beans.TestBean"&gt;</p>
<p>&lt;test:debug/&gt;</p>
<p>&lt;propertyname="name"value="Rob Harrop"/&gt;</p>
<p>&lt;propertyname="age"value="23"/&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&lt;beanid="chainedTestBean"class="org.springframework.beans.TestBean"&gt;</p>
<p>&lt;test:debug/&gt;</p>
<p>&lt;test:nop/&gt;</p>
<p>&lt;propertyname="name"value="Rob Harrop"/&gt;</p>
<p>&lt;propertyname="age"value="23"/&gt;</p>
<p>&lt;/bean&gt;</p>
<p>&lt;beanid="decorateWithAttribute"class="org.springframework.beans.TestBean"test:object-name="foo"/&gt;</p>
<p>&lt;/beans&gt;</p>
<p>相关的测试方法：</p>
<p>publicvoid testSimpleParser() throws Exception {</p>
<p>TestBean bean = (TestBean) this.beanFactory.getBean("testBean");</p>
<p>assetTestBean(bean);</p>
<p>}</p>
<p>publicvoid testSimpleDecorator() throws Exception {</p>
<p>TestBean bean = (TestBean) this.beanFactory.getBean("customisedTestBean");</p>
<p>assetTestBean(bean);</p>
<p>}</p>
<p>publicvoid testProxyingDecorator() throws Exception {</p>
<p>ITestBean bean = (ITestBean) this.beanFactory.getBean("debuggingTestBean");</p>
<p>assetTestBean(bean);</p>
<p>assertTrue(AopUtils.isAopProxy(bean));</p>
<p>Advisor[] advisors = ((Advised) bean).getAdvisors();</p>
<p>assertEquals("Incorrect number of advisors", 1, advisors.length);</p>
<p>assertEquals("Incorrect advice class.", DebugInterceptor.class, advisors[0].getAdvice().getClass());</p>
<p>}</p>
<p>publicvoid testChainedDecorators() throws Exception {</p>
<p>ITestBean bean = (ITestBean) this.beanFactory.getBean("chainedTestBean");</p>
<p>assetTestBean(bean);</p>
<p>assertTrue(AopUtils.isAopProxy(bean));</p>
<p>Advisor[] advisors = ((Advised) bean).getAdvisors();</p>
<p>assertEquals("Incorrect number of advisors", 2, advisors.length);</p>
<p>assertEquals("Incorrect advice class.", DebugInterceptor.class, advisors[0].getAdvice().getClass());</p>
<p>assertEquals("Incorrect advice class.", NopInterceptor.class, advisors[1].getAdvice().getClass());</p>
<p>}</p>
<p>publicvoid testDecorationViaAttribute() throws Exception {</p>
<p>RootBeanDefinition beanDefinition <br />
= (RootBeanDefinition)this.beanFactory.getBeanDefinition("decorateWithAttribute");</p>
<p>assertEquals("foo", beanDefinition.getAttribute("objectName"));</p>
<p>}</p>
<p>privatevoid assetTestBean(ITestBean bean) {</p>
<p>assertEquals("Invalid name", "Rob Harrop", bean.getName());</p>
<p>assertEquals("Invalid age", 23, bean.getAge());</p>
<p>}</p>
<br />
<img src ="http://www.blogjava.net/i369/aggbug/157730.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-11-02 12:56 <a href="http://www.blogjava.net/i369/articles/157730.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]CAS及客户端Acegi的安装配置指南</title><link>http://www.blogjava.net/i369/articles/155776.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Thu, 25 Oct 2007 01:19:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/155776.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/155776.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/155776.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/155776.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/155776.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: CAS及客户端Acegi的安装配置指南（上）作者：龙智&nbsp;(Dragon)时间：2006-07-09&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CAS（Central Authentication Service）是耶鲁大学开发的一个开源的SSO（single sign on，单点登录）系统。它提供了丰富的客...&nbsp;&nbsp;<a href='http://www.blogjava.net/i369/articles/155776.html'>阅读全文</a><img src ="http://www.blogjava.net/i369/aggbug/155776.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/i369/" target="_blank">芦苇</a> 2007-10-25 09:19 <a href="http://www.blogjava.net/i369/articles/155776.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]浅谈Acegi配置</title><link>http://www.blogjava.net/i369/articles/155769.html</link><dc:creator>芦苇</dc:creator><author>芦苇</author><pubDate>Thu, 25 Oct 2007 01:06:00 GMT</pubDate><guid>http://www.blogjava.net/i369/articles/155769.html</guid><wfw:comment>http://www.blogjava.net/i369/comments/155769.html</wfw:comment><comments>http://www.blogjava.net/i369/articles/155769.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/i369/comments/commentRss/155769.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/i369/services/trackbacks/155769.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Acegi配置文档 作者：javafish(likunkun) Email:javafish@sunxin.org Acegi是基于Spring的一个开源的安全认证框架，现在的最新版本是1.04。Acegi的特点就是有很多的过滤器：不过我们也用不到这么多的过滤器，只是可以把它们看作为一个个的模块，在用的时候加上自己用的着的即可，由于认证的流程的