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

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

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

    隨筆-88  評(píng)論-77  文章-48  trackbacks-0
    Spring Aop Step-By-Step 學(xué)習(xí)筆記(上)
    ?www.uusam.com
    ?
    最近由于工作需要,要求掌握關(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í)例來(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
    下載地址:
    http://prdownloads.sourceforge.net/springframework/spring-framework-1.2.8-with-dependencies.zip?use_mirror=ufpr
    ?
    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 入門
    ?
    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)單,顧客到商店買東西,店員根據(jù)顧客的需要給于顧客提供服務(wù)。實(shí)現(xiàn)方法前插入,方法后插入,環(huán)繞,異常四種。
    ?
    ?????? 代碼:
    ???? ???? 建立一個(gè)用戶類;
    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è)方法,買奶酪,買胡椒粉,買果醬;
    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("-- 我想買:" + s);
    ???? ???? return s;
    ?
    ???? }
    ?
    ???? public Pepper buyPepper(Customer customer) throws NoMorePepperException{
    ?
    ???? ???? if (pepperIsEmpty) {
    ???? ???? ???? throw new NoMorePepperException();
    ???? ???? }
    ?
    ???? ???? Pepper s = new Pepper();
    ???? ???? System.out.println("-- 我想買:" + s);
    ???? ???? return s;
    ?
    ???? }
    ?
    ???? public Squish buySquish(Customer customer) throws NoMoreSquishException{
    ?
    ???? ???? if (squishIsEmpty) {
    ???? ???? ???? throw new NoMoreSquishException();
    ???? ???? }
    ?
    ???? ???? Squish s = new Squish();
    ???? ???? System.out.println("-- 我想買:" + 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í)例類;
    ?????????
    public class RunDemo {
    ?
    ???? ???? ???? public static void kwikEMart() {
    ?
    ???? ???? ???? ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo/kwikemart.xml");
    ?
    ???? ???? ???? ???? //如果你想通過(guò)類來(lái)引用這個(gè)的話,就要用到CGLIB.jar了,同時(shí)在代理工廠里面設(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">
    ???? ???? <!--
    ???? ???? ???? 把這里注釋去掉的話,程序調(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è)類的代碼都不大。如果你對(duì) org.springframework.aop.framework.ProxyFactoryBean 不是很了解的話可以看我下篇尾處的介紹。 讀清楚之后,我們運(yùn)行RunDemo 類,查看控制臺(tái)結(jié)果,如下:
    ?
    店員::Hello 悠~游! . How are you doing?
    店員:悠~游! ,Can I help you ?
    -- 我想買:果醬!
    店員:OK! 悠~游!.give you!
    店員:Thank you 悠~游! . Come again!
    店員::Hello 悠~游! . How are you doing?
    店員:悠~游! ,Can I help you ?
    -- 我想買:胡椒粉!
    店員:OK! 悠~游!.give you!
    店員:Thank you 悠~游! . Come again!
    店員::Hello 悠~游! . How are you doing?
    店員:悠~游! ,Can I help you ?
    -- 我想買:奶酪!
    店員: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 異常!
    ???? 好好理解一下,我就不廢話了,我們進(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 ?
    --我想買:果醬!
    店員:OK! 悠~游!.give you!
    店員:悠~游! ,Can I help you ?
    --我想買:胡椒粉!
    店員:OK! 悠~游!.give you!
    店員:悠~游! ,Can I help you ?
    --我想買:奶酪!
    ??????? 店員: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 的子類的實(shí)現(xiàn),必須要oro包支持。(注:RegexpMethodPointcut有倆個(gè)子類的實(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類,實(shí)現(xiàn)getMethodMatcher()方法即可,接下來(lái)看我們把那兩個(gè)Pointcut組合成一個(gè),當(dāng)其中一個(gè)Pointcut滿足的時(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>
    修改runDemofilterPointcutAdvisorpointcut來(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è)類是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),交叉的工具類為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)
    ?* 滿足條件是:當(dāng)傳入的數(shù)字大于1塊錢的時(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ù)輸入的錢數(shù)和動(dòng)作(必須是以buy開(kāi)頭的方法),來(lái)確定是否有錢購(gòu)買商品,買完之后去掉商品的價(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("門衛(wèi):你要買的東西太貴,你的錢 "+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ù)字,就是用戶的money,進(jìn)入商店時(shí)候兜里的錢^_^。同樣修改我們的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 ?
    --我想買:果醬!
    店員:OK! 悠~游!.give you!
    店員:悠~游! ,Can I help you ?
    --我想買:胡椒粉!
    店員:OK! 悠~游!.give you!
    門衛(wèi):你要買的東西太貴,你的錢 85 太少!~ , 取消服務(wù)!
    --我想買:奶酪!//服務(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)前線程堆棧中是否有demo.RunDemo這個(gè)類;?-->
    ???? <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 ?
    --我想買:果醬!
    店員:OK! 悠~游!.give you!
    店員:悠~游! ,Can I help you ?
    --我想買:胡椒粉!
    店員:OK! 悠~游!.give you!
    店員:悠~游! ,Can I help you ?
    --我想買:奶酪!
    店員:OK! 悠~游!.give you!
    ????
    ???? 動(dòng)態(tài)切入點(diǎn)是根據(jù)當(dāng)前堆棧信息進(jìn)行方法匹配的一種規(guī)則,讀者可以自己修改demo.RunDemo,如java.lang.Integer,來(lái)看看結(jié)果。
    ?
    --我想買:果醬!
    --我想買:胡椒粉!
    --我想買:奶酪!
    ????
    ???? 到這里能夠讀下來(lái)已經(jīng)很不容易了,呵呵。還是站起來(lái)走動(dòng)一下吧,接下來(lái)我們將搞定其他的一些東東。

    posted on 2006-07-05 17:26 崛起的程序員 閱讀(350) 評(píng)論(0)  編輯  收藏

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲国产日韩在线| 精选影视免费在线 | 无码人妻一区二区三区免费看 | 久久亚洲国产伦理| 青青青视频免费观看| 无码永久免费AV网站| 久久亚洲一区二区| 一级成人a免费视频| 午夜寂寞在线一级观看免费| 亚洲精品第一国产综合精品| a级精品九九九大片免费看| 亚洲AV永久无码精品一区二区国产 | 亚洲综合一区二区精品导航| 四虎影视在线看免费观看| 成年人免费观看视频网站| 亚洲精品中文字幕无码AV| 中文字幕免费不卡二区| 久久精品亚洲福利| 色偷偷亚洲第一综合网| 中文字幕无码不卡免费视频| 老色鬼久久亚洲AV综合| 日本免费A级毛一片| 久久久久亚洲AV无码专区网站| 国产精品亚洲专区无码唯爱网| 国产精品成人免费一区二区| 亚洲视频在线免费看| 久久伊人免费视频| 国产亚洲一区二区三区在线| www一区二区www免费| 亚洲男人av香蕉爽爽爽爽| 在线亚洲v日韩v| 国产精品成人四虎免费视频| 亚洲最大天堂无码精品区| 在线视频观看免费视频18| 亚洲一区无码中文字幕乱码| 四虎精品视频在线永久免费观看| 久久久久亚洲精品天堂| 日本在线看片免费人成视频1000| 久久精品夜色国产亚洲av| 久久精品私人影院免费看| 亚洲欧洲国产精品你懂的|