須要的類包:java
一、一個簡單的例子spring
package com.yyq.annotation; public interface Waiter { void greetTo(String name); void serveTo(String name); }
NaiveWaiter業務類:數組
package com.yyq.annotation; public class NaiveWaiter implements Waiter { @Override public void greetTo(String name) { System.out.println("NaiveWaiter:greet to " + name + "..."); } @Override public void serveTo(String name) { System.out.println("NaiveWaiter:serving to " + name + "..."); } }
PreGreetingAspect切面實現類:ide
package com.yyq.annotation; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; //經過該註解將PreGreetingAspect標識爲一個切面 @Aspect public class PreGreetingAspect { //定義切點和加強類型 @Before("execution(* greetTo(..))") //加強的橫切邏輯 public void beforeGreeting(){ System.out.println("How are you"); } }
測試方法:函數
@Test public void aspectJProxyTest(){ Waiter target = new NaiveWaiter(); AspectJProxyFactory factory = new AspectJProxyFactory(); //設置目標對象 factory.setTarget(target); //添加切面對象 factory.addAspect(PreGreetingAspect.class); //生成織入切面的代理對象 Waiter proxy = factory.getProxy(); proxy.greetTo("Anny"); proxy.serveTo("Mei"); }
輸出結果:測試
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!--目標Bean--> <bean id="waiter" class="com.yyq.annotation.NaiveWaiter"/> <!--使用了@AspectJ註解的切面類--> <bean class="com.yyq.annotation.PreGreetingAspect"/> <!--自動代理建立器,自動將@AspectJ註解切面類織入到目標Bean中--> <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/> </beans>
測試方法:this
@Test public void aspectJProxyTest2(){ String configPath = "com\\yyq\\annotation\\beans.xml"; ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath); Waiter waiter = (Waiter)ctx.getBean("waiter"); waiter.greetTo("John"); }
<?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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <aop:aspectj-autoproxy/> <bean id="waiter" class="com.yyq.annotation.NaiveWaiter"/> <bean class="com.yyq.annotation.PreGreetingAspect"/> </beans>
測試方法:spa
@Test public void aspectJProxyTest3(){ String configPath = "com\\yyq\\annotation\\beans2.xml"; ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath); Waiter waiter = (Waiter)ctx.getBean("waiter"); waiter.greetTo("Herry"); }
Spring支持9個@ApsectJ切點表達式函數,它們用不一樣的方式描述目標類的鏈接點,根據描述對象的不一樣,能夠將它們大體分爲4種類型:
· 方法切點函數:經過描述目標類方法信息定義鏈接點;
· 方法入參切點函數:經過描述目標類方法入參的信息定義鏈接點;
· 目標類切點函數:經過描述目標類類型信息定義鏈接點;
· 代理類切點函數:經過描述目標類的代理類的信息定義鏈接點; 代理
類別 | 函數 | 入參 | 說明 |
方法切點函數 | execution() | 方法匹配模式串 | 表示知足某一匹配模式的全部目標類方法鏈接點。如execution(* greetTo(..))表示全部目標類中的greetTo()方法。 |
@annotation() | 方法註解類名 | 表示標註了特定註解的目標方法鏈接點。如@annotation(com.baobaotao.anno.NeedTest)表示任何標註了@NeedTest註解的目標類方法。 | |
方法入參切點函數 | args() | 類名 | 經過判別目標類方法運行時入參對象的類型定義指定鏈接點。如args(com.baobaotao.Waiter)表示全部有且僅有一個按類型匹配於Waiter的入參的方法。 |
@args() | 類型註解類名 | 經過判別目標方法的運行時入參對象的類是否標註特定註解來指定鏈接點。如@args(com.baobaotao.Monitorable)表示任何這樣的一個目標方法:它有一個入參且入參對象的類標註@Monitorable註解。 | |
目標類切點函數 | within() | 類名匹配串 | 表示特定域下的全部鏈接點。如within(com.baobaotao.service.*)表示 com.baobaotao.service包中的全部鏈接點,也即包中全部類的全部方法,而 within(com.baobaotao.service.*Service)表示在com.baobaotao.service包中,全部以 Service結尾的類的全部鏈接點。 |
target() | 類名 | 假如目標類按類型匹配於指定類,則目標類的全部鏈接點匹配這個切點。如經過target(com.baobaotao.Waiter)定義的切點,Waiter、以及Waiter實現類NaiveWaiter中全部鏈接點都匹配該切點。 | |
@within() | 類型註解類名 | 假如目標類按類型匹配於某個類A,且類A標註了特定註解,則目標類的全部鏈接點匹配這個切點。如@within(com.baobaotao.Monitorable)定義的切點,假如Waiter類標註了@Monitorable註解,則Waiter以及Waiter實現類NaiveWaiter類的全部鏈接點都匹配。 | |
@target() | 類型註解類名 | 目標類標註了特定註解,則目標類全部鏈接點匹配該切點。如@target(com.baobaotao.Monitorable),假如NaiveWaiter標註了@Monitorable,則NaiveWaiter全部鏈接點匹配切點。 | |
代理類切點函數 | this() | 類名 | 代理類按類型匹配於指定類,則被代理的目標類全部鏈接點匹配切點。 |
package com.yyq.annotation; public interface Seller { int sell(String goods, String clientName); }
SmartSeller實現類:調試
package com.yyq.annotation; public class SmartSeller implements Seller { public int sell(String goods,String clientName) { System.out.println("SmartSeller: sell "+goods +" to "+clientName+"..."); return 100; } }
EnableSellerAspect切面實現類:
package com.yyq.annotation; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.DeclareParents; @Aspect public class EnableSellerAspect { @DeclareParents(value = "com.yyq.annotation.NaiveWaiter",defaultImpl = SmartSeller.class) public Seller seller; }
beans3.xml配置文件:
<?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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <aop:aspectj-autoproxy/> <bean id="waiter" class="com.yyq.annotation.NaiveWaiter"/> <bean class="com.yyq.annotation.EnableSellerAspect"/> </beans>
測試方法:
@Test public void aspectJProxyTest4(){ String configPath = "com\\yyq\\annotation\\beans3.xml"; ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath); Waiter waiter = (Waiter)ctx.getBean("waiter"); waiter.greetTo("John"); Seller seller = (Seller)waiter; //成功進行強制類型轉換 seller.sell("Beer","John"); }
package com.yyq.aspectJ; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface NeedTest { boolean value() default true; }
Waiter接口:
package com.yyq.aspectJ; public interface Waiter { void greetTo(String name); void serveTo(String name); }
NaiveWaiter實現類:
package com.yyq.aspectJ; public class NaiveWaiter implements Waiter { @Override public void greetTo(String name) { System.out.println("NaiveWaiter:greet to " + name + "..."); } @Override public void serveTo(String name) { System.out.println("NaiveWaiter:serving to " + name + "..."); } }
NaughtyWaiter實現類:
package com.yyq.aspectJ; public class NaughtyWaiter implements Waiter { @NeedTest public void greetTo(String clientName) { System.out.println("NaughtyWaiter:greet to "+clientName+"..."); } public void serveTo(String clientName){ System.out.println("NaughtyWaiter:serving "+clientName+"..."); } public void joke(String clientName,int times){ System.out.println("NaughtyWaiter:play "+times+" jokes to "+clientName+"..."); } }
TestAspcet切面實現類:
package com.yyq.aspectJ; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; @Aspect public class TestAspect { @AfterReturning("@annotation(com.yyq.aspectJ.NeedTest)") public void needTestFun(){ System.out.println("needTestFun() executed!"); } }
Spring配置自動應用切面:
<?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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <aop:aspectj-autoproxy/> <bean id="naiveWaiter" class="com.yyq.aspectJ.NaiveWaiter"/> <bean id="naughtyWaiter" class="com.yyq.aspectJ.NaughtyWaiter"/> <bean class="com.yyq.aspectJ.TestAspect"/> </beans>
測試方法:
package com.yyq; import com.yyq.aspectJ.Waiter; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AspectJTest { @Test public void annotationAspectJTest() { String configPath = "com\\yyq\\aspectJ\\beans.xml"; ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath); Waiter naiveWaiter = (Waiter) ctx.getBean("naiveWaiter"); Waiter naughtyWaiter = (Waiter) ctx.getBean("naughtyWaiter"); naiveWaiter.greetTo("John"); naiveWaiter.serveTo("John"); naughtyWaiter.greetTo("Tom"); naughtyWaiter.serveTo("Tom"); } }
形如within(com.baobaotao.NaiveWaiter)是within()函數所能表達的最小粒度,若是試圖用within()匹配方法級別的鏈接點,如within(com.baobaotao.NaiveWaiter.greet*)將會產生解析錯誤。
匹配目標類NaiveWaiter的全部方法。若是切點調整爲within(com.baobaotao.Waiter),則NaiveWaiter和 NaughtyWaiter中的全部方法都不匹配,而Waiter自己是接口不可能實例化,因此 within(com.baobaotao.Waiter)的聲明是無心義的;
匹配com.baobaotao包中的全部類,但不包括子孫包,因此com.baobaotao.service包中類的方法不匹配這個切點;
匹配com.baobaotao包及子孫包中的類,因此com.baobaotao.service、com.baobaotao.dao以及com.baobaotao.service.fourm等包中全部類的方法都匹配這個切點。