一、基礎
AOP功能:aop希望把分散在各個業務邏輯代碼中的相同代碼通過橫向切割的方式抽取到一個獨立的模塊中,還業務邏輯一個清晰的世界。
AOP術語:
1)連接點:程序執行的某個特定位置,spring僅支持方法的連接點。連接點由兩部分組成:方法表示的程序執行點、用相對位置表示方位。
2)切點:使用類和方法作爲連接點的查詢條件,連接點是方法執行前、後。而切點定位到某個方法
3)增強:增強是織入目標連接點上的一段程序代碼。
4)目標對象:要增強的目標類。
5)織入:將增強添加到目標類的具體連接點上的過程。分爲編譯器織入,類裝載期織入、動態代理織入;spring採用動態織入,AspectJ採用編譯器織入和類裝載期織入。
6)代理:一個類被AOP織入增強後,就產生一個結果類,它是融合了原類和增強邏輯的代理類。
7)切面:由切點和增強組成。
二、基於@AspectJ和Schema的AOP
註解
@Retention(RetentionPolicy.RUNTIME)//聲明註解的保留期限是在運行期間 而SOURCE:保留在源碼文件中;CLASS:類的字節碼文件中; @Target(ElementType.METHOD)//表示註解只能在目標類的方法上;TYPE、FIELD,METHOD,PARAMETER... public @interface Test { //成員必須以無參、無拋出異常的方式聲明;可以通過default指定默認值;如果只有一個成員,必須取名爲value(); boolean value() default true; }
2.使用@AspectJ
1)定義切面
@Aspect //通過註解將其標識爲一個切面 public class PreGreetingAspect{ @Before("execution(* greetTo(..))")//定義切點和增強類型 public void beforeGreeting(){ //增強的橫切邏輯 System.out.println("How are you"); } }
2)配置使用@AspectJ
xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> <aop:aspectj-autoproxy/>
Waiter target = new NaiveWaiter(); AspectJProxyFactory factory = new AspectJProxyFactory(); factory.setTarget(target);//設置目標對象 factory.addAspect(PreGreetingAspect.class);//添加切面 Waiter proxy = factory.getProxy();//生成織入切面的代理對象 proxy.greetTo("John"); proxy.serveTo("John");
<aop:aspectj-autoproxy/>自動爲spring容器中那些標註@AspectJ切面的Bean創建代理。有個proxy-target-class屬性,默認爲false,表示使用JDK動態代理,當設置爲true時表示使用CGLib動態代理。
3.@AspectJ語法基礎
1)通配符:*匹配任意字符,但是隻能匹配一個元素、 ..匹配任意字符,可以匹配多個元素、+表示按類型匹配指定類的所有類,必須在類的後面。
2)運算符:&& || !
3)增強類型:@Before前置增強、@AfterReturning後置增強、@Around環繞增強、@AfaterThrowing拋出增強、@After不管是拋出還是正常退出都增強、@DeclareParents引介增強(給服務員增加個收銀員);
4)切點函數之@annotation()表示標註了某個註解的所有方法
@AfterReturning("@annotation(com.smart.anno.NeedTest)") public void atAnnotaionTest(){ System.out.println("atAnnotaionTest() executed!"); } @NeedTest public void serveTo(String clientName){ System.out.println("NaiveWaiter:serving "+clientName+"..."); }
切點函數之execution()
execution(<修飾符> <返回類型> <方法名>(<參數>) )
4.基於Schema配置切面
<?xml version="1.0" encoding="UTF-8" ?> <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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> <aop:config proxy-target-class="true"> <aop:advisor advice-ref="testAdvice" pointcut="execution(* com..*.Waiter.greetTo(..))"/> <aop:aspect ref="adviceMethods"> <aop:before method="preGreeting" pointcut="target(com.smart.NaiveWaiter) and args(name)" arg-names="name" /> <aop:after-returning method="afterReturning" pointcut="target(com.smart.SmartSeller)" returning="retVal" /> <aop:around method="aroundMethod" pointcut="execution(* serveTo(..)) and within(com.smart.Waiter)" /> <aop:after-throwing method="afterThrowingMethod" pointcut="target(com.smart.SmartSeller) and execution(* checkBill(..))" throwing="iae" /> <aop:after method="afterMethod" pointcut="execution(* com..*.Waiter.greetTo(..))" /> </aop:aspect> </aop:config> <bean id="testAdvice" class="com.smart.schema.TestBeforeAdvice"/> <bean id="adviceMethods" class="com.smart.schema.AdviceMethods" /> <bean id="naiveWaiter" class="com.smart.NaiveWaiter" /> <bean id="naughtyWaiter" class="com.smart.NaughtyWaiter" /> <bean id="seller" class="com.smart.SmartSeller" /> </beans>
<aop:config>內可以定義多個切面,<aop:aspect ref="增強方法的bean">表示一個切面,切面可以包含多個增強<aop:befor pointcut="execution()" method="">
<Advisor>僅包含一個切點和一個增強
<aop:advisor advice-ref="增強類的bean" pointcut="execution(* com..*.Waiter.greeto(..))"/>