﻿<?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-闲人野居-随笔分类-aop</title><link>http://www.blogjava.net/zyl/category/17748.html</link><description>好好学习，天天向上</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 19:46:51 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 19:46:51 GMT</pubDate><ttl>60</ttl><item><title>用AOP实现观察者模式</title><link>http://www.blogjava.net/zyl/archive/2006/11/17/81790.html</link><dc:creator>布衣郎</dc:creator><author>布衣郎</author><pubDate>Fri, 17 Nov 2006 08:55:00 GMT</pubDate><guid>http://www.blogjava.net/zyl/archive/2006/11/17/81790.html</guid><wfw:comment>http://www.blogjava.net/zyl/comments/81790.html</wfw:comment><comments>http://www.blogjava.net/zyl/archive/2006/11/17/81790.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zyl/comments/commentRss/81790.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zyl/services/trackbacks/81790.html</trackback:ping><description><![CDATA[
		<div style="line-height: 30px;">
				<b>
观察者(Observer)模式</b>
				<br />    用途：定义对象之间的一对多依赖关系，因此，当一个对象的状态发生改变时，其所有依赖项都会得到通知，并自动更新。<br />    它是 OO 设计模式的皇后。该模式被人们广泛应用（特别是在 GUI 应用程序中），并构成了 MVC 架构的关键部分。它处理复杂的问题，而在解决这类问题方面表现得相对较好。但是，从实现需要的努力和代码理解的角度来说，它还是带来了一些难以解决的难题。<br />    不足：观察者(Observer)模式要求您先侵入系统中现有的类，然后才能支持该模式 —— 至少在 Java 语言中是这样。<br />    而方面可以降低像观察者(Observer)模式这种侵入性模式的负担，使得模式参与者更灵活，因为不需要包含模式代码。而且，模式本身可以变成抽象的基本方面，允许开发人员通过导入和应用它来实现重用，不必每次都要重新考虑模式。<br />    下面通过一个例子来说明：<br />    假设如下的情况：<br />    AccountManager 对象能够观察 Account，这样，在帐户状态改变时，它们可以向销售人员发送一封电子邮件。<br />    代码如下：
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><br /><br />public class Account {<br /><br />    private int state;<br />     private String name;<br /><br />    public String getName() {<br />        return name;<br />    }<br />    public Account(String name) {<br />        super();<br />        this.name = name;<br />    }<br />    public int getState() {<br />        return state;<br />    }<br /><br />    public void setState(int state) {<br />        this.state = state;<br />    }<br />     @Override<br />    public String toString() {<br />        return name;<br />    }<br />}<br /><br />public class AccountManager {<br /><br />    public void sendEmail(Account account) {<br />         System.out.println("send Email:" + account);<br />    }<br />}<br /><br /></div>来看一下java代码是如何实现观察者模式的<br /><br /><b>Java 语言的观察者</b><br />虽然实现的差异很明显，但在它们之间还是有一些相似之处。不论如何实现观察者，代码中都必须回答以下 4 个问题：<br />   1. 哪个对象是主体，哪个对象是观察者？<br />   2. 什么时候主体应当向它的观察者发送通知？<br />   3. 当接收到通知时，观察者应该做什么？<br />   4. 观察关系应当在什么时候开始，什么时候终止？<br /><br /><b>角色定义</b><br />    首先从标记器接口来分配角色开始。Observer 接口只定义了一个方法：update()，它对应着 Subject 发送通知时执行的操作。 Subject 承担着更多的职责。它的标记器接口定义了两个方法，一个用来跟踪观察者，另一个用来通知事件的那些观察者。
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><br /><br />public interface Observer {<br /><br />    public void update(Subject subject);<br />}<br /><br />public interface Subject {   <br />    public void addObserver(Observer o);<br />    public void removeObserver(Observer o);<br />    public void notifyObservers();<br />}  </div><br />一旦定义了这些角色，就可以把它们应用到系统中对应的角色上。<br /><br /><b>应用观察者角色</b><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><br /><br />public class AccountManager implements Observer {<br /><br />   public void update(Subject subject) {<br />        sendEmail((Account) subject);<br />    }<br />}<br /><br /></div><b>跟踪和通知观察者</b><br />一旦这项工作完成，就可以转移到Subject。在这里，要对 Account进行修改：
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><br />  private Set observers = new HashSet();  <br />  public void addObserver(Observer o) {<br />    observers.add(o);<br />  }<br />  public void removeObserver(Observer o) {<br />    observers.remove(o);<br />  }<br />  public void notifyObservers() {<br />    for (Observer o : observers) {<br />      o.update(this);<br />    }<br />  }</div><br /><b>触发事件</b><br />    现在已经把类调整到它们在模式中的角色上了。但是，还需要回过头来，在对应的事件发生时触发通知。<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);">
    Account<br />    public void setState(int state) {<br />        if (this.state != state) {<br />            this.state = state;<br />            notifyObservers();<br />        }<br />    }</div><br /><b>启动观察关系</b><br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);">
public class ObserverClient {<br /><br />    public static void main(String[] args) {<br />        AccountManager manager = new AccountManager();<br />        AccountManager manager2 = new AccountManager();<br />        Account account = new Account("Account1");<br />        account.addObserver(manager);<br />        account.addObserver(manager2);<br />        account.setState(1);<br />    }<br />}</div><br /><br /><b>AspectJ 观察者</b><br /><br /><b>定义抽象类来实现观察者</b><br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);">
//采用java5的泛型来定义观察对象和主体<br />public abstract class AbstractSubjectObserver&lt;Sub, Obv&gt; {<br /><br />       //不允许空item<br />    protected static void iaxIfNull(Object item, String name) {<br />        if (null == item) {<br />            throw new IllegalArgumentException("null " + name);<br />        }<br />    }<br />       //用于保存所有的主体和观察者之间的对象关系<br />    private final HashMap&lt;Sub, ArrayList&lt;Obv&gt;&gt; fObservers = new HashMap&lt;Sub, ArrayList&lt;Obv&gt;&gt;();<br /><br />    protected AbstractSubjectObserver() {<br /><br />    }<br /><br />    public synchronized void addObserver(Sub subject, Obv observer) {<br />        iaxIfNull(subject, "subject");<br />        iaxIfNull(observer, "observer");<br />        getObservers(subject).add(observer);<br />    }<br /><br />    public synchronized void removeObserver(<br />            Sub subject,<br />            Obv observer) {<br />        iaxIfNull(subject, "subject");<br />        iaxIfNull(observer, "observer");<br />        getObservers(subject).remove(observer);<br />    }<br /><br />    public synchronized ArrayList&lt;Obv&gt; getObservers(Sub subject) {<br />        iaxIfNull(subject, "subject");<br />        ArrayList&lt;Observer&gt; result = fObservers.get(subject);<br />        if (null == result) {<br />            result = new ArrayList&lt;Observer&gt;();<br />            fObservers.put(subject, result);<br />        }<br />        return result;<br />    }<br />    //主体状态改变，更新所有的观察者对象<br />    protected void subjectChanged(Sub subject) {<br />        iaxIfNull(subject, "subject");<br />        ArrayList&lt;Observer&gt; list = getObservers(subject);<br />        if (!list.isEmpty()) {<br />            updateObservers(subject, Collections.unmodifiableList(list));<br />        }<br />    }<br /><br />   //更新所有观察者操作，调用具体的updateObserver<br />    protected synchronized void updateObservers(<br />            Subject subject,<br />            List&lt;Observer&gt; observers) {<br />        iaxIfNull(subject, "subject");<br />        iaxIfNull(observers, "observers");<br />        for (Observer observer : observers) {<br />            updateObserver(subject, observer);<br />        }<br />    }<br />     //需要子类实现，具体的更新操作<br />    protected abstract void updateObserver(Subject subject, Observer observer);<br /><br />}</div><br /><br /><b>定义方面：</b><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);">
public abstract aspect SubjectObserver&lt;Sub, Obv&gt; extends<br />        AbstractSubjectObserver&lt;Sub, Obv&gt; {<br /><br />    //需要横切的代码，表示哪些需要触发观察者模式<br />    protected abstract pointcut changing();<br /><br />    //在状态改变后，触发所有的观察者<br />    after(Sub subject) returning : target(subject) &amp;&amp; changing() {<br />        subjectChanged(subject);<br />    }<br />}<br /></div><br />无需改动原有的实现，看一下客户端如何启动观察关系<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);">
public class ObserverClient {<br /><br />    public static void main(String[] args) {<br />        Account account=new Account("Account1");<br />        Client client=Client.aspectOf();<br />        client.addObserver(account,new AccountManager());<br />        client.addObserver(account,new AccountManager());<br />        account.setState(1);<br />    }<br />    static aspect Client extends SubjectObserver&lt;Account, AccountManager&gt; {<br /><br />        protected pointcut changing() : execution(void  Account.setState(int));<br /><br />        protected void updateObserver(Account account, AccountManager manager) {<br />            manager.sendEmail(account);<br />        }<br />    }<br />}</div><br /><br /><b>AspectJ 观察者的分析</b><br />   易于理解：从参与者的视角来看，AOP 版本的观察者更简单<br />   重用:可以很容易的实现重用<br /><br /><br /><br /></div>
<img src ="http://www.blogjava.net/zyl/aggbug/81790.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zyl/" target="_blank">布衣郎</a> 2006-11-17 16:55 <a href="http://www.blogjava.net/zyl/archive/2006/11/17/81790.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>几个有用的静态方面，用于审查代码（aspectJ实现）</title><link>http://www.blogjava.net/zyl/archive/2006/11/16/81587.html</link><dc:creator>布衣郎</dc:creator><author>布衣郎</author><pubDate>Thu, 16 Nov 2006 10:56:00 GMT</pubDate><guid>http://www.blogjava.net/zyl/archive/2006/11/16/81587.html</guid><wfw:comment>http://www.blogjava.net/zyl/comments/81587.html</wfw:comment><comments>http://www.blogjava.net/zyl/archive/2006/11/16/81587.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zyl/comments/commentRss/81587.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zyl/services/trackbacks/81587.html</trackback:ping><description><![CDATA[收集了几个常用的方面：<br /><br />NoCallsIntoTestFromOutside     禁止从产品包到测试包的引用<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);">public abstract aspect NoCallsIntoTestFromOutside {<br />    //引用带有test的包的所有可能操作<br />    pointcut referToTestPackage():<br />        call(* *..test..*.*(..)) || call(*..test..*.new(..))<br />        || get(* *..test..*.*) || set(* *..test..*.*)<br />        || get(*..test..* *) || set(*..test..* *)<br />        || (staticinitialization(!*..test..*)<br />           &amp;&amp; staticinitialization(*..test..*+))<br />        || call(* *(*..test..*, ..))<br />        || call(* *(*, *..test..*, ..))<br />        || call(* *(*, *, *..test..*))<br />        || call(* *(.., *..test..*))<br />        || execution(* *(*..test..*, ..))<br />        || execution(* *(*, *..test..*, ..))<br />        || execution(* *(*, *, *..test..*, ..))<br />        || execution(* *(.., *..test..*))<br />        ;<br />    // getcode scary-tests END<br /><br />    abstract protected pointcut withinTypes();<br /><br />    pointcut fromWithinNonTest(): within(!*..test..*);<br /><br />    declare error: withinTypes() &amp;&amp; referToTestPackage() <br />        &amp;&amp; fromWithinNonTest(): "production code referring to test code";    <br />}
</div><br />UtilityClassEnforced 	    禁止构造实用工具类<br /><br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);">public aspect UtilityClassEnforced {<br />    <br />    declare error : <br />        //定义非private 的构造器<br />        execution(!private (@UtilityClass *).new(..))<br />        //调用new 初始化方法<br />        || call((@UtilityClass *).new(..))<br />        //执行工具类的任何方法<br />        || execution((@UtilityClass *) *(..))        <br />        : "no instances of utility classes";<br /><br />}<br /><br />@Retention(RetentionPolicy.RUNTIME)<br />@Target({ElementType.TYPE}) <br />public @interface UtilityClass {<br /><br />} <br /></div><br />NoSystemOut     禁止使用 System.err 或 System.out<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);">public abstract aspect NoSystemOut {<br />    abstract protected pointcut withinTypes；<br />    //读取System.out对象<br />    declare error: withinTypes() &amp;&amp; get(PrintStream System.out) : "no System.out";<br />     //读取System.err对象<br />    declare error: withinTypes() &amp;&amp; get(PrintStream System.err) : "no System.err";<br />    //读取FileDescriptor.err<br />    declare error: withinTypes() &amp;&amp; get(PrintStream FileDescriptor.err) : "no FileDescriptor.err";<br />    //读取FileDescriptor.out<br />    declare error: withinTypes() &amp;&amp; get(PrintStream FileDescriptor.out) : "no FileDescriptor.out";<br />     //执行Throwable.printStackTrace()方法<br />    declare error: withinTypes() &amp;&amp; call(void Throwable.printStackTrace()) : "no System.err";<br />}</div><br />GetterSetter     禁止在除初始化或 getter 方法以外进行字段读取操作，禁止在初始化或 setter 方法以外进行字段写操作<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);">public abstract aspect GetterSetter {<br />    <br />    abstract protected pointcut withinTypes();<br />    //所有的sets 非public fields<br />    pointcut sets() : set(!public * *);<br />       //所有的gets 非public fields<br />    pointcut gets() : get(!public * *);<br />    declare error : withinTypes() &amp;&amp; gets() &amp;&amp; <br />        //在get*方法或者构造器以外地方使用<br />        !(withincode(!void get*()) || withincode(new(..)))<br />        : "non-public field-get outside constructor or getter method";<br />    declare error : withinTypes() &amp;&amp; sets() &amp;&amp; <br />        !(withincode(void set*(*)) || withincode(new(..)))<br />        : "non-public field-set outside constructor or setter method";<br />}</div><br />NoNullParameters           在公共方法传递空参数时抛出异常<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);">public abstract aspect NoNullParameters {<br />    abstract protected pointcut withinTypes();<br />    <br />    pointcut publicParameters() : <br />         //执行public 构造器或者public 方法<br />        (execution(public new(*,..)) || execution(public * *(*,..)))<br />         //除了执行非Object的参数,如原类型，int,long<br />        &amp;&amp; !(execution(* *(!Object+)) || execution(*.new(!Object+)));<br />    //如果参数为null,则抛出例外            <br />    before() : withinTypes() &amp;&amp; publicParameters() {<br />        Object[] args = thisJoinPoint.getArgs();<br />        for (int i = 0; i &lt; args.length; i++) {<br />            if (null == args[i]) {<br />                JoinPoint.StaticPart sp = thisJoinPointStaticPart;<br />                String name = AJReflect.getParameterName(sp, i);<br />                throw new IllegalArgumentException("null " + name);<br />            }<br />        }<br />    }<br />}</div><img src ="http://www.blogjava.net/zyl/aggbug/81587.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zyl/" target="_blank">布衣郎</a> 2006-11-16 18:56 <a href="http://www.blogjava.net/zyl/archive/2006/11/16/81587.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AspectJ 学习笔记：Aspect的生命周期</title><link>http://www.blogjava.net/zyl/archive/2006/10/21/76573.html</link><dc:creator>布衣郎</dc:creator><author>布衣郎</author><pubDate>Sat, 21 Oct 2006 12:50:00 GMT</pubDate><guid>http://www.blogjava.net/zyl/archive/2006/10/21/76573.html</guid><wfw:comment>http://www.blogjava.net/zyl/comments/76573.html</wfw:comment><comments>http://www.blogjava.net/zyl/archive/2006/10/21/76573.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zyl/comments/commentRss/76573.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zyl/services/trackbacks/76573.html</trackback:ping><description><![CDATA[   

<span style="font-family: 宋体;">默认的情况下，Aspect类只有一个实例存在于虚拟机中，也就是作为单例存在的，对于每个对象来说，方面是共享的。一般这样的方面，不能用来保存相应对象的状态。<br />   对于AspectJ 来说，Aspect方面类，包括以下的实例化方式。<br /></span><ul><li><span style="font-family: 宋体;">每虚拟机(默认），只有一个实例，其生命周期从虚拟机启动开始，一直到虚拟机停止。</span></li><li><span style="font-family: 宋体;">每对象，对于每一个对象都有一个方面实例，其生命周期跟随相关联的对象。</span></li><li><span style="font-family: 宋体;">每控制流，对于每个controlFlow点，都会创建相应的方面实例，可以参考事务管理（对于事务，每个原子操作，都是一个控制流，方面的生命周期，从控制流开始，一直到控制流结束）。</span></li></ul><h4 style="margin-left: 1cm; text-indent: -1cm;"><!--[if !supportLists]--><span style="line-height: 156%; font-family: Courier;" lang="EN-US"><span style="">1)<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">   </span></span></span><!--[endif]--><span style="font-size: 12pt; line-height: 156%; font-family: 宋体;">每虚拟机</span><span style="font-family: 宋体;">关联</span><span style="line-height: 156%; font-family: Courier;" lang="EN-US"><o:p></o:p></span></h4><p class="MsoNormal"><span style="font-family: 宋体;">默认方面，它的状态是共享的。</span></p><h4 style="margin-left: 1cm; text-indent: -1cm;"><!--[if !supportLists]--><span style="font-size: 12pt; line-height: 156%; font-family: 宋体;" lang="EN-US"><span style="">2)<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"></span></span></span><!--[endif]--><span style="font-size: 12pt; line-height: 156%; font-family: 宋体;">每对象</span><span style="font-family: 宋体;">关联</span></h4><span style="font-size: 10.5pt; font-family: 宋体;">通常，重用基础方面需要保持每个对象的状态，也就是对象的数据。对于每个对象都会创建一个方面实例。</span><span style="font-family: 宋体;"><br /><br />对于每对象关联可以指定两种类型：</span><br /><p class="MsoNormal" style="text-indent: 21pt;"><span lang="EN-US">perthis()-与当前所匹配的连接点的执行对象，所关联</span></p><p class="MsoNormal" style="text-indent: 21pt;"><span lang="EN-US">pertarget()</span><span style="font-family: 宋体;">—与当前所匹配的连接点的目标执行对象，所关联</span><span style="font-family: 宋体;"></span></p><h4 style="margin-left: 1cm; text-indent: -1cm;"><!--[if !supportLists]--><span style="font-size: 12pt; line-height: 156%; font-family: 宋体;" lang="EN-US"><span style="">3)<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"></span></span></span><!--[endif]--><span style="font-size: 12pt; line-height: 156%; font-family: 宋体;">每<span lang="EN-US"></span>控制流关联</span></h4><p class="MsoNormal"><span style="font-family: 宋体;">可以指定两种类型的每控制流对象关联：</span></p><p class="MsoNormal"></p><p class="MsoNormal"><span lang="EN-US">percflow()­-</span><span style="font-family: 宋体;">对于在</span><span lang="EN-US">percflow()</span><span style="font-family: 宋体;">指定的</span><span lang="EN-US">pointcut</span><span style="font-family: 宋体;">所匹配的连接点，关联每一个独立的方面实例和控制流执行。</span></p><p class="MsoNormal"><span lang="EN-US">percflowbelow()</span><span style="font-family: 宋体;">，对于在</span><span lang="EN-US">prcflowbelow ()</span><span style="font-family: 宋体;">指定的</span><span lang="EN-US">pointcut</span><span style="font-family: 宋体;">所匹配的连接点，关联每一个独立的方面实例和控制流下的执行。</span></p><p class="MsoNormal"><br /><span style="font-family: 宋体;"></span></p><p class="MsoNormal"><span style="font-family: 宋体;">下面来看一个实例：来区别不同点：</span></p><p class="MsoNormal"><span style="font-family: 宋体;">声明必要的测试类<br /></span></p><table border="0" cellpadding="0" cellspacing="0" height="172" width="741"><tbody><tr valign="top"><td width="10"><br /></td><td width="100%"><br /><table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" height="383" width="676"><tbody><tr><td>public class TestBean {<br /><br />    private String name;<br /><br />    public TestBean(String name) {<br />        this.name = name;<br />    }<br /><br />    public void method1() {<br />    }<br /><br />    public void method2() {<br />    }<br /><br />    @Override<br />    public String toString() {<br />        return name;<br />    }<br /><br />}<br /><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;" lang="EN-US"></span><span style="font-size: 10pt; font-family: &quot;Courier New&quot;;" lang="EN-US"><o:p>测试类：</o:p></span></p><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: &quot;Courier New&quot;;" lang="EN-US"><o:p>public class LogAspectTest {<br /><br />    @Test<br />    public void testAssociation() {<br />        TestBean bean1 = new TestBean("bean1");<br />        TestBean bean2 = new TestBean("bean2");<br />        bean1.method1();<br />        bean1.method2();<br />        bean2.method1();<br />        bean2.method2();<br />    }<br />}</o:p></span></p><p class="MsoNormal" style="text-align: left;" align="left"><br /><span style="font-size: 10pt; font-family: &quot;Courier New&quot;;" lang="EN-US"><o:p></o:p></span></p>方面类：<br />public aspect LogAspect {<br /><br />    private static Log log = LogFactory.getLog(LogAspect.class);<br /><br />    public LogAspect() {<br />        log.info("create LogAspect instance");<br />    }<br /><br />    pointcut logMethod(TestBean bean)<br />        :execution(* TestBean.method*(..))&amp;&amp;this(bean)&amp;&amp;!within(LogAspect+);<br /><br />    before(TestBean bean):logMethod( bean){<br />        log.info("JoinPoint: "<br />                 + thisJoinPointStaticPart<br />                 + "\n\taspect: "<br />                 + this<br />                 + "\n\tobject: "<br />                 + bean);<br /><br />    }<br />}<br /></td></tr></tbody></table></td></tr></tbody></table><br />默认的输出为：<br />2006-10-21 20:42:02,275 [demo.chap4.log.LogAspect] - create LogAspect instance<br />2006-10-21 20:42:02,275 [demo.chap4.log.LogAspect] - JoinPoint: execution(void demo.chap4.log.TestBean.method1())<br />    aspect: demo.chap4.log.LogAspect@15601ea<br />    object: bean1<br />2006-10-21 20:42:02,275 [demo.chap4.log.LogAspect] - JoinPoint: execution(void demo.chap4.log.TestBean.method2())<br />    aspect: demo.chap4.log.LogAspect@15601ea<br />    object: bean1<br />2006-10-21 20:42:02,275 [demo.chap4.log.LogAspect] - JoinPoint: execution(void demo.chap4.log.TestBean.method1())<br />    aspect: demo.chap4.log.LogAspect@15601ea<br />    object: bean2<br />2006-10-21 20:42:02,275 [demo.chap4.log.LogAspect] - JoinPoint: execution(void demo.chap4.log.TestBean.method2())<br />    aspect: demo.chap4.log.LogAspect@15601ea<br />    object: bean2<br /><p class="MsoNormal">可以看到只是实例化了一次</p><br />现在更改相应的aspect，<br /><br />public aspect LogAspect <font color="#ff3300">perthis(logMethod(TestBean))</font>{<br /><br />
    ....<br /><br />
    }<br />
}<br /><p class="MsoNormal"><span style="font-family: 宋体;">只是增加了</span><font color="#ff3300">perthis(logMethod(TestBean))</font></p><p class="MsoNormal">输出时，可以看到创建了两个实例<br /></p><p class="MsoNormal"><font color="#ff3300"><font color="#000000"><font color="#ff0000">2006-10-21 20:45:21,306 [demo.chap4.log.LogAspect] - create LogAspect instance</font><br />2006-10-21 20:45:21,306 [demo.chap4.log.LogAspect] - JoinPoint: execution(void demo.chap4.log.TestBean.method1())<br />    aspect: demo.chap4.log.LogAspect@197d257<br />    object: bean1<br />2006-10-21 20:45:21,306 [demo.chap4.log.LogAspect] - JoinPoint: execution(void demo.chap4.log.TestBean.method2())<br />    aspect: demo.chap4.log.LogAspect@197d257<br />    object: bean1<br /><font color="#ff0000">2006-10-21 20:45:21,306 [demo.chap4.log.LogAspect] - create LogAspect instance</font><br />2006-10-21 20:45:21,306 [demo.chap4.log.LogAspect] - JoinPoint: execution(void demo.chap4.log.TestBean.method1())<br />    aspect: demo.chap4.log.LogAspect@7259da<br />    object: bean2<br />2006-10-21 20:45:21,306 [demo.chap4.log.LogAspect] - JoinPoint: execution(void demo.chap4.log.TestBean.method2())<br />    aspect: demo.chap4.log.LogAspect@7259da<br />    object: bean2</font></font></p><p class="MsoNormal">继续更改aspect，把perthis改为percflow</p><p class="MsoNormal">输出改为：<br /></p><p class="MsoNormal">2006-10-21 20:46:58,009 [demo.chap4.log.LogAspect] - create LogAspect instance<br />2006-10-21 20:46:58,009 [demo.chap4.log.LogAspect] - JoinPoint: execution(void demo.chap4.log.TestBean.method1())<br />    aspect: demo.chap4.log.LogAspect@eee36c<br />    object: bean1<br />2006-10-21 20:46:58,009 [demo.chap4.log.LogAspect] - create LogAspect instance<br />2006-10-21 20:46:58,009 [demo.chap4.log.LogAspect] - JoinPoint: execution(void demo.chap4.log.TestBean.method2())<br />    aspect: demo.chap4.log.LogAspect@194df86<br />    object: bean1<br />2006-10-21 20:46:58,009 [demo.chap4.log.LogAspect] - create LogAspect instance<br />2006-10-21 20:46:58,009 [demo.chap4.log.LogAspect] - JoinPoint: execution(void demo.chap4.log.TestBean.method1())<br />    aspect: demo.chap4.log.LogAspect@defa1a<br />    object: bean2<br />2006-10-21 20:46:58,009 [demo.chap4.log.LogAspect] - create LogAspect instance<br />2006-10-21 20:46:58,009 [demo.chap4.log.LogAspect] - JoinPoint: execution(void demo.chap4.log.TestBean.method2())<br />    aspect: demo.chap4.log.LogAspect@f5da06<br />    object: bean2</p><br />每个方法都创建相应的实例。<br /><br /><br /><img src ="http://www.blogjava.net/zyl/aggbug/76573.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zyl/" target="_blank">布衣郎</a> 2006-10-21 20:50 <a href="http://www.blogjava.net/zyl/archive/2006/10/21/76573.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于AspectJ 中的pointcut 语法</title><link>http://www.blogjava.net/zyl/archive/2006/10/17/75732.html</link><dc:creator>布衣郎</dc:creator><author>布衣郎</author><pubDate>Tue, 17 Oct 2006 12:00:00 GMT</pubDate><guid>http://www.blogjava.net/zyl/archive/2006/10/17/75732.html</guid><wfw:comment>http://www.blogjava.net/zyl/comments/75732.html</wfw:comment><comments>http://www.blogjava.net/zyl/archive/2006/10/17/75732.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/zyl/comments/commentRss/75732.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zyl/services/trackbacks/75732.html</trackback:ping><description><![CDATA[    这两天忙着看AspectJ in Action 为了补一下AOP知识。看了Spring 2.0的规范，其中AOP部分已经基本融合了AspectJ，看来有必要看一看AspectJ了。<br />   看了很多AOP的文章了，AOP这两年发展的很慢，没有什么新意，现在到处都是SOA，SCA了，不过研究了一下，觉得还是很有帮助的。尤其是增加系统的契约性和模块的独立性来说，很有帮助。<br />   当然，学东西，基础很重要。下面就说说AspectJ中的基本语法，有兴趣的可以看看AspectJ in Action。<br />   先来说说pointcut，从字面的意思说的是切面的意思。也就是横切的时候，会有哪些执行点会被识别。只有先识别了，才能执行相应的Advice。<br />   基本的定义如下：<br />   <br />   public <font color="#ff6600">pointcut </font>accountOperations:call(* Account.*(..))<br />   <br />   <b>1.通配符和pointcut 操作符<br /></b><ul><li><b>   </b><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">*  </span><span style="font-size: 10.5pt; font-family: 宋体;">表示任何数量的字符，除了(.)</span></li><li><span style="font-size: 10.5pt; font-family: 宋体;">    </span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">..</span><span style="font-size: 10.5pt; font-family: 宋体;"> 表示任何数量的字符包括任何数量的(.)</span></li><li><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">       + </span><span style="font-size: 10.5pt; font-family: 宋体;">描述指定类型的任何子类或者子接口</span></li></ul><span style="font-size: 10.5pt; font-family: 宋体;">    </span><span style="font-size: 10.5pt; font-family: 宋体;">同</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">java</span><span style="font-size: 10.5pt; font-family: 宋体;">一样，提供了一元和二元的条件表达操作符。<br />    </span><span style="font-size: 10.5pt; font-family: 宋体;">一元操作符：</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">!<br />      </span><span style="font-size: 10.5pt; font-family: 宋体;">二元操作符：</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">||</span><span style="font-size: 10.5pt; font-family: 宋体;">和</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">&amp;&amp;<br />      </span><span style="font-size: 10.5pt; font-family: 宋体;">优先权同</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">java<br /><br />  <b>    2.</b></span><b><span style="font-size: 12pt; font-family: 宋体;">签名语法<br /><br />  </span></b><b style=""><span style="font-size: 10.5pt; font-family: 宋体;">类型签名</span></b><b style=""><span style="font-size: 10.5pt; font-family: 宋体;">样式<br /><br />  </span></b><span style="font-size: 10.5pt; font-family: 宋体;">主要的例子:</span><br /><b><span style="font-size: 12pt; font-family: 宋体;">  </span></b><b style=""><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">Account</span></b><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US"><span style="">                              </span></span><span style="font-size: 10.5pt; font-family: 宋体;">类型</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">Account<br />    </span><b style=""><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">*Account                                      </span></b><span style="font-size: 10.5pt; font-family: 宋体;">使用</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">Account</span><span style="font-size: 10.5pt; font-family: 宋体;">名称结束的类型，如</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">SavingsAccount</span><span style="font-size: 10.5pt; font-family: 宋体;">和</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">CheckingAccount<br />    </span><b style=""><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">java.*.Date                         </span></b><span style="font-size: 10.5pt; font-family: 宋体;">类型</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">Date</span><span style="font-size: 10.5pt; font-family: 宋体;">在任何直接的</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">java</span><span style="font-size: 10.5pt; font-family: 宋体;">子包中，如</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">java.util.Date</span><span style="font-size: 10.5pt; font-family: 宋体;">和</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">java.sql.Date<br />    </span><b style=""><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">java..*                                 </span></b><span style="font-size: 10.5pt; font-family: 宋体;">任何在</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">java</span><span style="font-size: 10.5pt; font-family: 宋体;">包或者所有子包中的类型，如</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">java.awt</span><span style="font-size: 10.5pt; font-family: 宋体;">和</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">java.util</span><span style="font-size: 10.5pt; font-family: 宋体;">或者</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">java.awt.event </span><span style="font-size: 10.5pt; font-family: 宋体;">和</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">java.util.logging<br />    </span><b style=""><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">javax..*Model+                   </span></b><span style="font-size: 10.5pt; font-family: 宋体;">所有</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">javax</span><span style="font-size: 10.5pt; font-family: 宋体;">包或者子包中以</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">Model</span><span style="font-size: 10.5pt; font-family: 宋体;">结尾的类型和其所有子类，如</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">TableModel,TreeModel</span><span style="font-size: 10.5pt; font-family: 宋体;">。<br />  </span><b style=""><span style="font-size: 10.5pt; font-family: 宋体;">！</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">vector <span style="">      </span></span></b><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US"><span style="">                      </span></span><span style="font-size: 10.5pt; font-family: 宋体;">所有除了</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">Vector</span><span style="font-size: 10.5pt; font-family: 宋体;">的类型<br />  </span><b style=""><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">Vector|| Hashtable<span style="">              </span></span></b><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">Vector</span><span style="font-size: 10.5pt; font-family: 宋体;">或者</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">Hashtable</span><span style="font-size: 10.5pt; font-family: 宋体;">类型<br />  </span><b style=""><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">java.util.RandomAccess+<span style="">    </span></span></b><span style="font-size: 10.5pt; font-family: 宋体;">实现</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">RandomAccess</span><span style="font-size: 10.5pt; font-family: 宋体;">和</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">List</span><span style="font-size: 10.5pt; font-family: 宋体;">的所有子类</span><br /><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">   </span><b style=""><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">&amp;&amp; java.util.List+</span></b><br /><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">   <br />   </span><b style=""><span style="font-size: 10.5pt; font-family: 宋体;">方法和构造器签名模式<br /><br />  public void Collection.clear()：<br />  </span></b><span style="font-size: 10.5pt; font-family: 宋体;">在Collection中同样签名的clear方法<br /><br /></span><b style=""><span style="font-size: 10.5pt; font-family: 宋体;">  public void Account.debit(float) throws InsufficientBalanceException：<br />  </span></b><span style="font-size: 10.5pt; font-family: 宋体;">Account中同样签名的debit方法<br /><br /></span><b style=""><span style="font-size: 10.5pt; font-family: 宋体;">  public void Account.set*(*)<br />  </span></b><span style="font-size: 10.5pt; font-family: 宋体;">Account中以set开头，并且只有一个参数类型的方法<br /><br /></span><b style=""><span style="font-size: 10.5pt; font-family: 宋体;">  public void Account.*()<br /> </span></b><span style="font-size: 10.5pt; font-family: 宋体;"> Account中所有的没有参数的public void 方法<br /> <br /></span><b style=""><span style="font-size: 10.5pt; font-family: 宋体;">  public * Account.*()<br /></span></b><span style="font-size: 10.5pt; font-family: 宋体;">  Account中所有没有参数的public 方法<br /><br /></span><b style=""><span style="font-size: 10.5pt; font-family: 宋体;">  public * Account.*(..)<br />  </span></b><span style="font-size: 10.5pt; font-family: 宋体;">Account中所有的public 方法<br /><br /></span><b style=""><span style="font-size: 10.5pt; font-family: 宋体;">  * Account.*(..)<br /> </span></b><span style="font-size: 10.5pt; font-family: 宋体;"> Account中的所有方法，包括private方法<br /><br /></span><b style=""><span style="font-size: 10.5pt; font-family: 宋体;">  !public * Account.*(..)<br /> </span></b><span style="font-size: 10.5pt; font-family: 宋体;"> 所有的非public 方法</span><b style=""><span style="font-size: 10.5pt; font-family: 宋体;"><br /><br />   * Account+.*(..)<br />   </span></b><span style="font-size: 10.5pt; font-family: 宋体;">所有的方法，包括子类的方法<br /><br /></span><b style=""><span style="font-size: 10.5pt; font-family: 宋体;">   * java.io.Reader.read(..)<br />   </span></b><span style="font-size: 10.5pt; font-family: 宋体;">所有的read方法<br /><br /></span><b style=""><span style="font-size: 10.5pt; font-family: 宋体;">   * java.io.Reader.read(char[],..)<br />   </span></b><span style="font-size: 10.5pt; font-family: 宋体;">所有以read(char[])开始的方法，包括read(char[])和read(char[],int,int)<br /><br /></span><b style=""><span style="font-size: 10.5pt; font-family: 宋体;">   * javax..*.add*Listener(EventListener+)<br />   </span></b><span style="font-size: 10.5pt; font-family: 宋体;">命名以add开始，以Listener结尾的方法，参数中为EventListener或子类<br /><br /></span><b style=""><span style="font-size: 10.5pt; font-family: 宋体;">   * *.*(..) throws RemoteException<br />   </span></b><span style="font-size: 10.5pt; font-family: 宋体;">抛出RemoteException的所有方法</span><b style=""><span style="font-size: 10.5pt; font-family: 宋体;"><br /><br />   构造器，同上面<br />   public Account.new()<br />   </span></b><span style="font-size: 10.5pt; font-family: 宋体;">没有参数的构造器方法<br /><br />    <b>属性签名模式</b><br />    同方法一样，属性也查不多<br />   <b> * Account.*  </b>  <br />    所有的Account属性<br /><br />    <b>!public static * banking..*.*</b><br />    所有的非public static 属性，在banking的包或者子包中<br />    <br />    <b>3.主要的pointcuts类型<br />   <br /></b>    <b>分类pointcuts</b><br />    遵循特定的语法用于捕获每一个种类的可使用连接点。<br />    主要的种类：<br /></span><ul><li><span style="font-size: 10.5pt; font-family: 宋体;">方法执行：execution(MethodSignature)</span></li><li><span style="font-size: 10.5pt; font-family: 宋体;">方法调用：call(MethodSignature)</span></li><li><span style="font-size: 10.5pt; font-family: 宋体;">构造器执行：execution(ConstructorSignature)</span></li><li><span style="font-size: 10.5pt; font-family: 宋体;">构造器调用：call(ConstructorSignature)</span></li><li><span style="font-size: 10.5pt; font-family: 宋体;">类初始化：staticinitialization(TypeSignature)</span></li><li><span style="font-size: 10.5pt; font-family: 宋体;">属性读操作：get(FieldSignature)</span></li><li><span style="font-size: 10.5pt; font-family: 宋体;">属性写操作：set(FieldSignature)</span></li><li><span style="font-size: 10.5pt; font-family: 宋体;">例外处理执行：handler(TypeSignature)</span></li><li><span style="font-size: 10.5pt; font-family: 宋体;">对象初始化：initialization(ConstructorSignature)</span></li><li><span style="font-size: 10.5pt; font-family: 宋体;">对象预先初始化：preinitialization(ConstructorSignature)</span></li><li><span style="font-size: 10.5pt; font-family: 宋体;">Advice执行：adviceexecution()</span></li></ul>   <b>基于控制流的pointcuts</b><br />   主要包括两种类型的控制流：<br />   cflow(Pointcut)，捕获所有的连接点在指定的方法执行中，包括执行方法本身。<br />   cflowbelow(Pointcut)，捕获所有的连接点在指定的方法执行中，除了执行方法本身。<br /><br />   如以下的例子：<br />   <b>cflow(call(* Account.debit(..))</b><br />   所有的debit方法中的连接点，包括debit方法本身<br />  <b> cflowbelow(call(* Account.debit(..))</b><br />   所有debit方法中的连接点，除了debit方法本身<br />  <b> cflow(transactedOperations())</b><br />   所有由transactedOperations捕获的连接点<br />   <b>cflowbelow(execution(Account.new(..))</b><br />   所有在Account 构造器中执行的连接点<br /><br />   <b>基于词汇结构的连接点</b><br />   源代码片断。，如within()和withincode()<br />   within ：捕获在指定类或者方面中的程序体中的所有连接点，包括内部类。<br />   Withincode：用于捕获在构造器或者方法中的所有连接点，包括在其中的本地类<br /><br />   <b>执行对象连接点</b><br />   匹配this,和target对象，作为方法被调用的对象。<br />   this(Account)，所有Account的实例的执行点，匹配所有的连接点，如方法调用，属性设置，当前的执行对象为Account，或者其子类。<br />   target(Account)：匹配所有的连接点，目标对象为Account或其子类。<br /><br />   必须执行相应的类型，不能使用*,或者..通配符。当前静态方法，不能被匹配。<br /><br />   在within()和this()中的区别：<br />   一个是程序体，而另一个为对象执行。<br /><br />   <b>参数pointcuts</b><br />   用于捕获参数类型的连接点。<br />   args(String,..,int)<br />   args(RemoteException)<br /><br />   <b>条件检测pointcuts</b><br />   if(System.currentTimeMillis()&gt;triggerTime)<br /><br /><br />   基本的语法就这些，不过AspectJ5 已经增加了不少语法，主要关于Annotation 的，不过这部分还没有仔细研究，以后再讲解吧。希望能有所帮助<br /><br /><span style="font-size: 10.5pt; font-family: 宋体;">   <br /></span><b style=""><span style="font-size: 10.5pt; font-family: 宋体;"><br /></span></b><img src ="http://www.blogjava.net/zyl/aggbug/75732.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zyl/" target="_blank">布衣郎</a> 2006-10-17 20:00 <a href="http://www.blogjava.net/zyl/archive/2006/10/17/75732.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring aop 2.0 编程(三)</title><link>http://www.blogjava.net/zyl/archive/2006/09/17/70116.html</link><dc:creator>布衣郎</dc:creator><author>布衣郎</author><pubDate>Sun, 17 Sep 2006 03:13:00 GMT</pubDate><guid>http://www.blogjava.net/zyl/archive/2006/09/17/70116.html</guid><wfw:comment>http://www.blogjava.net/zyl/comments/70116.html</wfw:comment><comments>http://www.blogjava.net/zyl/archive/2006/09/17/70116.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/zyl/comments/commentRss/70116.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zyl/services/trackbacks/70116.html</trackback:ping><description><![CDATA[
		<p>前面这是讲了许多的概念，下面以一个例子来说明：<br />一个很好理解的aop 例子，也就是日志服务。<br />先从aop第一种方式来实现，也就是xml配置方式<br />先创建基本的日志类：<br />public class Logger {</p>
		<p>    private static Log log = LogFactory.getLog(Logger.class);</p>
		<p>    public void entry(String message) {<br />        log.info(message);<br />    }<br />}<br />这里只是简单的一个方法，当然实际情况可能不同。<br />由于xml配置需要一个方面的实现bean<br />所以创建一个简单的bean ：<br />public class LogBean {</p>
		<p>    private Logger logger = new Logger();</p>
		<p>    public Object aroundLogCalls(ProceedingJoinPoint joinPoint) throws Throwable {<br />        logger.entry("before invoke method:"<br />                     + joinPoint.getSignature().getName());<br />        Object object = joinPoint.proceed();<br />        logger.entry("after invoke method:"<br />                     + joinPoint.getSignature().getName());<br />        return object;<br />    }<br />}<br />这里采取简单的around advice，其他类型的advice 基本上都差不多<br /><br />当然有了这两个核心的日志类，需要一个测试类，用于测试。<br />public class TestBean {</p>
		<p>    public void method1() {<br />        System.out.println("in method1");<br />    }</p>
		<p>    public void method2() {<br />        System.out.println("in method2");<br />    }<br />}<br />这就是需要测试的类了，需要记录日志的方法只有两个，这里用System.out.println，只是想显示方法的调用顺序。<br /><br /><br />然后关键的在于xml的配置了<br /><br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;beans xmlns="<a href="http://www.springframework.org/schema/beans">http://www.springframework.org/schema/beans</a>"<br /> xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>"<br /><font color="#ff0000"> xmlns:aop="</font><a href="http://www.springframework.org/schema/aop"><font color="#ff0000">http://www.springframework.org/schema/aop</font></a><font color="#ff0000">"<br /></font> xsi:schemaLocation="<br /><a href="http://www.springframework.org/schema/beans">http://www.springframework.org/schema/beans</a><a href="http://www.springframework.org/schema/beans/spring-beans.xsd">http://www.springframework.org/schema/beans/spring-beans.xsd</a><br /><a href="http://www.springframework.org/schema/aop"><font color="#ff0000">http://www.springframework.org/schema/aop</font></a><font color="#ff0000"></font><a href="http://www.springframework.org/schema/aop/spring-aop.xsd"><font color="#ff0000">http://www.springframework.org/schema/aop/spring-aop.xsd</font></a><font color="#ff0000">"&gt;</font><br /> <br /> &lt;aop:config&gt;<br />    &lt;!--  <font color="#ff0000">expression 表示要执行的匹配表达式，这里匹配所有的public方法，但是去除logger类的所有方法，防止无限调用</font><font color="#000000">--&gt;<br /></font><br />      &lt;aop:pointcut id="loggableCalls"<br />         <font color="#ff0000"> expression="execution(public * *(..)) and !execution(* org.spring.test.aop.log.Logger.*(..))"/</font>&gt;<br /><br /><br />  &lt;aop:aspect id="logAspect" ref="logBean"&gt;<br />   &lt;aop:around pointcut-ref="loggableCalls" method="aroundLogCalls"/&gt;<br />  &lt;/aop:aspect&gt;<br /> <br /> &lt;/aop:config&gt;<br /> &lt;bean id="logBean" class="org.spring.test.aop.log.LogBean" /&gt;<br /> &lt;bean id="testBean" class="org.spring.test.aop.log.TestBean"/&gt;<br /> <br />&lt;/beans&gt;<br /><br />现在写一个测试类：<br /><br />public class LogXmlTest extends RootTest {</p>
		<p>    @Override<br />    protected String getBeanXml() {<br />        return "org/spring/test/aop/log/bean.xml";<br />    }</p>
		<p>    public void testLog() {<br />        TestBean bean = (TestBean) ctx.getBean("testBean");<br />        bean.method1();<br />        bean.method2();<br />    }</p>
		<p>}<br /><br />public abstract class RootTest extends TestCase {</p>
		<p>    protected ApplicationContext  ctx;</p>
		<p>    protected Log log = LogFactory.getLog(getClass());</p>
		<p>    protected RootTest() {<br />        ctx = new ClassPathXmlApplicationContext(getBeanXml());<br />    }</p>
		<p>    protected abstract String getBeanXml();</p>
		<p>}<br /><br />打印的消息如下：<br />2006-09-17 11:08:28,203 INFO [org.spring.test.aop.log.Logger] - before invoke method:method1<br />in method1<br />2006-09-17 11:08:28,203 INFO [org.spring.test.aop.log.Logger] - after invoke method:method1<br />2006-09-17 11:08:28,218 INFO [org.spring.test.aop.log.Logger] - before invoke method:method2<br />in method2<br />2006-09-17 11:08:28,218 INFO [org.spring.test.aop.log.Logger] - after invoke method:method2<br /><br />第二种实现方式，采用注释方式：<br /><br />Logger 类不变<br />创建一个LogAspect类<br />@Aspect<br />public class LogAspect {</p>
		<p>    private Logger logger = new Logger();</p>
		<p>   <font color="#ff0000"> @Pointcut("execution(public * *(..))")<br /></font>    public void publicMethods() {</p>
		<p>    }</p>
		<p>   <font color="#ff0000"> @Pointcut("execution(* org.spring.test.aop.log.Logger.*(..))")<br /></font>    public void logObjectCalls() {</p>
		<p>    }</p>
		<p> <font color="#ff0000">   @Pointcut("publicMethods()&amp;&amp;!logObjectCalls()")<br /></font>    public void loggableCalls() {</p>
		<p>    }</p>
		<p>
				<font color="#ff0000">    @Around("loggableCalls()")<br /></font>    public Object aroundLogCalls(ProceedingJoinPoint joinPoint) throws Throwable {<br />        logger.entry("before invoke method:"<br />                     + joinPoint.getSignature().getName());<br />        Object object = joinPoint.proceed();<br />        logger.entry("after invoke method:"<br />                     + joinPoint.getSignature().getName());<br />        return object;<br />    }<br />}<br /><br />配置文件就简单多了<br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;beans xmlns="<a href="http://www.springframework.org/schema/beans">http://www.springframework.org/schema/beans</a>"<br /> xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>"<br /> xmlns:aop="<a href="http://www.springframework.org/schema/aop">http://www.springframework.org/schema/aop</a>"<br /> xsi:schemaLocation="<br /><a href="http://www.springframework.org/schema/beans">http://www.springframework.org/schema/beans</a><a href="http://www.springframework.org/schema/beans/spring-beans.xsd">http://www.springframework.org/schema/beans/spring-beans.xsd</a><br /><a href="http://www.springframework.org/schema/aop">http://www.springframework.org/schema/aop</a><a href="http://www.springframework.org/schema/aop/spring-aop.xsd">http://www.springframework.org/schema/aop/spring-aop.xsd</a>"&gt;<br /> <br /> &lt;aop:aspectj-autoproxy/&gt;<br /> <br /> &lt;!-- 或者使用以下定义<br /> <br /> <br /> <br /> &lt;bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" /&gt;<br /> <br /> --&gt;<br /> &lt;bean id="logAspect" class="org.spring.test.aop.log.LogAspect"/&gt;<br /> &lt;bean id="testBean" class="org.spring.test.aop.log.TestBean"/&gt;<br /> <br />&lt;/beans&gt;<br /><br />测试类：<br />跟上面的差不多<br />把xml文件换掉就行<br /><br />打印的方式差不多<br /><br />个人还是比较喜欢第二种实现。</p>
<img src ="http://www.blogjava.net/zyl/aggbug/70116.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zyl/" target="_blank">布衣郎</a> 2006-09-17 11:13 <a href="http://www.blogjava.net/zyl/archive/2006/09/17/70116.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring aop编程(二)</title><link>http://www.blogjava.net/zyl/archive/2006/09/15/69966.html</link><dc:creator>布衣郎</dc:creator><author>布衣郎</author><pubDate>Fri, 15 Sep 2006 11:31:00 GMT</pubDate><guid>http://www.blogjava.net/zyl/archive/2006/09/15/69966.html</guid><wfw:comment>http://www.blogjava.net/zyl/comments/69966.html</wfw:comment><comments>http://www.blogjava.net/zyl/archive/2006/09/15/69966.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zyl/comments/commentRss/69966.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zyl/services/trackbacks/69966.html</trackback:ping><description><![CDATA[
		<p>前面主要介绍了如何通过xml实现aop编程，下面主要介绍如何通过@<span style="font-size: 12pt; font-family: 'Times New Roman';" lang="EN-US">AspectJ来实现。<br />为了使@<span style="font-size: 12pt; font-family: 'Times New Roman';" lang="EN-US">AspectJ 支持生效,<br />需要做以下步骤：<br /><span style="font-family: 宋体;">在</span><span lang="EN-US">xml</span><span style="font-family: 宋体;">中设置</span></span></span></p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="" lang="EN">&lt;aop:aspectj-autoproxy/&gt;<br /><o:p></o:p></span>
		</p>
		<p>或者<br />在xml中加入<br /><span style="" lang="EN">&lt;bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" /&gt;<br /><o:p><br /><a name="_Toc144432325"><span style="font-size: 12pt; line-height: 173%; font-family: 宋体;"><strong>声明</strong></span></a><span style=""><span style="font-size: 12pt; line-height: 173%;" lang="EN-US"><strong> aspect</strong></span></span><span style="font-size: 12pt; line-height: 173%;" lang="EN-US"><o:p></o:p></span></o:p></span></p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">&lt;bean id="myAspect" class="org.xyz.NotVeryUsefulAspect"&gt;</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<span style="">   </span>&lt;!-- configure properties of aspect here as normal --&gt;</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">&lt;/bean&gt;</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">package org.xyz;</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">import org.aspectj.lang.annotation.Aspect;</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: red;" lang="EN-US">@Aspect<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">public class NotVeryUsefulAspect {</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">}<br /><br /></span>
				<a name="_Toc144432326">
						<span style="font-size: 12pt; line-height: 173%; font-family: 宋体;">
								<strong>声明</strong>
						</span>
				</a>
				<span style="">
						<span style="font-size: 12pt; line-height: 173%;" lang="EN-US">
								<strong>pointcut<br /></strong>
						</span>
				</span>
				<span style="font-size: 12pt; line-height: 173%;" lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font color="#ff0000">@Pointcut("execution(* transfer(..))")</font>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">public void transfer() {}<br /></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<br />
				<strong>声明</strong>
				<span style="font-size: 12pt; font-family: 'Times New Roman';" lang="EN-US">
						<strong>advice<br /></strong>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="" lang="EN">
						<strong>Before advice:<o:p></o:p></strong>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">@Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>public void doAccessCheck() {<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">    </span>// ...<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="" lang="EN">
						<strong>After returning advice:<o:p></o:p></strong>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">@AfterReturning("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>public void doAccessCheck() {<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">    </span>// ...<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="font-family: 宋体;">或者</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">@AfterReturning(<br />pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",<br />returning="retVal")<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">public void doAccessCheck(Object retVal) {<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">    </span>// ...<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span>
						<strong>After throwing advice：<o:p></o:p></strong>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">@AfterThrowing("SystemArchitecture.dataAccessOperation()")<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>public void doRecoveryActions() {<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">    </span>// ...<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="font-family: 宋体;">或者</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">@AfterThrowing(<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">    </span>pointcut=" SystemArchitecture.dataAccessOperation()",<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">    </span>throwing="ex")<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>public void doRecoveryActions(DataAccessException ex) {<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">    </span>// ...<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span>
						<strong>After (finally) advice：<o:p></o:p></strong>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">@After("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>public void doReleaseLock() {<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">    </span>// ...<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span>
						<strong>Around advice：<o:p></o:p></strong>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">@Around("com.xyz.myapp.SystemArchitecture.businessService()")<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>public Object doBasicProfiling(</span>
				<span style="color: red; font-family: 'Courier New';" lang="EN">ProceedingJoinPoint</span>
				<span style="color: blue; font-family: 'Courier New';" lang="EN"> pjp) throws Throwable {<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">    </span>// start stopwatch<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">    </span>Object retVal = pjp.proceed();<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">    </span>// stop stopwatch<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">    </span>return retVal;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span>
						<strong>Advice parameters：<o:p></o:p></strong>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">@Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation() &amp;&amp;" + </span>
				<span style="color: red; font-family: 'Courier New';" lang="EN">"args(account,..)"</span>
				<span style="color: blue; font-family: 'Courier New';" lang="EN">)<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">public void validateAccount(Account account) {<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>// ...<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<strong>
						<span style="font-family: 宋体;">声明参数名称：</span>
						<span lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</strong>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">@Before(<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">   </span>value="com.xyz.lib.Pointcuts.anyPublicMethod() &amp;&amp; " + <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">         </span>"@annotation(auditable)",<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>
				</span>
				<span style="color: red; font-family: 'Courier New';" lang="EN">
						<span style=""> </span>argNames="auditable"</span>
				<span style="color: blue; font-family: 'Courier New';" lang="EN">)<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">public void audit(Auditable auditable) {<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>AuditCode code = auditable.value();<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>// ...<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">}<span style="">  </span><o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span>
						<strong>Advice 排序：<o:p></o:p></strong>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="font-family: 宋体;">一般以声明的方法次序为先后</span>
				<span style="font-family: 'Courier New';" lang="EN">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="font-family: 宋体;">不同的</span>
				<span style="font-family: 'Courier New';" lang="EN">Advice</span>
				<span style="font-family: 宋体;">，通过实现</span>
				<span style="font-family: 'Courier New';" lang="EN">Ordered</span>
				<span style="font-family: 宋体;">接口，来排序<br /></span>
				<span style="font-family: 'Courier New';" lang="EN">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<a name="_Toc144432328">
						<span style="font-size: 12pt; line-height: 173%;" lang="EN-US">
								<br />
								<strong>Introductions</strong>
						</span>
				</a>
				<br />
				<span style="font-size: 12pt; line-height: 173%;" lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="font-family: 宋体;">用于引入新的接口</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">@Aspect<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">public class UsageTracking {<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>
				</span>
				<span style="color: red; font-family: 'Courier New';" lang="EN">@DeclareParents(value="com.xzy.myapp.service.*+",<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: red; font-family: 'Courier New';" lang="EN">
						<span style="">                  </span>defaultImpl=DefaultUsageTracked.class)<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>public static UsageTracked mixin;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>@Before("com.xyz.myapp.SystemArchitecture.businessService() &amp;&amp;" +<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">          </span>"this(usageTracked)")<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>public void recordUsage(UsageTracked usageTracked) {<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">    </span>usageTracked.incrementUseCount();<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">
						<span style="">  </span>
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="color: blue; font-family: 'Courier New';" lang="EN">}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"> </p>
<img src ="http://www.blogjava.net/zyl/aggbug/69966.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zyl/" target="_blank">布衣郎</a> 2006-09-15 19:31 <a href="http://www.blogjava.net/zyl/archive/2006/09/15/69966.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring 2.0 aop编程(一)</title><link>http://www.blogjava.net/zyl/archive/2006/09/15/69805.html</link><dc:creator>布衣郎</dc:creator><author>布衣郎</author><pubDate>Fri, 15 Sep 2006 01:41:00 GMT</pubDate><guid>http://www.blogjava.net/zyl/archive/2006/09/15/69805.html</guid><wfw:comment>http://www.blogjava.net/zyl/comments/69805.html</wfw:comment><comments>http://www.blogjava.net/zyl/archive/2006/09/15/69805.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zyl/comments/commentRss/69805.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zyl/services/trackbacks/69805.html</trackback:ping><description><![CDATA[在spring2.0中，aop发生了很大的变化：<br />主要分为两大方面<br />1.支持简单的aop xml配置<br />2.支持@<span style="font-size: 12pt; font-family: 'Times New Roman';" lang="EN-US">AspectJ的注释<br /><br />先来看一看第一种情况：<br />申明一个aspect，在xml中的申明如下：<br /><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;aop:config&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">  </span></span><span style="color: red; font-family: 'Courier New';" lang="EN">&lt;aop:aspect id="myAspect" ref="aBean"&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: red; font-family: 'Courier New';" lang="EN"><span style="">    </span>...<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: red; font-family: 'Courier New';" lang="EN"><span style="">  </span>&lt;/aop:aspect&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;/aop:config&gt;<br /><br /></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;bean id="aBean" class="..."&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">  </span>...<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;/bean&gt;<br /><o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><o:p><br /><font color="#000000" face="Times New Roman">申明<span style="font-size: 12pt; font-family: 'Times New Roman';" lang="EN-US">pointcut<br /></span></font></o:p></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;aop:config&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">  </span></span><span style="color: red; font-family: 'Courier New';" lang="EN">&lt;aop:pointcut id="businessService" <o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: red; font-family: 'Courier New';" lang="EN"><span style="">        </span>expression="execution(* com.xyz.myapp.service.*.*(..))"/&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;/aop:config&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><br />申明<span style="font-size: 12pt; font-family: 'Times New Roman';" lang="EN-US">advice<br /></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><b style=""><span style="" lang="EN">Before advice</span></b><b style=""><span style="font-family: 宋体;">：</span></b><b style=""><span style="" lang="EN"><o:p></o:p></span></b></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;aop:aspect id="beforeExample" ref="aBean"&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span></span><span style="color: red; font-family: 'Courier New';" lang="EN">&lt;aop:before <o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: red; font-family: 'Courier New';" lang="EN"><span style="">      </span>pointcut-ref="dataAccessOperation" <o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: red; font-family: 'Courier New';" lang="EN"><span style="">      </span>method="doAccessCheck"/&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;/aop:aspect&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><b style=""><span style="" lang="EN">After returning advice:<o:p></o:p></span></b></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;aop:aspect id="afterReturningExample" ref="aBean"&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><o:p> </o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span></span><span style="color: red; font-family: 'Courier New';" lang="EN">&lt;aop:after-returning <o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: red; font-family: 'Courier New';" lang="EN"><span style="">      </span>pointcut-ref="dataAccessOperation" <o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: red; font-family: 'Courier New';" lang="EN"><span style="">      </span>method="doAccessCheck"/&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">          </span><o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span>...<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span><o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;/aop:aspect&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 宋体;">或者带有返回参数</span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;aop:aspect id="afterReturningExample" ref="aBean"&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><o:p> </o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span>&lt;aop:after-returning <o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">      </span>pointcut-ref="dataAccessOperation"<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">     </span></span><span style="color: red; font-family: 'Courier New';" lang="EN"><span style=""> </span>returning="retVal" <o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">      </span>method="doAccessCheck"/&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">          </span><o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span>...<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span><o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;/aop:aspect&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><o:p> </o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><b style=""><span style="" lang="EN">After throwing advice</span></b><b style=""><span style="font-family: 宋体;">：</span></b><b style=""><span style="" lang="EN"><o:p></o:p></span></b></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;aop:aspect id="afterThrowingExample" ref="aBean"&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><o:p> </o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span>&lt;aop:after-throwing<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">      </span>pointcut-ref="dataAccessOperation" <o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style=""> </span><span style="">     </span>method="doRecoveryActions"/&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">          </span><o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span>...<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span><o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;/aop:aspect&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">或者带有throwing</span><span style="" lang="EN"><o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;aop:aspect id="afterThrowingExample" ref="aBean"&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><o:p> </o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span>&lt;aop:after-throwing <o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">      </span>pointcut-ref="dataAccessOperation"<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">      </span><font color="#ff0000">throwing="dataAccessEx"</font><o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">      </span>method="doRecoveryActions"/&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">          </span><o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span>...<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span><o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;/aop:aspect&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><b style=""><span style="" lang="EN">After (finally) advice</span></b><b style=""><span style="font-family: 宋体;">：</span></b><b style=""><span style="" lang="EN"><o:p></o:p></span></b></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;aop:aspect id="afterFinallyExample" ref="aBean"&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><o:p> </o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span>&lt;aop:after<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">      </span>pointcut-ref="dataAccessOperation" <o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">      </span>method="doReleaseLock"/&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">          </span><o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span>...<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span><o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;/aop:aspect&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><b style=""><span style="" lang="EN">Around advice</span></b><b style=""><span style="font-family: 宋体;">：</span></b><b style=""><span style="" lang="EN"><o:p></o:p></span></b></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;aop:aspect id="aroundExample" ref="aBean"&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><o:p> </o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span>&lt;aop:around<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">      </span>pointcut-ref="businessService" <o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">      </span>method="doBasicProfiling"/&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">          </span><o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span>...<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span><o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;/aop:aspect&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><b style=""><span style="" lang="EN">Advice parameters</span></b><b style=""><span style="font-family: 宋体;">：</span></b><b style=""><span style="" lang="EN"><o:p></o:p></span></b></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;aop:before<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">  </span>pointcut="Pointcuts.anyPublicMethod() and @annotation(auditable)"<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">  </span>method="audit"<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style=""> </span></span><span style="color: red; font-family: 'Courier New';" lang="EN"><span style=""> </span>arg-names="auditable"</span><span style="color: blue; font-family: 'Courier New';" lang="EN">/&gt;<br /><o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><br />对于引入接口（<a name="_Toc144432334"><span style="font-size: 12pt; font-family: 'Times New Roman';" lang="EN-US">Introductions</span></a>）：<br /></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;aop:aspect id="usageTrackerAspect" ref="usageTracking"&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: red; font-family: 'Courier New';" lang="EN"><span style="">  </span>&lt;aop:declare-parents<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: red; font-family: 'Courier New';" lang="EN"><span style="">      </span>types-matching="com.xzy.myapp.service.*+",<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: red; font-family: 'Courier New';" lang="EN"><span style="">      </span>implement-interface="UsageTracked"<br /><span style=""> </span><span style="">     </span>default-impl=" service.tracking.DefaultUsageTracked"/&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">  </span>&lt;aop:before<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span>pointcut="com.xyz.myapp.SystemArchitecture.businessService()<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">              </span>and this(usageTracked)"<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN"><span style="">    </span>method="recordUsage"/&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="color: blue; font-family: 'Courier New';" lang="EN">&lt;/aop:aspect&gt;<o:p></o:p></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt;"></p></span> <img src ="http://www.blogjava.net/zyl/aggbug/69805.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zyl/" target="_blank">布衣郎</a> 2006-09-15 09:41 <a href="http://www.blogjava.net/zyl/archive/2006/09/15/69805.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用aop创建松散耦合（分析日志程序）</title><link>http://www.blogjava.net/zyl/archive/2006/09/09/68648.html</link><dc:creator>布衣郎</dc:creator><author>布衣郎</author><pubDate>Sat, 09 Sep 2006 00:32:00 GMT</pubDate><guid>http://www.blogjava.net/zyl/archive/2006/09/09/68648.html</guid><wfw:comment>http://www.blogjava.net/zyl/comments/68648.html</wfw:comment><comments>http://www.blogjava.net/zyl/archive/2006/09/09/68648.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zyl/comments/commentRss/68648.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zyl/services/trackbacks/68648.html</trackback:ping><description><![CDATA[        日志，是每个系统都不可缺少的。但是，又不是必要的业务需求。<br />        但用于日志记录的代码和主要用于其它职责的代码缠绕在一起。根据所解决的问题的复杂程度和作用域的不同，所引起的混乱可大可小。更改一个应用程序的日志记录策略可能涉及数百次编辑 ― 即使可行，这是个令人头疼的任务。<br />         考虑一下以下代码：<br /><a name="code1"><b>清单 1. 日志调用手工插入到每个方法中</b></a>        
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">public void doGet(JspImplicitObjects theObjects) throws ServletException
{
  logger.entry("doGet(...)");

  JspTestController controller = new JspTestController();
  controller.handleRequest(theObjects);

  logger.exit("doGet");
}
</font></code></pre></td></tr></tbody></table>        可能在不同的方法中都存在这样的代码。这就造成代码的无限扩张，同时修改也变得非常困难。<br />       使用aop后，更改的代码为：<br /><a name="code2"><b>清单 2. 自动应用于每个方法的记录日志调用</b></a><br /><table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">public aspect AutoLog{
  
  pointcut publicMethods() : execution(public * org.apache.cactus..*(..));

  pointcut logObjectCalls() :
    execution(* Logger.*(..));
    
  pointcut loggableCalls() : publicMethods() &amp;&amp; ! logObjectCalls();
    
  before() : loggableCalls(){
    Logger.entry(thisJoinPoint.getSignature().toString());
  }
    
  after() : loggableCalls(){
    Logger.exit(thisJoinPoint.getSignature().toString());
  }
}

</font></code></pre></td></tr></tbody></table>所有的日志维护都集中于AutoLog方面。<br /><br /><p><a name="N1009B"><span class="smalltitle"><strong>Pointcut 和 join point</strong></span></a></p><p>要理解 Pointcut，必需知道 <i>join point</i> 是什么。join point 表示在程序执行中明确定义的点。AspectJ 中典型的 join point 包括方法调用、对类成员的访问以及异常处理程序块的执行。join point 可以包含其它 join point。例如，一个方法调用可能在它返回之前引起其它方法调用。那么，Pointcut 就是一种语言构造，这种构造根据已定义的标准挑选一组 join point。示例中的第一个 Pointcut 称为 <code><font face="Courier" size="2">publicMethods</font></code> ，选择 <code><font face="Courier" size="2">org.apache.cactus</font></code> 包中的所有公用（public）方法的执行。 <code><font face="Courier" size="2">execution</font></code> 是一个原始的 Pointcut（就象 <code><font face="Courier" size="2">int</font></code> 是一种原始的 Java 类型）。它选择与其括号中定义的方法说明匹配的任何方法的执行。方法说明允许包含通配符；示例中的一个方法说明包含了几个通配符。第二个名为 <code><font face="Courier" size="2">logObjectCalls</font></code> 的 Pointcut 选择了 <code><font face="Courier" size="2">Logger</font></code> 类中的所有方法的执行。第三个 Pointcut <code><font face="Courier" size="2">loggableCalls</font></code> ，通过使用 <code><font face="Courier" size="2">&amp;&amp; !</font></code> 合并了前两个 Pointcut，这意味着它选择了除 <code><font face="Courier" size="2">Logger</font></code> 类中的公用方法以外， <code><font face="Courier" size="2">org.apache.cactus</font></code> 中所有的公用方法。（记录 log 方法将导致无限递归。） <br /></p><p><a name="N100CF"><span class="smalltitle"><strong>Advice</strong></span></a></p><p>既然 Aspect 已经定义了它应该记录的点，它使用 Advice 来完成实际的日志记录。Advice 是在 join point 之前、之后或周围执行的代码。相对于 Pointcut 来定义 Advice，说类似于“在想要记录的每个方法调用之后运行这些代码”这样的话。因此 Advice 如下：</p><p></p><table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">before() : loggableCalls(){
    Logger.entry(thisJoinPoint.getSignature().toString());
}
</font></code></pre></td></tr></tbody></table><br /><p>Advice 使用 <code><font face="Courier" size="2">Logger</font></code> 类，其入口和出口方法类似于下列代码： </p><p></p><table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">public static void entry(String message){
   System.out.println("entering method " + message);
}
</font></code></pre></td></tr></tbody></table><br /><p>在示例中，传递到记录器的 <code><font face="Courier" size="2">String</font></code> 是从 <code><font face="Courier" size="2">thisJoinPoint</font></code> 派生的，这是一个特殊的反射对象，它允许访问 join point 执行所处的运行时上下文。在 Cactus 实际使用的 Aspect 中，Advice 使用这种对象来检索传递到每个记录的方法调用中的方法参数。当日志记录 Aspect 应用于代码时，方法调用的结果如下： </p><p><br /><a name="code3"><b>清单 3. AutoLog Aspect 的输出</b></a><br /></p><table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">entering method: void test.Logging.main(String[])
entering method: void test.Logging.foo()
exiting method: void test.Logging.foo()
exiting method: void test.Logging.main(String[])
</font></code></pre></td></tr></tbody></table><br /><img src ="http://www.blogjava.net/zyl/aggbug/68648.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zyl/" target="_blank">布衣郎</a> 2006-09-09 08:32 <a href="http://www.blogjava.net/zyl/archive/2006/09/09/68648.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>理解AOP</title><link>http://www.blogjava.net/zyl/archive/2006/09/06/68113.html</link><dc:creator>布衣郎</dc:creator><author>布衣郎</author><pubDate>Wed, 06 Sep 2006 12:05:00 GMT</pubDate><guid>http://www.blogjava.net/zyl/archive/2006/09/06/68113.html</guid><wfw:comment>http://www.blogjava.net/zyl/comments/68113.html</wfw:comment><comments>http://www.blogjava.net/zyl/archive/2006/09/06/68113.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zyl/comments/commentRss/68113.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zyl/services/trackbacks/68113.html</trackback:ping><description><![CDATA[         AOP这个概念提出来很久了，可对它总是一知半解。这几天好好补了一下其中的知识，终于有所突破。<br />         简单的来说,AOP就是面向方面（aspect)编程。具体的概念是这样的：<br />         面向 Aspect 的编程（AOP）是一种新的编程技术，它允许程序员对 <i>横切关系（crosscutting concerns）</i>（跨越典型职责界限的行为，例如日志记录）进行模块化。AOP 引进了 <i>Aspect，</i>它将影响多个类的行为封装到一个可重用模块中。<br />         那<a name="IDA0ESCC"><span class="atitle"><strong><font size="4">什么是横切？</font></strong></span></a><i> <br />        横切</i> 是面向方面编程的专有名词。它指的是在一个给定的编程模型中穿越既定的职责部分（比如日志记录和性能优化）的操作。在横切的世界里，横切有两种类型：动态横切和静态横切。<br />        <a name="IDABFSCC"><span class="smalltitle"><strong>动态横切</strong></span></a><i><br />       动态横切</i> 是通过 <i>切入点</i> 和 <i>连接点</i> 在一个 <i>方面</i> 中创建行为的过程，连接点可以在执行时横向地应用于现有对象。动态横切通常用于帮助向对象层次中的各种方法添加日志记录或身份认证。下面让我们花点时间了解一下动态横切中的一些实际概念： 
<ul><li><b>方面（aspect）</b>类似于 Java 编程语言中的类。方面定义切入点和通知（advice），并由诸如 AspectJ 这样的方面编译器来编译，以便将横切（包括动态的和静态的）织入（interweave）现有的对象中。 <br /><br /></li><li>一个 <b>连接点（join point）</b> 是程序执行中一个精确执行点，比如类中的一个方法。例如，对象 <code><font face="Courier" size="2">Foo </font></code>中的方法 <code><font face="Courier" size="2">bar()</font></code> 就可以是一个连接点。 <i>连接点</i>是个抽象的概念；不用主动定义一个连接点。 <br /><br /></li><li>一个 <b>切入点（pointcut）</b> 本质上一个用于捕捉连接点的结构。例如，可以定义一个切入点来捕捉对对象 <code><font face="Courier" size="2">Foo </font></code>中的方法 <code><font face="Courier" size="2">bar()</font></code> 的所有调用。和连接点相反，切入点需要在方面中定义。 <br /><br /></li><li><b>通知（advice）</b> 是切入点的可执行代码。一个经常定义的通知是添加日志记录功能，其中切入点捕捉对对象 <code><font face="Courier" size="2">Foo </font></code>中的 <code><font face="Courier" size="2">bar()</font></code> 的每个调用，然后该通知动态地插入一些日志记录功能，比如捕捉 <code><font face="Courier" size="2">bar()</font></code> 的参数。 </li></ul><p>       这些概念是动态横切的核心，虽然正如我们即将看到的，它们并不全都是静态横切所必需的。<br /><br />       <a name="IDAZCSCC"><span class="smalltitle"><strong>静态横切</strong></span></a></p><p><i>     静态横切</i> 和动态横切的区别在于它不修改一个给定对象的执行行为。相反，它允许通过引入附加的方法字段和属性来修改对象的 <i>结构</i>。此外，静态横切可以把扩展和实现附加到对象的基本结构中。 <br />    虽然现在还无法谈及静态横切的普遍使用——它看起来是 AOP 的一个相对未被探索（尽管非常具有吸引力）的特性——然而这一技术蕴含的潜力是巨大的。使用静态横切，架构师和设计者能用一种真正面向对象的方法有效地建立复杂系统的模型。静态横切允许您不用创建很深的层次结构，以一种本质上更优雅、更逼真于现实结构的方式，插入跨越整个系统的公共行为。</p><p>       </p><img src ="http://www.blogjava.net/zyl/aggbug/68113.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zyl/" target="_blank">布衣郎</a> 2006-09-06 20:05 <a href="http://www.blogjava.net/zyl/archive/2006/09/06/68113.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>