<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    常言笑的家

    Spring, Hibernate, Struts, Ajax, RoR

    Spring Aop Step-By-Step 學(xué)習(xí)筆記(上)

    最近由于工作需要,要求掌握關(guān)于 Spring 方面的東西。所以花了兩個(gè)星期的時(shí)間來(lái)學(xué)習(xí) Spring 的基本知識(shí),主要包括 Ioc Aop 兩方面。
    本文為筆者的 Spring Aop 方面的學(xué)習(xí)筆記,主要結(jié)合了 Spring In Action 第三章 Spring-Reference 第五章 為學(xué)習(xí)向?qū)А8鶕?jù)自己的理解和書(shū)中的實(shí)例來(lái)一步一步完成對(duì)于在 Spring Aop 方面的編程。其中基礎(chǔ)部分 Ioc 需要讀者自己參考資料了解,本文將不做描述。
    說(shuō)明:我將盡量縮短程序長(zhǎng)度,在程序部分將減少注釋說(shuō)明,重點(diǎn)要讀者自己根據(jù)上下文和程序結(jié)果理解體會(huì),具體 api 信息請(qǐng)讀者自己參考 Spring-api 文檔和相關(guān)資料。
    一.    準(zhǔn)備工作:
     
    1.  開(kāi)發(fā)環(huán)境:
    l             適合人群:
                      要了解 Spring Ioc ,對(duì) Spring- Aop 可以不了解或者僅僅熟悉 Aop 概念,未參與 Spring Aop 開(kāi)發(fā)實(shí)戰(zhàn)的初學(xué)者。同時(shí)也希望高手對(duì)于本文的不足或理解錯(cuò)誤之處給予指點(diǎn),謝謝。
    l             開(kāi)發(fā)環(huán)境:
    JDK 1.4_2
    l             開(kāi)發(fā)工具:
    Eclipse 3.12 (未采用任何插件,主要是為初學(xué)者熟悉和理解 xml 文檔的配置)
    l             所需組件:
    Spring-Framework-1.2.8
    下載地址:
     
    2.    建立工程:
       首先用 Eclpse 建立一個(gè)普通 java 項(xiàng)目,導(dǎo)入 jar 文件到編譯環(huán)境中,如下:
    a)             Spring.jar Spring 的核心 jar 文件,必須;
    b)             Commons-loggin.jar 日志文件,必須;
    c)             Cglib.jar 動(dòng)態(tài)代理文件,不是必須(本文需要);
    d)             Jak-oro.jar 使用 Perl Awk 正則表達(dá)式進(jìn)行文本解析工具,不是必須(本文需要);
    建立工程如下:

    好了,下來(lái)我們開(kāi)始我們的 Spring-aop 之旅;
     
    二.  Spring -Aop 入門(mén)
     
    AOP 全名 Aspect-oriented programming Spring framework 是很有前途的 AOP 技術(shù)。作為一種非侵略性的,輕型的 AOP framework ,你無(wú)需使用預(yù)編譯器或其他的元標(biāo)簽,便可以在 Java 程序中使用它。這意味著開(kāi)發(fā)團(tuán)隊(duì)里只需一人要對(duì)付 AOP framework ,其他人還是像往常一樣編程。
    關(guān)鍵性概念:
    1)          Advice 是代碼的具體實(shí)現(xiàn),例如一個(gè)實(shí)現(xiàn)日志記錄的代碼。
    2)          Pointcut 是在將 Advice 插入到程序的條件。
    3)           advisor 是把 pointcut advice 的組合在一起裝配器。
     
    圖例:
    你的程序可能如上,現(xiàn)在要在三個(gè)流程上同時(shí)加入日志控制和權(quán)限控制,如下:
     

     你的程序可能如上,現(xiàn)在要在三個(gè)流程上同時(shí)加入日志控制和權(quán)限控制,如下:

     

     

             其中拿日志為例,日志控制和流程之間的穿插點(diǎn)處叫做連接點(diǎn)( Joinpoint ),而 Advice 就是我們?nèi)罩咎幚淼木唧w代碼, Pointcut 就是定義一個(gè)規(guī)則,對(duì)三個(gè)和業(yè)務(wù)有關(guān)的連接點(diǎn)進(jìn)行過(guò)濾和匹配(例如我們對(duì)于業(yè)務(wù) 1 不做日志處理)。 Advisor 就是將符合的規(guī)則的剩下的兩個(gè)連接點(diǎn)和具體的日志記錄代碼組合在一起。
     
    三.  Spring-Aop 前置通知、后置通知、環(huán)繞通知、異常通知實(shí)現(xiàn)
     
    我以 Spring In Action 提供的例子進(jìn)行二次改造,完成我們自己的流程。業(yè)務(wù)流程很簡(jiǎn)單,顧客到商店買(mǎi)東西,店員根據(jù)顧客的需要給于顧客提供服務(wù)。實(shí)現(xiàn)方法前插入,方法后插入,環(huán)繞,異常四種。
     
           代碼:
              建立一個(gè)用戶(hù)類(lèi);
    public   class  Customer  {
         
    private  String name  =   " 悠~游! " ;
         
    public  String getName()  {
              
    return  name;
         }

    }

    三個(gè)產(chǎn)品
    public class Cheese {
       
    public String toString()
             
    return "奶酪!";
       }

    }

    public class Pepper {
         
    public String toString()
              
    return "胡椒粉!";
         }

    }

    public class Squish {
         
    public String toString()
              
    return "果醬!";
         }

    }

              建立一個(gè)接口;
    public   interface  KwikEMart  {
         Squish buySquish(Customer customer) 
    throws  KwikEMartException;
         Pepper buyPepper(Customer customer) 
    throws  KwikEMartException;
         Cheese buyCheese(Customer customer) 
    throws  KwikEMartException;
    }
    實(shí)現(xiàn)這個(gè)接口,我們實(shí)現(xiàn)三個(gè)方法,買(mǎi)奶酪,買(mǎi)胡椒粉,買(mǎi)果醬;
    public   class  ApuKwikEMart  implements  KwikEMart  {
         
    private   boolean  cheeseIsEmpty  =   false ;

         
    private   boolean  pepperIsEmpty  =   false ;

         
    private   boolean  squishIsEmpty  =   false ;

         
    public  Cheese buyCheese(Customer customer)  throws  NoMoreCheeseException {

              
    if  (cheeseIsEmpty)  {
                   
    throw   new  NoMoreCheeseException();
              }


              Cheese s 
    =   new  Cheese();
              System.out.println(
    " --我想買(mǎi): "   +  s);
              
    return  s;

         }


         
    public  Pepper buyPepper(Customer customer)  throws  NoMorePepperException {

              
    if  (pepperIsEmpty)  {
                   
    throw   new  NoMorePepperException();
              }


              Pepper s 
    =   new  Pepper();
              System.out.println(
    " --我想買(mǎi): "   +  s);
              
    return  s;

         }


         
    public  Squish buySquish(Customer customer)  throws  NoMoreSquishException {

              
    if  (squishIsEmpty)  {
                   
    throw   new  NoMoreSquishException();
              }


              Squish s 
    =   new  Squish();
              System.out.println(
    " --我想買(mǎi): "   +  s);
              
    return  s;

         }


         
    public   void  setCheeseIsEmpty( boolean  cheeseIsEmpty)  {
              
    this .cheeseIsEmpty  =  cheeseIsEmpty;
         }


         
    public   void  setPepperIsEmpty( boolean  pepperIsEmpty)  {
              
    this .pepperIsEmpty  =  pepperIsEmpty;
         }


         
    public   void  setSquishIsEmpty( boolean  squishIsEmpty)  {
              
    this .squishIsEmpty  =  squishIsEmpty;
         }


    }

    環(huán)繞通知的實(shí)現(xiàn),必須實(shí)現(xiàn)invoke方法,通過(guò)調(diào)用invoke.proceed()手工調(diào)用對(duì)象方法:
    public   class  OnePerCustomerInterceptor  implements  MethodInterceptor  {
         
         
    private  Set customers = new  HashSet();

         
    public  Object invoke(MethodInvocation invoke)  throws  Throwable  {
              
              Customer customer
    = (Customer)invoke.getArguments()[ 0 ];
              
    if (customers.contains(customer))
                   
    throw   new  KwikEMartException( " One per customer. " );
              }

              
              System.out.println(
    " 店員: " + customer.getName()  +   "  ,Can I help you ? " );
              Object squishee
    = invoke.proceed();  // 手工調(diào)用對(duì)象方法;
              System.out.println( " 店員:OK!  "   +  customer.getName()  +   " .give you!  "  );
              
              customers.add(squishee);

              
    return  squishee;
         }

    }

    前置通知的實(shí)現(xiàn);
    public class WelcomeAdvice implements MethodBeforeAdvice {

         
    public void before(Method method, Object[] args, Object target) throws Throwable {
              
              Customer customer 
    = (Customer) args[0];
              System.out.println(
    "店員::Hello " + customer.getName() + " . How are you doing?");

         }

    }

    public class Customer {
         
    private String name = "悠~游!";
         
    public String getName() {
              
    return name;
         }

    }
    后置通知實(shí)現(xiàn);
    public class ThankYouAdvice implements AfterReturningAdvice {

         
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
              
              Customer customer 
    = (Customer) args[0];
              System.out.println(
    "店員:Thank you " + customer.getName() + " . Come again! " );

         }

    }
    系統(tǒng)異常處理通知實(shí)現(xiàn);
    public   class  KwikEmartExceptionAdvice  implements  ThrowsAdvice  {

         
    public   void  afterThrowing(NoMoreSquishException e)  {
              System.out.println(
    " 系統(tǒng):NoMoreSquisheesException異常截獲了:  "   +  e.getMessage());
         }

         
    public   void  afterThrowing(NoMoreCheeseException e)  {
              System.out.println(
    " 系統(tǒng):NoMoreCheeseException異常截獲了:  "   +  e.getMessage());
         }

         
    public   void  afterThrowing(NoMorePepperException e)  {
              System.out.println(
    " 系統(tǒng):NoMorePepperException異常截獲了:  "   +  e.getMessage());
         }

    }

    自定義的異常接口;
    public class KwikEMartException extends Exception {

         
    private static final long serialVersionUID = -3962577696326432053L;

         String retValue 
    = "KwikEMartException 異常!";

         
    public KwikEMartException(String name) {
              retValue 
    = name;
         }

         
    public KwikEMartException() {

         }

         
    public String getMessage() {
              
    return retValue;
         }


    }
    沒(méi)有更多的奶酪異常;
    public class NoMoreCheeseException extends KwikEMartException {
         
    private static final long serialVersionUID = -3961123496322432053L;

         String retValue 
    = "NoMoreCheeseException 異常!";

         
    public NoMoreCheeseException() {
              
    super();
         }


         
    public NoMoreCheeseException(String name) {
              
    super(name);
         }


         
    public String getMessage() {

              
    return retValue;
         }

    }
    沒(méi)有更多的胡椒粉異常;
    public   class  NoMorePepperException  extends  KwikEMartException  {
         
    private   static   final   long  serialVersionUID  =   - 3961234696322432053L ;

         String retValue 
    =   " NoMorePepperException 異常! " ;

         
    public  NoMorePepperException()  {
              
    super ();
         }


         
    public  NoMorePepperException(String name)  {
              
    super (name);
         }


         
    public  String getMessage()  {

              
    return  retValue;
         }

    }

    沒(méi)有更多的果醬異常;
    public   class  NoMoreSquishException  extends  KwikEMartException  {
         
    private   static   final   long  serialVersionUID  =   - 3121234696322432053L ;

         String retValue 
    =   " NoMoreSquishException 異常! " ;

         
    public  NoMoreSquishException()  {
              
    super ();
         }


         
    public  NoMoreSquishException(String name)  {
              
    super (name);
         }


         
    public  String getMessage()  {

              
    return  retValue;
         }

    }
    運(yùn)行實(shí)例類(lèi);
    public class RunDemo {

                   
    public static void kwikEMart() {

                   ClassPathXmlApplicationContext context 
    = new ClassPathXmlApplicationContext("demo/kwikemart.xml");

                        
    //如果你想通過(guò)類(lèi)來(lái)引用這個(gè)的話(huà),就要用到CGLIB.jar了,同時(shí)在代理工廠(chǎng)里面設(shè)置:
                        
    //<property name="proxyTargetClass" value="true" />
                        KwikEMart akem = (KwikEMart) context.getBean("kwikEMart");
         
                        
    try {
                             akem.buySquish(
    new Customer());
                             akem.buyPepper(
    new Customer());
                             akem.buyCheese(
    new Customer());
                        }
     catch (KwikEMartException e) {
                             
    //異常已經(jīng)被截獲了,不信你看控制臺(tái)!~;
                        }

                   }


                   
    public static void main(String[] args) {
                        kwikEMart();
                   }

    }

    Xml 文件配置:
        
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">


    <beans>
         
    <bean id="kwikEMartTarget" class="demo.ApuKwikEMart">
              
    <!-- 
                   把這里注釋去掉的話(huà),程序調(diào)用的時(shí)候測(cè)試異常通知;
                   <property name="cheeseIsEmpty">
                        <value>true</value>
                   </property>
                   <property name="pepperIsEmpty">
                        <value>true</value>
                   </property>
                   <property name="squishIsEmpty">
                        <value>true</value>
                   </property>
              
    -->
         
    </bean>

         
    <!-- 方法調(diào)用前通知 -->
         
    <bean id="welcomeAdvice" class="demo.advice.WelcomeAdvice" />
         
    <!-- 方法調(diào)用后通知 -->
         
    <bean id="thankYouAdvice" class="demo.advice.ThankYouAdvice" />
         
    <!-- 環(huán)繞調(diào)用通知 -->
         
    <bean id="onePerCustomerInterceptor" class="demo.advice.OnePerCustomerInterceptor" />
         
    <!-- 異常調(diào)用通知 -->
         
    <bean id="kwikEmartExceptionAdvice" class="demo.advice.KwikEmartExceptionAdvice" />
         
         
    <bean id="kwikEMart" class="org.springframework.aop.framework.ProxyFactoryBean">
              
    <property name="proxyInterfaces" value="demo.KwikEMart" />
              
    <property name="interceptorNames">
                   
    <list>
                        
                             
    <value>welcomeAdvice</value>
                             
    <value>thankYouAdvice</value>
                             
    <value>onePerCustomerInterceptor</value>
                             
    <value>kwikEmartExceptionAdvice</value>
                        
                   
    </list>
              
    </property>
              
    <property name="target">
                   
    <ref bean="kwikEMartTarget" />
              
    </property>
         
    </bean>

    </beans>

    這個(gè)例子?xùn)|西很多,不過(guò)每個(gè)類(lèi)的代碼都不大。如果你對(duì) org.springframework.aop.framework.ProxyFactoryBean 不是很了解的話(huà)可以看我下篇尾處的介紹。 讀清楚之后,我們運(yùn)行RunDemo 類(lèi),查看控制臺(tái)結(jié)果,如下:
     
    店員::Hello 悠~游! . How are you doing?
    店員:悠~游! ,Can I help you ?
    -- 我想買(mǎi):果醬!
    店員:OK! 悠~游!.give you!
    店員:Thank you 悠~游! . Come again!
    店員::Hello 悠~游! . How are you doing?
    店員:悠~游! ,Can I help you ?
    -- 我想買(mǎi):胡椒粉!
    店員:OK! 悠~游!.give you!
    店員:Thank you 悠~游! . Come again!
    店員::Hello 悠~游! . How are you doing?
    店員:悠~游! ,Can I help you ?
    -- 我想買(mǎi):奶酪!
    店員:OK! 悠~游!.give you!
    店員:Thank you 悠~游! . Come again!
     
        我們將 kwikEMartTarget 里面的注釋去掉,測(cè)試異常實(shí)現(xiàn),如下:
        
    店員::Hello 悠~游! . How are you doing?
    店員:悠~游! ,Can I help you ?
    系統(tǒng):NoMoreSquisheesException異常截獲了: NoMoreSquishException 異常!
         好好理解一下,我就不廢話(huà)了,我們進(jìn)行下一節(jié)。
     
     
     
    四. Spring-Aop Pointcut+advice+Advisor 實(shí)現(xiàn)
     
    我們修改我們的xml文檔后如下:
     
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>

         
    <bean id="kwikEMartTarget" class="demo.ApuKwikEMart"></bean>

         
    <!-- 環(huán)繞調(diào)用通知 -->
         
    <bean id="onePerCustomerInterceptor" class="demo.advice.OnePerCustomerInterceptor" />

         
    <!-- 使用NameMatchMethodPointcut -->
         
    <bean id="nameMatchfilterPointcut" class="org.springframework.aop.support.NameMatchMethodPointcut">
              
    <property name="mappedName">
                   
    <!-- 
                        buy.* 以buy開(kāi)頭的方法;
                   
    -->
                   
    <value>buy*</value>
              
    </property>
         
    </bean>

         
    <!-- 使用Perl5RegexpMethodPointcut -->
         
    <bean id="regexpFilterPointcut" class="org.springframework.aop.support.Perl5RegexpMethodPointcut">
              
    <property name="pattern">
                   
    <!-- 
                        .*buy.+ 以buy開(kāi)頭的方法;
                        .*buyS.+ 以buyS開(kāi)頭的方法;
                   
    -->
                   
    <value>.*suy.+</value>
              
    </property>
         
    </bean>

         
    <bean id="runDemofilterPointcutAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
              
    <property name="pointcut">
                   
    <ref bean="nameMatchfilterPointcut" />
              
    </property>
              
    <property name="advice">
                   
    <ref bean="onePerCustomerInterceptor" />
              
    </property>
         
    </bean>
         
    <bean id="kwikEMart" class="org.springframework.aop.framework.ProxyFactoryBean">
              
    <property name="proxyInterfaces" value="demo.KwikEMart" />
              
    <property name="interceptorNames">
                   
    <list>
                        
    <value>runDemofilterPointcutAdvisor</value>
                   
    </list>
              
    </property>
              
    <property name="target">
                   
    <ref bean="kwikEMartTarget" />
              
    </property>
         
    </bean>

    </beans>
     
    運(yùn)行,結(jié)果如下:
    店員:悠~游! ,Can I help you ?
    --我想買(mǎi):果醬!
    店員:OK! 悠~游!.give you!
    店員:悠~游! ,Can I help you ?
    --我想買(mǎi):胡椒粉!
    店員:OK! 悠~游!.give you!
    店員:悠~游! ,Can I help you ?
    --我想買(mǎi):奶酪!
            店員:OK! 悠~游!.give you!
     
    在這里簡(jiǎn)單說(shuō)明一下xml文檔:nameMatchfilterPointcutregexpFilterPointcut 是我們自己定義好規(guī)則的Pointcut。nameMatchfilterPointcut 根據(jù)mappedName來(lái)設(shè)置過(guò)濾規(guī)則, regexpFilterPointcut則是用pattern來(lái)設(shè)置過(guò)濾規(guī)則。runDemofilterPointcutAdvisor則將我們的Pointcutadvice組合在一起。
    讀者可以自己修改runDemofilterPointcutAdvisorpointcut來(lái)切換不同的Pointcut。如果需要RegexpMethodPointcut 的子類(lèi)的實(shí)現(xiàn),必須要oro包支持。(注:RegexpMethodPointcut有倆個(gè)子類(lèi)的實(shí)現(xiàn),JdkRegexpMethodPointcut和Perl5RegexpMethodPointcut)。
         但是,如果我們想讓我們的Advisor同時(shí)實(shí)現(xiàn)多個(gè)Pointcut+advice怎么辦呢?利用Spring In Action里面的實(shí)例,我們來(lái)自己實(shí)現(xiàn)我們的Pointcut
     
        代碼:
     
     
    public class MyUnionPointcut implements Pointcut {
         
         
    private Pointcut delegate;

         
    public ClassFilter getClassFilter() {
              
    return getDelegate().getClassFilter();
         }


         
    private Pointcut getDelegate() {
              
    if (delegate == null{
                   
    throw new AopConfigException("No pointcuts have been configured.");
              }

              
    return delegate;
         }


         
    public MethodMatcher getMethodMatcher() {
              
    return getDelegate().getMethodMatcher();
         }


         
    public void setPointcuts(List pointcuts) {

              
    if (pointcuts == null || pointcuts.size() == 0{
                   
    throw new AopConfigException("Must have at least one Pointcut.");
              }

              delegate 
    = (Pointcut) pointcuts.get(0);

              
    for (int i = 1; i < pointcuts.size(); i++{
                   Pointcut pointcut 
    = (Pointcut) pointcuts.get(i);
                   delegate 
    = Pointcuts.union(delegate, pointcut);
              }


         }

    }

    其實(shí)就是繼承Pointcut類(lèi),實(shí)現(xiàn)getMethodMatcher()方法即可,接下來(lái)看我們把那兩個(gè)Pointcut組合成一個(gè),當(dāng)其中一個(gè)Pointcut滿(mǎn)足的時(shí)候就返回true,調(diào)用我們的Advice。
     
    在xml中,加入下面代碼:
    <bean id="myUnionPointcut" class="demo.utils.MyUnionPointcut">
              
    <property name="pointcuts">
                   
    <list>
                   
    <!-- 這里說(shuō)明一下:動(dòng)態(tài)切入點(diǎn)和靜態(tài)切入點(diǎn)集合在一起的時(shí)候好像有問(wèn)題? -->
                        
    <ref bean="nameMatchfilterPointcut" />
                        
    <ref bean="regexpFilterPointcut" />
                   
    </list> 
              
    </property>
         
    </bean>
    修改runDemofilterPointcutAdvisor的pointcut來(lái)加入我們組合好的Pointcut。

         
    <bean id="runDemofilterPointcutAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
              
    <property name="pointcut">
                   
    <ref bean=”myUnionPointcut" />
              
    </property>
              
    <property name="advice">
                   
    <ref bean="onePerCustomerInterceptor" />
              
    </property>
         
    </bean>
     
     
        
    同時(shí)在運(yùn)行前,讀者可以自己修改兩個(gè)pointcut的匹配方法,來(lái)匹配更多的可選項(xiàng)。同時(shí)可以參考的一個(gè)類(lèi)是org.springframework.aop.support.UnionPointcut,它實(shí)現(xiàn)兩個(gè)pointcut的聯(lián)合。如果讀者想實(shí)現(xiàn)更加靈活的匹配,需要自己來(lái)定義自己的pointcut。(如第一個(gè)pointcut交叉第二個(gè)pointcut,聯(lián)合第三個(gè)pointcut),交叉的工具類(lèi)為ComposablePointcut。
    運(yùn)行的結(jié)果請(qǐng)讀者自己試驗(yàn)。這個(gè)時(shí)候您可能在想,這些pointcut都是Spring自己的實(shí)現(xiàn),我們能否自己來(lái)定義我們自己規(guī)則的pointcut呢?當(dāng)然可以!~
    代碼:
    /**
     * 
     * 自己定義的靜態(tài)切入點(diǎn)
     * 滿(mǎn)足條件是:當(dāng)傳入的數(shù)字大于1塊錢(qián)的時(shí)候才可以;
     * 
     * 
    @author 悠~游
     * 
    @since 2006-06-22
     * 
    @link www.uusam.com
     
    */

    public class MyPointcut extends StaticMethodMatcherPointcut implements Serializable {

         
    private static final long serialVersionUID = -101281038294508751L;

         
    private int money = 0;

         
    /**
          * 實(shí)現(xiàn)方法,業(yè)務(wù)邏輯為:根據(jù)輸入的錢(qián)數(shù)和動(dòng)作(必須是以buy開(kāi)頭的方法),來(lái)確定是否有錢(qián)購(gòu)買(mǎi)商品,買(mǎi)完之后去掉商品的價(jià)格;
          
    */

         
    public boolean matches(Method method, Class targetClass) {
              
    if (method.getName().indexOf("buyCheese"== 0 && money >= 100{
                   money 
    -= 100;
                   
    return true;
              }
     else if (method.getName().indexOf("buyPepper"== 0 && money >= 5{
                   money 
    -= 5;
                   
    return true;
              }
     else if (method.getName().indexOf("buySquish"== 0 && money >= 10{
                   money 
    -= 10;
                   
    return true;
              }

              System.out.println(
    "門(mén)衛(wèi):你要買(mǎi)的東西太貴,你的錢(qián) "+money+" 太少!~ ,取消服務(wù)!");
              
    return false;
         }


         
    public void setMoney(int money) {
              
    this.money = money;
         }


    }

    這個(gè)就是我們自己定義的靜態(tài)Pointcut,主要實(shí)現(xiàn)自己的matches方法。看看如何加入到我們的XML文檔中:
    <!-- 使用自定義的切入點(diǎn) -->
         
    <bean id="myPointcut" class="demo.pointcut.MyPointcut">
              
    <property name="money">
                   
    <value>100</value>
              
    </property>
         
    </bean>
        
     
    很簡(jiǎn)單不是么?我們定義一個(gè)數(shù)字,就是用戶(hù)的money,進(jìn)入商店時(shí)候兜里的錢(qián)^_^。同樣修改我們的myUnionPointcut里面的pointcuts,加入我們的pointcut。
     
    <bean id="myUnionPointcut" class="demo.utils.MyUnionPointcut">
              
    <property name="pointcuts">
                   
    <list>
                        
    <!—上面兩個(gè)要設(shè)置成不通過(guò)哦,或者索性就去掉先。 -->
                        
    <ref bean="nameMatchfilterPointcut" />
                        
    <ref bean="regexpFilterPointcut" />
    <ref bean="myPointcut" />
                   
    </list> 
              
    </property>
         
    </bean>
     
        
    當(dāng)上面兩個(gè)Pointcut定義的規(guī)則不通過(guò)的時(shí)候,程序開(kāi)始校驗(yàn)我們的myPointcut。運(yùn)行,結(jié)果如下:
    店員:悠~游! ,Can I help you ?
    --我想買(mǎi):果醬!
    店員:OK! 悠~游!.give you!
    店員:悠~游! ,Can I help you ?
    --我想買(mǎi):胡椒粉!
    店員:OK! 悠~游!.give you!
    門(mén)衛(wèi):你要買(mǎi)的東西太貴,你的錢(qián) 85 太少!~ , 取消服務(wù)!
    --我想買(mǎi):奶酪!//服務(wù)員沒(méi)了...
        
         好了,是不是我們想要的結(jié)果呢?呵呵。
         同時(shí),Spring 提供動(dòng)態(tài)Pointcut。關(guān)于動(dòng)態(tài)的說(shuō)明我就不在熬述了,我們這里只關(guān)心具體Spring帶給我們的具體實(shí)現(xiàn)方法,具體應(yīng)用請(qǐng)讀者自己斟酌使用。
        
     
        
    <!-- 定制動(dòng)態(tài)接入點(diǎn),來(lái)判斷當(dāng)前線(xiàn)程堆棧中是否有demo.RunDemo這個(gè)類(lèi); -->
         
    <bean id="runDemoPointcut" class="org.springframework.aop.support.ControlFlowPointcut">
              
    <constructor-arg>
                   
    <value>demo.RunDemo</value>
              
    </constructor-arg>
         
    </bean>
         修改下面的引用我們的動(dòng)態(tài)Pointcut;
    <bean id="myUnionPointcut" class="demo.utils.MyUnionPointcut">
              
    <property name="pointcuts">
    <list>
         
    <ref bean=" runDemoPointcut " />
             
    </list> 
        
    </property>
    </bean>
     
         運(yùn)行,結(jié)果如下:
    店員:悠~游! ,Can I help you ?
    --我想買(mǎi):果醬!
    店員:OK! 悠~游!.give you!
    店員:悠~游! ,Can I help you ?
    --我想買(mǎi):胡椒粉!
    店員:OK! 悠~游!.give you!
    店員:悠~游! ,Can I help you ?
    --我想買(mǎi):奶酪!
    店員:OK! 悠~游!.give you!
        
         動(dòng)態(tài)切入點(diǎn)是根據(jù)當(dāng)前堆棧信息進(jìn)行方法匹配的一種規(guī)則,讀者可以自己修改demo.RunDemo,如java.lang.Integer,來(lái)看看結(jié)果。
     
    --我想買(mǎi):果醬!
    --我想買(mǎi):胡椒粉!
    --我想買(mǎi):奶酪!
        
         到這里能夠讀下來(lái)已經(jīng)很不容易了,呵呵。還是站起來(lái)走動(dòng)一下吧,接下來(lái)我們將搞定其他的一些東東。

    posted on 2006-12-19 13:12 常言笑 閱讀(394) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): JAVA/J2EE

    My Links

    Blog Stats

    常用鏈接

    留言簿(5)

    隨筆分類(lèi)

    隨筆檔案

    搜索

    積分與排名

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 亚洲国产午夜中文字幕精品黄网站| 色久悠悠婷婷综合在线亚洲| 亚洲AV日韩AV永久无码下载| 精品国产呦系列在线观看免费| 在线亚洲精品自拍| XXX2高清在线观看免费视频| 国产成人亚洲精品影院| 亚洲欧美熟妇综合久久久久| 成人性生交大片免费看无遮挡| 国产精品亚洲综合久久| 成人免费在线观看网站| 亚洲天堂男人影院| 久久久精品免费视频| 好大好深好猛好爽视频免费| 亚洲精品国产精品| 全部免费国产潢色一级| 亚洲Av高清一区二区三区| 欧美大尺寸SUV免费| 亚洲色大成网站WWW国产| 国产片免费在线观看| 成人免费网站视频www| 综合久久久久久中文字幕亚洲国产国产综合一区首| 一区二区三区精品高清视频免费在线播放| 亚洲国产高清在线一区二区三区| 丁香六月婷婷精品免费观看| 亚洲熟妇中文字幕五十中出| 无码中文字幕av免费放dvd| 亚洲国产美女福利直播秀一区二区| 可以免费看的卡一卡二| 亚洲人成电影网站免费| 免费精品国产自产拍观看| 一级做a爰片久久免费| 久久久久久亚洲精品| 综合在线免费视频| 亚洲成a人无码亚洲成www牛牛| 亚洲JIZZJIZZ中国少妇中文| 两个人看的www免费视频中文| 亚洲精品在线不卡| 88av免费观看| 亚洲综合激情另类小说区| 午夜两性色视频免费网站|