??xml version="1.0" encoding="utf-8" standalone="yes"?>中文一区一区三区免费 ,中文字幕日韩专区,久久一二三四http://www.aygfsteel.com/zyl/category/17748.html好好学习Q天天向?/description>zh-cnTue, 27 Feb 2007 19:46:51 GMTTue, 27 Feb 2007 19:46:51 GMT60用AOP实现观察者模?/title><link>http://www.aygfsteel.com/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.aygfsteel.com/zyl/archive/2006/11/17/81790.html</guid><wfw:comment>http://www.aygfsteel.com/zyl/comments/81790.html</wfw:comment><comments>http://www.aygfsteel.com/zyl/archive/2006/11/17/81790.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/zyl/comments/commentRss/81790.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/zyl/services/trackbacks/81790.html</trackback:ping><description><![CDATA[ <div style="line-height: 30px;"> <b> 观察?Observer)模式</b> <br />    用途:定义对象之间的一对多依赖关系Q因此,当一个对象的状态发生改变时Q其所有依赖项都会得到通知Qƈ自动更新?br />    它是 OO 设计模式的皇后。该模式被h们广泛应用(特别是在 GUI 应用E序中)Qƈ构成?MVC 架构的关键部分。它处理复杂的问题,而在解决q类问题斚w表现得相对较好。但是,从实现需要的努力和代码理解的角度来说Q它q是带来了一些难以解决的N?br />    不Q观察?Observer)模式要求您先侵入pȝ中现有的c,然后才能支持该模?—?臛_?Java 语言中是q样?br />    而方面可以降低像观察?Observer)模式q种侵入性模式的负担Q得模式参与者更灉|Q因Z需要包含模式代码。而且Q模式本w可以变成抽象的基本斚wQ允许开发h员通过导入和应用它来实现重用,不必每次都要重新考虑模式?br />    下面通过一个例子来说明Q?br />    假设如下的情况:<br />    AccountManager 对象能够观察 AccountQ这P在帐L态改变时Q它们可以向销售h员发送一电子邮件?br />    代码如下Q? <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 />虽然实现的差异很明显Q但在它们之间还是有一些相g处。不论如何实现观察者,代码中都必须回答以下 4 个问题:<br />   1. 哪个对象是主体,哪个对象是观察者?<br />   2. 什么时候主体应当向它的观察者发送通知Q?br />   3. 当接收到通知Ӟ观察者应该做什么?<br />   4. 观察关系应当在什么时候开始,什么时候终止?<br /><br /><b>角色定义</b><br />    首先从标记器接口来分配角色开始。Observer 接口只定义了一个方法:update()Q它对应着 Subject 发送通知时执行的操作?Subject 承担着更多的职责。它的标记器接口定义了两个方法,一个用来跟t观察者,另一个用来通知事g的那些观察者? <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 />一旦定义了q些角色Q就可以把它们应用到pȝ中对应的角色上?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 />一旦这工作完成,可以{UdSubject。在q里Q要?Accountq行修改Q? <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>触发事g</b><br />    现在已经把类调整到它们在模式中的角色上了。但是,q需要回q头来,在对应的事g发生时触发通知?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>定义抽象cL实现观察?/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<Sub, Obv> {<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 />       //用于保存所有的M和观察者之间的对象关系<br />    private final HashMap<Sub, ArrayList<Obv>> fObservers = new HashMap<Sub, ArrayList<Obv>>();<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<Obv> getObservers(Sub subject) {<br />        iaxIfNull(subject, "subject");<br />        ArrayList<Observer> result = fObservers.get(subject);<br />        if (null == result) {<br />            result = new ArrayList<Observer>();<br />            fObservers.put(subject, result);<br />        }<br />        return result;<br />    }<br />    //M状态改变,更新所有的观察者对?br />    protected void subjectChanged(Sub subject) {<br />        iaxIfNull(subject, "subject");<br />        ArrayList<Observer> 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<Observer> observers) {<br />        iaxIfNull(subject, "subject");<br />        iaxIfNull(observers, "observers");<br />        for (Observer observer : observers) {<br />            updateObserver(subject, observer);<br />        }<br />    }<br />     //需要子cd玎ͼ具体的更新操?br />    protected abstract void updateObserver(Subject subject, Observer observer);<br /><br />}</div><br /><br /><b>定义斚wQ?/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<Sub, Obv> extends<br />        AbstractSubjectObserver<Sub, Obv> {<br /><br />    //需要横切的代码Q表C哪些需要触发观察者模?br />    protected abstract pointcut changing();<br /><br />    //在状态改变后Q触发所有的观察?br />    after(Sub subject) returning : target(subject) && changing() {<br />        subjectChanged(subject);<br />    }<br />}<br /></div><br />无需改动原有的实玎ͼ看一下客L如何启动观察关系<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<Account, AccountManager> {<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 />   易于理解Q从参与者的视角来看QAOP 版本的观察者更?br />   重用:可以很容易的实现重用<br /><br /><br /><br /></div> <img src ="http://www.aygfsteel.com/zyl/aggbug/81790.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/zyl/" target="_blank">布衣?/a> 2006-11-17 16:55 <a href="http://www.aygfsteel.com/zyl/archive/2006/11/17/81790.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>几个有用的静态方面,用于审查代码QaspectJ实现Q?/title><link>http://www.aygfsteel.com/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.aygfsteel.com/zyl/archive/2006/11/16/81587.html</guid><wfw:comment>http://www.aygfsteel.com/zyl/comments/81587.html</wfw:comment><comments>http://www.aygfsteel.com/zyl/archive/2006/11/16/81587.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/zyl/comments/commentRss/81587.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/zyl/services/trackbacks/81587.html</trackback:ping><description><![CDATA[攉了几个常用的斚wQ?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 />           && 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() && referToTestPackage() <br />        && fromWithinNonTest(): "production code referring to test code";    <br />} </div><br />UtilityClassEnforced     止构造实用工L<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 />        //执行工具cȝMҎ<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 withinTypesQ?br />    //dSystem.out对象<br />    declare error: withinTypes() && get(PrintStream System.out) : "no System.out";<br />     //dSystem.err对象<br />    declare error: withinTypes() && get(PrintStream System.err) : "no System.err";<br />    //dFileDescriptor.err<br />    declare error: withinTypes() && get(PrintStream FileDescriptor.err) : "no FileDescriptor.err";<br />    //dFileDescriptor.out<br />    declare error: withinTypes() && get(PrintStream FileDescriptor.out) : "no FileDescriptor.out";<br />     //执行Throwable.printStackTrace()Ҏ<br />    declare error: withinTypes() && call(void Throwable.printStackTrace()) : "no System.err";<br />}</div><br />GetterSetter     止在除初始化或 getter Ҏ以外q行字段d操作Q禁止在初始化或 setter Ҏ以外q行字段写操?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() && gets() && <br />        //在get*Ҏ或者构造器以外地方使用<br />        !(withincode(!void get*()) || withincode(new(..)))<br />        : "non-public field-get outside constructor or getter method";<br />    declare error : withinTypes() && sets() && <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的参?如原cdQint,long<br />        && !(execution(* *(!Object+)) || execution(*.new(!Object+)));<br />    //如果参数为null,则抛Z外 ?         <br />    before() : withinTypes() && publicParameters() {<br />        Object[] args = thisJoinPoint.getArgs();<br />        for (int i = 0; i < 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.aygfsteel.com/zyl/aggbug/81587.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/zyl/" target="_blank">布衣?/a> 2006-11-16 18:56 <a href="http://www.aygfsteel.com/zyl/archive/2006/11/16/81587.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AspectJ 学习W记QAspect的生命周?/title><link>http://www.aygfsteel.com/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.aygfsteel.com/zyl/archive/2006/10/21/76573.html</guid><wfw:comment>http://www.aygfsteel.com/zyl/comments/76573.html</wfw:comment><comments>http://www.aygfsteel.com/zyl/archive/2006/10/21/76573.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/zyl/comments/commentRss/76573.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/zyl/services/trackbacks/76573.html</trackback:ping><description><![CDATA[   <span style="font-family: 宋体;">默认的情况下QAspectcd有一个实例存在于虚拟ZQ也是作ؓ单例存在的,对于每个对象来说Q方面是׃n的。一般这L斚wQ不能用来保存相应对象的状态?br />   对于AspectJ 来说QAspect斚wc,包括以下的实例化方式?br /></span><ul><li><span style="font-family: 宋体;">每虚拟机(默认Q,只有一个实例,其生命周期从虚拟机启动开始,一直到虚拟机停止?/span></li><li><span style="font-family: 宋体;">每对象,对于每一个对象都有一个方面实例,其生命周期跟随相兌的对象?/span></li><li><span style="font-family: 宋体;">每控制流Q对于每个controlFlow点,都会创徏相应的方面实例,可以参考事务管理(对于事务Q每个原子操作,都是一个控制流Q方面的生命周期Q从控制开始,一直到控制结束)?/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: "Times New Roman"; 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: 宋体;">默认斚wQ它的状态是׃n的?/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: "Times New Roman"; 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: 宋体;">通常Q重用基斚w需要保持每个对象的状态,也就是对象的数据。对于每个对象都会创Z个方面实例?/span><span style="font-family: 宋体;"><br /><br />对于每对象关联可以指定两U类型:</span><br /><p class="MsoNormal" style="text-indent: 21pt;"><span lang="EN-US">perthis()-与当前所匚w的连接点的执行对象,所兌</span></p><p class="MsoNormal" style="text-indent: 21pt;"><span lang="EN-US">pertarget()</span><span style="font-family: 宋体;">—与当前所匚w的连接点的目标执行对象,所兌</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: "Times New Roman"; 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: 宋体;">可以指定两种cd的每控制对象关联:</span></p><p class="MsoNormal"></p><p class="MsoNormal"><span lang="EN-US">percflow()B-</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: 宋体;">所匚w的连接点Q关联每一个独立的斚w实例和控制流执行?/span></p><p class="MsoNormal"><span lang="EN-US">percflowbelow()</span><span style="font-family: 宋体;">Q对于在</span><span lang="EN-US">prcflowbelow ()</span><span style="font-family: 宋体;">指定?/span><span lang="EN-US">pointcut</span><span style="font-family: 宋体;">所匚w的连接点Q关联每一个独立的斚w实例和控制流下的执行?/span></p><p class="MsoNormal"><br /><span style="font-family: 宋体;"></span></p><p class="MsoNormal"><span style="font-family: 宋体;">下面来看一个实例:来区别不同点Q?/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: "Courier New"; color: black;" lang="EN-US"></span><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-US"><o:p>试c:</o:p></span></p><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: "Courier New";" 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: "Courier New";" lang="EN-US"><o:p></o:p></span></p>斚wc:<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*(..))&&this(bean)&&!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 />默认的输ZؓQ?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 />现在更改相应的aspectQ?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">l箋更改aspectQ把perthis改ؓpercflow</p><p class="MsoNormal">输出改ؓQ?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.aygfsteel.com/zyl/aggbug/76573.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/zyl/" target="_blank">布衣?/a> 2006-10-21 20:50 <a href="http://www.aygfsteel.com/zyl/archive/2006/10/21/76573.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于AspectJ 中的pointcut 语法http://www.aygfsteel.com/zyl/archive/2006/10/17/75732.html布衣?/dc:creator>布衣?/author>Tue, 17 Oct 2006 12:00:00 GMThttp://www.aygfsteel.com/zyl/archive/2006/10/17/75732.htmlhttp://www.aygfsteel.com/zyl/comments/75732.htmlhttp://www.aygfsteel.com/zyl/archive/2006/10/17/75732.html#Feedback1http://www.aygfsteel.com/zyl/comments/commentRss/75732.htmlhttp://www.aygfsteel.com/zyl/services/trackbacks/75732.html   看了很多AOP的文章了QAOPq两q发展的很慢Q没有什么新意,现在到处都是SOAQSCA了,不过研究了一下,觉得q是很有帮助的。尤其是增加pȝ的契U性和模块的独立性来_很有帮助?br />   当然Q学东西Q基很重要。下面就说说AspectJ中的基本语法Q有兴趣的可以看看AspectJ in Action?br />   先来说说pointcutQ从字面的意思说的是切面的意思。也是横切的时候,会有哪些执行点会被识别。只有先识别了,才能执行相应的Advice?br />   基本的定义如下:
  
   public pointcut accountOperations:call(* Account.*(..))
  
   1.通配W和pointcut 操作W?br />
  •    表示M数量的字W,除了(.)
  •     .. 表示M数量的字W包括Q何数量的(.)
  •        + 描述指定cd的Q何子cL者子接口
    ?/span>java一P提供了一元和二元的条件表达操作符?br />    一元操作符Q?/span>!
     
二元操作W:||?/span>&&
     
优先权同java

      2.
{֐语法

 
cd{֐样式

 
主要的例?
  Account                              cdAccount
   
*Account                             使用Account名称l束的类型,?/span>SavingsAccount?/span>CheckingAccount
   
java.*.Date                         cdDate在Q何直接的java子包中,?/span>java.util.Date?/span>java.sql.Date
   
java..*                                 M?/span>java包或者所有子包中的类型,?/span>java.awt?/span>java.util或?/span>java.awt.event ?/span>java.util.logging
   
javax..*Model+                   所?/span>javax包或者子包中?/span>Modell尾的类型和其所有子c,?/span>TableModel,TreeModel?br />  Q?/span>vector                             所有除?/span>Vector的类?br />  Vector|| Hashtable              Vector或?/span>Hashtablecd
 
java.util.RandomAccess+    实现RandomAccess?/span>List的所有子c?/span>
   && java.util.List+
  
  
Ҏ和构造器{֐模式

  public void Collection.clear()Q?br /> 
在Collection中同L名的clearҎ

  public void Account.debit(float) throws InsufficientBalanceExceptionQ?br />  Account中同L名的debitҎ

  public void Account.set*(*)
 
Account中以set开_q且只有一个参数类型的Ҏ

  public void Account.*()
 
Account中所有的没有参数的public void Ҏ
 
  public * Account.*()
  Account中所有没有参数的public Ҏ

  public * Account.*(..)
 
Account中所有的public Ҏ

  * Account.*(..)
 
Account中的所有方法,包括privateҎ

  !public * Account.*(..)
 
所有的非public Ҏ

   * Account+.*(..)
  
所有的ҎQ包括子cȝҎ

   * java.io.Reader.read(..)
  
所有的readҎ

   * java.io.Reader.read(char[],..)
  
所有以read(char[])开始的ҎQ包括read(char[])和read(char[],int,int)

   * javax..*.add*Listener(EventListener+)
  
命名以add开始,以Listenerl尾的方法,参数中ؓEventListener或子c?br />
   * *.*(..) throws RemoteException
  
抛出RemoteException的所有方?/span>

   构造器Q同上面
   public Account.new()
  
没有参数的构造器Ҏ

    属性签名模?/b>
    同方法一P属性也查不?br />    * Account.*   
    所有的Account属?br />
    !public static * banking..*.*
    所有的非public static 属性,在banking的包或者子包中
   
    3.主要的pointcutscd
  
    分类pointcuts
    遵@特定的语法用于捕h一个种cȝ可用连接点?br />    主要的种c:
  • Ҏ执行Qexecution(MethodSignature)
  • Ҏ调用Qcall(MethodSignature)
  • 构造器执行Qexecution(ConstructorSignature)
  • 构造器调用Qcall(ConstructorSignature)
  • cd始化Qstaticinitialization(TypeSignature)
  • 属性读操作Qget(FieldSignature)
  • 属性写操作Qset(FieldSignature)
  • 例外处理执行Qhandler(TypeSignature)
  • 对象初始化:initialization(ConstructorSignature)
  • 对象预先初始化:preinitialization(ConstructorSignature)
  • Advice执行Qadviceexecution()
   Z控制的pointcuts
   主要包括两种cd的控制流Q?br />   cflow(Pointcut)Q捕h有的q接点在指定的方法执行中Q包括执行方法本w?br />   cflowbelow(Pointcut)Q捕h有的q接点在指定的方法执行中Q除了执行方法本w?br />
   如以下的例子Q?br />   cflow(call(* Account.debit(..))
   所有的debitҎ中的q接点,包括debitҎ本n
   cflowbelow(call(* Account.debit(..))
   所有debitҎ中的q接点,除了debitҎ本n
   cflow(transactedOperations())
   所有由transactedOperations捕获的连接点
   cflowbelow(execution(Account.new(..))
   所有在Account 构造器中执行的q接?br />
   Z词汇l构的连接点
   源代码片断。,如within()和withincode()
   within Q捕获在指定cL者方面中的程序体中的所有连接点Q包括内部类?br />   WithincodeQ用于捕获在构造器或者方法中的所有连接点Q包括在其中的本地类

   执行对象q接?/b>
   匚wthis,和target对象Q作为方法被调用的对象?br />   this(Account)Q所有Account的实例的执行点,匚w所有的q接点,如方法调用,属性设|,当前的执行对象ؓAccountQ或者其子类?br />   target(Account)Q匹配所有的q接点,目标对象为Account或其子类?br />
   必须执行相应的类型,不能使用*,或?.通配W。当前静态方法,不能被匹配?br />
   在within()和this()中的区别Q?br />   一个是E序体,而另一个ؓ对象执行?br />
   参数pointcuts
   用于捕获参数cd的连接点?br />   args(String,..,int)
   args(RemoteException)

   条gpointcuts
   if(System.currentTimeMillis()>triggerTime)


   基本的语法就q些Q不qAspectJ5 已经增加了不语法,主要关于Annotation 的,不过q部分还没有仔细研究Q以后再讲解吧。希望能有所帮助

  



]]>
spring aop 2.0 ~程(?http://www.aygfsteel.com/zyl/archive/2006/09/17/70116.html布衣?/dc:creator>布衣?/author>Sun, 17 Sep 2006 03:13:00 GMThttp://www.aygfsteel.com/zyl/archive/2006/09/17/70116.htmlhttp://www.aygfsteel.com/zyl/comments/70116.htmlhttp://www.aygfsteel.com/zyl/archive/2006/09/17/70116.html#Feedback4http://www.aygfsteel.com/zyl/comments/commentRss/70116.htmlhttp://www.aygfsteel.com/zyl/services/trackbacks/70116.html前面q是讲了许多的概念,下面以一个例子来说明Q?br />一个很好理解的aop 例子Q也是日志服务?br />先从aopW一U方式来实现Q也是xml配置方式
先创建基本的日志c:
public class Logger {

    private static Log log = LogFactory.getLog(Logger.class);

    public void entry(String message) {
        log.info(message);
    }
}
q里只是单的一个方法,当然实际情况可能不同?br />׃xml配置需要一个方面的实现bean
所以创Z个简单的bean Q?br />public class LogBean {

    private Logger logger = new Logger();

    public Object aroundLogCalls(ProceedingJoinPoint joinPoint) throws Throwable {
        logger.entry("before invoke method:"
                     + joinPoint.getSignature().getName());
        Object object = joinPoint.proceed();
        logger.entry("after invoke method:"
                     + joinPoint.getSignature().getName());
        return object;
    }
}
q里采取单的around adviceQ其他类型的advice 基本上都差不?br />
当然有了q两个核心的日志c,需要一个测试类Q用于测试?br />public class TestBean {

    public void method1() {
        System.out.println("in method1");
    }

    public void method2() {
        System.out.println("in method2");
    }
}
q就是需要测试的cMQ需要记录日志的Ҏ只有两个Q这里用System.out.printlnQ只是想昄Ҏ的调用顺序?br />

然后关键的在于xml的配|了

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=" xmlns:xsi=" xmlns:aop="http://www.springframework.org/schema/aop"
 xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd">
 
 <aop:config>
    <!--  expression 表示要执行的匚w表达式,q里匚w所有的publicҎQ但是去除loggercȝ所有方法,防止无限调用-->

      <aop:pointcut id="loggableCalls"
          expression="execution(public * *(..)) and !execution(* org.spring.test.aop.log.Logger.*(..))"/>


  <aop:aspect id="logAspect" ref="logBean">
   <aop:around pointcut-ref="loggableCalls" method="aroundLogCalls"/>
  </aop:aspect>
 
 </aop:config>
 <bean id="logBean" class="org.spring.test.aop.log.LogBean" />
 <bean id="testBean" class="org.spring.test.aop.log.TestBean"/>
 
</beans>

现在写一个测试类Q?br />
public class LogXmlTest extends RootTest {

    @Override
    protected String getBeanXml() {
        return "org/spring/test/aop/log/bean.xml";
    }

    public void testLog() {
        TestBean bean = (TestBean) ctx.getBean("testBean");
        bean.method1();
        bean.method2();
    }

}

public abstract class RootTest extends TestCase {

    protected ApplicationContext  ctx;

    protected Log log = LogFactory.getLog(getClass());

    protected RootTest() {
        ctx = new ClassPathXmlApplicationContext(getBeanXml());
    }

    protected abstract String getBeanXml();

}

打印的消息如下:
2006-09-17 11:08:28,203 INFO [org.spring.test.aop.log.Logger] - before invoke method:method1
in method1
2006-09-17 11:08:28,203 INFO [org.spring.test.aop.log.Logger] - after invoke method:method1
2006-09-17 11:08:28,218 INFO [org.spring.test.aop.log.Logger] - before invoke method:method2
in method2
2006-09-17 11:08:28,218 INFO [org.spring.test.aop.log.Logger] - after invoke method:method2

W二U实现方式,采用注释方式Q?br />
Logger cM?br />创徏一个LogAspectc?br />@Aspect
public class LogAspect {

    private Logger logger = new Logger();

    @Pointcut("execution(public * *(..))")
    public void publicMethods() {

    }

    @Pointcut("execution(* org.spring.test.aop.log.Logger.*(..))")
    public void logObjectCalls() {

    }

    @Pointcut("publicMethods()&&!logObjectCalls()")
    public void loggableCalls() {

    }

    @Around("loggableCalls()")
    public Object aroundLogCalls(ProceedingJoinPoint joinPoint) throws Throwable {
        logger.entry("before invoke method:"
                     + joinPoint.getSignature().getName());
        Object object = joinPoint.proceed();
        logger.entry("after invoke method:"
                     + joinPoint.getSignature().getName());
        return object;
    }
}

配置文gq单多?br /><?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=" xmlns:xsi=" xmlns:aop=" xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop 
 <aop:aspectj-autoproxy/>
 
 <!-- 或者用以下定?br /> 
 
 
 <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />
 
 -->
 <bean id="logAspect" class="org.spring.test.aop.log.LogAspect"/>
 <bean id="testBean" class="org.spring.test.aop.log.TestBean"/>
 
</beans>

试c:
跟上面的差不?br />把xml文g换掉p

打印的方式差不多

个hq是比较喜欢W二U实现?/p>

]]>
spring aop~程(?http://www.aygfsteel.com/zyl/archive/2006/09/15/69966.html布衣?/dc:creator>布衣?/author>Fri, 15 Sep 2006 11:31:00 GMThttp://www.aygfsteel.com/zyl/archive/2006/09/15/69966.htmlhttp://www.aygfsteel.com/zyl/comments/69966.htmlhttp://www.aygfsteel.com/zyl/archive/2006/09/15/69966.html#Feedback0http://www.aygfsteel.com/zyl/comments/commentRss/69966.htmlhttp://www.aygfsteel.com/zyl/services/trackbacks/69966.html前面主要介绍了如何通过xml实现aop~程Q下面主要介l如何通过@AspectJ来实现?br />Z使@AspectJ 支持生效,
需要做以下步骤Q?br />?/span>xml中设|?/span>

<aop:aspectj-autoproxy/>

或?br />在xml中加?br /><bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />

声明 aspect

<bean id="myAspect" class="org.xyz.NotVeryUsefulAspect">

   <!-- configure properties of aspect here as normal -->

</bean>

 

package org.xyz;

import org.aspectj.lang.annotation.Aspect;

 

@Aspect

public class NotVeryUsefulAspect {

 

}

声明 pointcut

@Pointcut("execution(* transfer(..))")

public void transfer() {}


声明 advice

Before advice:

@Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")

  public void doAccessCheck() {

    // ...

  }

After returning advice:

@AfterReturning("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")

  public void doAccessCheck() {

    // ...

  }

或?/span>

@AfterReturning(
pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",
returning="retVal")

public void doAccessCheck(Object retVal) {

    // ...

  }

After throwing adviceQ?o:p>

@AfterThrowing("SystemArchitecture.dataAccessOperation()")

  public void doRecoveryActions() {

    // ...

  }

或?/span>

@AfterThrowing(

    pointcut=" SystemArchitecture.dataAccessOperation()",

    throwing="ex")

  public void doRecoveryActions(DataAccessException ex) {

    // ...

  }

After (finally) adviceQ?o:p>

@After("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")

  public void doReleaseLock() {

    // ...

  }

Around adviceQ?o:p>

@Around("com.xyz.myapp.SystemArchitecture.businessService()")

  public Object doBasicProfiling( ProceedingJoinPoint pjp) throws Throwable {

    // start stopwatch

    Object retVal = pjp.proceed();

    // stop stopwatch

    return retVal;

  }

Advice parametersQ?o:p>

@Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation() &&" + "args(account,..)" )

public void validateAccount(Account account) {

  // ...

}

声明参数名称Q?/span>

@Before(

   value="com.xyz.lib.Pointcuts.anyPublicMethod() && " +

         "@annotation(auditable)",

   argNames="auditable" )

public void audit(Auditable auditable) {

  AuditCode code = auditable.value();

  // ...

} 

Advice 排序Q?o:p>

一般以声明的方法次序ؓ先后

不同?/span> Advice Q通过实现 Ordered 接口Q来排序


Introductions

用于引入新的接口

@Aspect

public class UsageTracking {

 

  @DeclareParents(value="com.xzy.myapp.service.*+",

                  defaultImpl=DefaultUsageTracked.class)

  public static UsageTracked mixin;

 

  @Before("com.xyz.myapp.SystemArchitecture.businessService() &&" +

          "this(usageTracked)")

  public void recordUsage(UsageTracked usageTracked) {

    usageTracked.incrementUseCount();

  }

 

}

 



]]>
spring 2.0 aop~程(一)http://www.aygfsteel.com/zyl/archive/2006/09/15/69805.html布衣?/dc:creator>布衣?/author>Fri, 15 Sep 2006 01:41:00 GMThttp://www.aygfsteel.com/zyl/archive/2006/09/15/69805.htmlhttp://www.aygfsteel.com/zyl/comments/69805.htmlhttp://www.aygfsteel.com/zyl/archive/2006/09/15/69805.html#Feedback0http://www.aygfsteel.com/zyl/comments/commentRss/69805.htmlhttp://www.aygfsteel.com/zyl/services/trackbacks/69805.html主要分ؓ两大斚w
1.支持单的aop xml配置
2.支持@AspectJ的注?br />
先来看一看第一U情况:
x一个aspectQ在xml中的x如下Q?br />

<aop:config>

  <aop:aspect id="myAspect" ref="aBean">

    ...

  </aop:aspect>

</aop:config>

<bean id="aBean" class="...">

  ...

</bean>


xpointcut

<aop:config>

  <aop:pointcut id="businessService"

        expression="execution(* com.xyz.myapp.service.*.*(..))"/>

</aop:config>


xadvice

Before adviceQ?/span>

<aop:aspect id="beforeExample" ref="aBean">

    <aop:before

      pointcut-ref="dataAccessOperation"

      method="doAccessCheck"/>

</aop:aspect>

After returning advice:

<aop:aspect id="afterReturningExample" ref="aBean">

 

    <aop:after-returning

      pointcut-ref="dataAccessOperation"

      method="doAccessCheck"/>

         

    ...

   

</aop:aspect>

或者带有返回参?/span>

<aop:aspect id="afterReturningExample" ref="aBean">

 

    <aop:after-returning

      pointcut-ref="dataAccessOperation"

      returning="retVal"

      method="doAccessCheck"/>

         

    ...

   

</aop:aspect>

 

After throwing adviceQ?/span>

<aop:aspect id="afterThrowingExample" ref="aBean">

 

    <aop:after-throwing

      pointcut-ref="dataAccessOperation"

      method="doRecoveryActions"/>

         

    ...

   

</aop:aspect>

或者带有throwing

<aop:aspect id="afterThrowingExample" ref="aBean">

 

    <aop:after-throwing

      pointcut-ref="dataAccessOperation"

      throwing="dataAccessEx"

      method="doRecoveryActions"/>

         

    ...

   

</aop:aspect>

After (finally) adviceQ?/span>

<aop:aspect id="afterFinallyExample" ref="aBean">

 

    <aop:after

      pointcut-ref="dataAccessOperation"

      method="doReleaseLock"/>

         

    ...

   

</aop:aspect>

Around adviceQ?/span>

<aop:aspect id="aroundExample" ref="aBean">

 

    <aop:around

      pointcut-ref="businessService"

      method="doBasicProfiling"/>

         

    ...

   

</aop:aspect>

Advice parametersQ?/span>

<aop:before

  pointcut="Pointcuts.anyPublicMethod() and @annotation(auditable)"

  method="audit"

  arg-names="auditable"/>


对于引入接口Q?a name="_Toc144432334">IntroductionsQ:

<aop:aspect id="usageTrackerAspect" ref="usageTracking">

  <aop:declare-parents

      types-matching="com.xzy.myapp.service.*+",

      implement-interface="UsageTracked"
      default-impl=" service.tracking.DefaultUsageTracked"/>

  <aop:before

    pointcut="com.xyz.myapp.SystemArchitecture.businessService()

              and this(usageTracked)"

    method="recordUsage"/>

</aop:aspect>

 

]]>
使用aop创徏松散耦合Q分析日志程序)http://www.aygfsteel.com/zyl/archive/2006/09/09/68648.html布衣?/dc:creator>布衣?/author>Sat, 09 Sep 2006 00:32:00 GMThttp://www.aygfsteel.com/zyl/archive/2006/09/09/68648.htmlhttp://www.aygfsteel.com/zyl/comments/68648.htmlhttp://www.aygfsteel.com/zyl/archive/2006/09/09/68648.html#Feedback0http://www.aygfsteel.com/zyl/comments/commentRss/68648.htmlhttp://www.aygfsteel.com/zyl/services/trackbacks/68648.html        但用于日志记录的代码和主要用于其它职责的代码~绕在一赗根据所解决的问题的复杂E度和作用域的不同,所引v的؜乱可大可。更改一个应用程序的日志记录{略可能涉及数百ơ编??即可行Q这是个令h头疼的Q务?br />         考虑一下以下代码:
清单 1. 日志调用手工插入到每个方法中        
public void doGet(JspImplicitObjects theObjects) throws ServletException
{
  logger.entry("doGet(...)");

  JspTestController controller = new JspTestController();
  controller.handleRequest(theObjects);

  logger.exit("doGet");
}
        可能在不同的Ҏ中都存在q样的代码。这造成代码的无限扩张,同时修改也变得非常困难?br />       使用aop后,更改的代码ؓQ?br />清单 2. 自动应用于每个方法的记录日志调用
public aspect AutoLog{
  
  pointcut publicMethods() : execution(public * org.apache.cactus..*(..));

  pointcut logObjectCalls() :
    execution(* Logger.*(..));
    
  pointcut loggableCalls() : publicMethods() && ! logObjectCalls();
    
  before() : loggableCalls(){
    Logger.entry(thisJoinPoint.getSignature().toString());
  }
    
  after() : loggableCalls(){
    Logger.exit(thisJoinPoint.getSignature().toString());
  }
}

所有的日志l护都集中于AutoLog斚w?br />

Pointcut ?join point

要理?PointcutQ必需知道 join point 是什么。join point 表示在程序执行中明确定义的点。AspectJ 中典型的 join point 包括Ҏ调用、对cL员的讉K以及异常处理E序块的执行。join point 可以包含其它 join point。例如,一个方法调用可能在它返回之前引起其它方法调用。那么,Pointcut 是一U语a构造,q种构造根据已定义的标准挑选一l?join point。示例中的第一?Pointcut UCؓ publicMethods Q选择 org.apache.cactus 包中的所有公用(publicQ方法的执行?execution 是一个原始的 PointcutQ就?int 是一U原始的 Java cdQ。它选择与其括号中定义的Ҏ说明匚w的Q何方法的执行。方法说明允许包含通配W;CZ中的一个方法说明包含了几个通配W。第二个名ؓ logObjectCalls ?Pointcut 选择?Logger cM的所有方法的执行。第三个 Pointcut loggableCalls Q通过使用 && ! 合ƈ了前两个 PointcutQ这意味着它选择了除 Logger cM的公用方法以外, org.apache.cactus 中所有的公用Ҏ。(记录 log Ҏ导致无限递归。)

Advice

既然 Aspect 已经定义了它应该记录的点Q它使用 Advice 来完成实际的日志记录。Advice 是在 join point 之前、之后或周围执行的代码。相对于 Pointcut 来定?AdviceQ说cM于“在惌记录的每个方法调用之后运行这些代码”这L话。因?Advice 如下Q?/p>

before() : loggableCalls(){
    Logger.entry(thisJoinPoint.getSignature().toString());
}

Advice 使用 Logger c,其入口和出口ҎcM于下列代码:

public static void entry(String message){
   System.out.println("entering method " + message);
}

在示例中Q传递到记录器的 String 是从 thisJoinPoint z的,q是一个特D的反射对象Q它允许讉K join point 执行所处的q行时上下文。在 Cactus 实际使用?Aspect 中,Advice 使用q种对象来检索传递到每个记录的方法调用中的方法参数。当日志记录 Aspect 应用于代码时Q方法调用的l果如下Q?


清单 3. AutoLog Aspect 的输?/b>

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[])



]]>
理解AOPhttp://www.aygfsteel.com/zyl/archive/2006/09/06/68113.html布衣?/dc:creator>布衣?/author>Wed, 06 Sep 2006 12:05:00 GMThttp://www.aygfsteel.com/zyl/archive/2006/09/06/68113.htmlhttp://www.aygfsteel.com/zyl/comments/68113.htmlhttp://www.aygfsteel.com/zyl/archive/2006/09/06/68113.html#Feedback0http://www.aygfsteel.com/zyl/comments/commentRss/68113.htmlhttp://www.aygfsteel.com/zyl/services/trackbacks/68113.html         单的来说,AOP是面向斚wQaspect)~程。具体的概念是这LQ?br />         面向 Aspect 的编E(AOPQ是一U新的编E技术,它允许程序员?横切关系Qcrosscutting concernsQ?/i>Q跨典型职责界限的行ؓQ例如日志记录)q行模块化。AOP 引进?AspectQ?/i>它将影响多个cȝ行ؓ装C个可重用模块中?br />         ?a name="IDA0ESCC">什么是横切Q?/font> 
        横切
是面向方面编E的专有名词。它指的是在一个给定的~程模型中穿既定的职责部分Q比如日志记录和性能优化Q的操作。在横切的世界里Q横切有两种cdQ动态横切和静态横切?br />        动态横?/strong>
       动态横?/i> 是通过 切入?/i> ?q接?/i> 在一?斚w 中创为的q程Q连接点可以在执行时横向地应用于现有对象。动态横切通常用于帮助向对象层ơ中的各U方法添加日志记录或w䆾认证。下面让我们q旉了解一下动态横切中的一些实际概念:
  • 斚wQaspectQ?/b>cM?Java ~程语言中的cR方面定义切入点和通知QadviceQ,q由诸如 AspectJ q样的方面编译器来编译,以便横切(包括动态的和静态的Q织入(interweaveQ现有的对象中?

  • 一?q接点(join pointQ?/b> 是程序执行中一个精执行点Q比如类中的一个方法。例如,对象 Foo 中的Ҏ bar() 可以是一个连接点?q接?/i>是个抽象的概念;不用d定义一个连接点?

  • 一?切入点(pointcutQ?/b> 本质上一个用于捕捉连接点的结构。例如,可以定义一个切入点来捕捉对对象 Foo 中的Ҏ bar() 的所有调用。和q接点相反,切入炚w要在斚w中定义?

  • 通知QadviceQ?/b> 是切入点的可执行代码。一个经常定义的通知是添加日志记录功能,其中切入Ҏ捉对对象 Foo 中的 bar() 的每个调用,然后该通知动态地插入一些日志记录功能,比如捕捉 bar() 的参数?

       q些概念是动态横切的核心Q虽然正如我们即看到的Q它们ƈ不全都是静态横切所必需的?br />
       静态横?/strong>

     静态横?/i> 和动态横切的区别在于它不修改一个给定对象的执行行ؓ。相反,它允讔R过引入附加的方法字D和属性来修改对象?l构。此外,静态横切可以把扩展和实现附加到对象的基本结构中?
    虽然现在q无法谈及静态横切的普遍使用——它看v来是 AOP 的一个相Ҏ被探索(管非常h吸引力)的特性——然而这一技术蕴含的潜力是巨大的。用静态横切,架构师和设计者能用一U真正面向对象的Ҏ有效地徏立复杂系l的模型。静态横切允许您不用创徏很深的层ơ结构,以一U本质上更优雅、更逼真于现实结构的方式Q插入跨整个系l的公共行ؓ?/p>

      



]]>
վ֩ģ壺 | ͤ| Ĵʡ| | ԫ| ֽ| | | | | | С| | ͬ| Ƹ| | | | ȫ| | ˳| | ϳ| | ¡| | | گ| | | | ͬ| | ֺ| | Զ| | | ƽ| ³| ɽ|