讀書筆記-基於註解和聲明式的aop

@AspectJ配置切面

編程方式實現

public class Waiter {
    public void check(String name){
        System.out.println("waiter說:結帳?"+name);
    }
    public void serve(String name){
        System.out.println("waiter說:要點什麼?"+name);
    }
}
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class PreGreeting {
    @Before("execution(* serve(..))")
    public void beforeGreeting(){
        System.out.println("how are you!");
    }
}

@Before註解表示前置加強,後面的切點表達式表示在目標類的serve()方法織入加強,serve()方法能夠帶任意的傳入參數和任意的返回值。
PreGreeting類經過註解,將切點,加強類型和加強的橫切邏輯組合在一塊兒。PreGreeting類至關於上一篇中的BeforeAdvice(加強),NameMatchMethodPointcut(切點)DefaultPointcutAdvisor(切面)三者聯合表達的信息。java

Waiter waiter=new Waiter();
        AspectJProxyFactory factory=new AspectJProxyFactory();
        factory.setTarget(waiter);//設置目標類
        factory.addAspect(PreGreeting.class);//添加切面
        Waiter proxy=factory.getProxy();
        proxy.serve("TheViper");
        proxy.check("TheViper");
how are you!
waiter說:要點什麼?TheViper
waiter說:結帳?TheViper

經過配置使用

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop.xsd">
    <aop:aspectj-autoproxy/>
    <bean id='waiter' class='aspectj.Waiter'/>
    <bean class='aspectj.PreGreeting'/>
</beans>
  • 引用aop命名空間spring

xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="...  
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop.xsd"
  • <aop:aspectj-autoproxy/>自動爲spring容器中那些匹配@AspectJ切面的Bean建立代理,完成切面織入express

ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
        Waiter waiter=(Waiter)ctx.getBean("waiter");
        waiter.serve("TheViper");
        waiter.check("TheViper");

使用的時候,直接獲取bean操做就能夠了,不用像前面還要建立AspectJProxyFactory,設置好代理才能用。編程

schema配置切面

配置命名切點

須要引入aspectjweaversegmentfault

public class GreetBefore {
    public void say(String name){
        System.out.println("hallo!"+name);
    }
}

加強不用像上一篇中那樣,須要繼承特定類或實現特定接口。app

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id='waiterTarget' class='com.Waiter'/>
    <bean id='greetBefore' class='schema.GreetBefore'/>
    <aop:config>
        <aop:pointcut expression="target(com.Waiter) and execution(* check(..)) and args(name,..)" 
        id="servePointcut"/>
        <aop:aspect ref="greetBefore">
            <aop:before method="say" pointcut-ref="servePointcut"/>
        </aop:aspect>
    </aop:config>
</beans>

匹配Waiter類中的check()方法。代理

  • 須要引入aop命名空間code

xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="... http://www.springframework.org/schema/aop 
http://www.springframework.org/schema/aop/spring-aop.xsd"
  • <aop:aspect>定義切面,其內部能夠定義多個加強,ref屬性指定引用的具體加強xml

  • <aop:before>聲明瞭一個前置加強,經過pointcut-ref屬性引用切點,method屬性指定加強中哪一個方法用於具體的加強行爲對象

  • <aop:pointcut>定義切點,expression屬性設置切點表達式,其語法和@AspectJ中的語法徹底相同。

public class Waiter {
    public void check(String name){
        System.out.println("waiter說:結帳?"+name);
    }
    public void serve(String name){
        System.out.println("waiter說:要點什麼?"+name);
    }
}
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
        Waiter waiter=(Waiter)ctx.getBean("waiterTarget");
        waiter.serve("TheViper");
        waiter.check("TheViper");
waiter說:要點什麼?TheViper
hallo!TheViper
waiter說:結帳?TheViper

配置順序問題

命名切點只能被當前<aop:aspect>內定義的元素訪問到,<aop:config>中的配置順序必須是<aop:pointcut>=><aop:advisor>=><aop:aspect>

各類加強類型

後置加強

<aop:config>
    ...
    <aop:aspect ref="greetBefore">
        <aop:after-returning method="sayEnjoy" pointcut='target(com.Waiter) and execution(* serve(..))'/>
    </aop:aspect>
</aop:config>

環繞加強

<aop:config>
    ...
    <aop:aspect ref="greetBefore">
        <aop:around method="aroundMethod" pointcut='execution(* serve(..)) and within(com.Waiter))'/>
    </aop:aspect>
</aop:config>
public void aroundMethod(ProceedingJoinPoint pjp){
    //pjp能夠訪問到環繞加強的鏈接點信息
        ...
    }

拋出異常加強

<aop:config>
    ...
    <aop:aspect ref="greetBefore">
        <aop:after-throwing method="afterThrowingMethod" pointcut='target(com.Waiter) and 
        execution(* serve(..))' throwing='exception'/>
    </aop:aspect>
</aop:config>
public void afterThrowingMethod(Exception exception){
    ...
}

throwing屬性聲明須要綁定的異常對象,指定的異常名必須和加強方法對應的傳入參數一致

final加強

<aop:config>
    ...
    <aop:aspect ref="greetBefore">
        <aop:after method="afterMethod" pointcut='execution(*com.Waiter. serve(..))'/>
    </aop:aspect>
</aop:config>

引介加強

相關文章
相關標籤/搜索