Aspect Oriented Programing 面向切面編程,相比較 oop 面向對象編程來講,Aop 關注的再也不是程序代碼中某個類,某些方法,而 aop 考慮的更多的是一種面到面的切入,即層與層之間的一種切入,因此稱之爲切面。聯想你們吃的漢堡(中間夾肉)。那麼 aop 是怎麼作到攔截整個面的功能呢?考慮學到的 servlet urlpattern /* 的配置,實際上也是 aop 的實現 。java
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.9</version> </dependency>
添加命名空間spring
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
配置 Aop 代理express
<aop:aspectj-autoproxy/>
/** * 聲明切面組件 */ @Component @Aspect public class LogCut { /** * 定義切入點 匹配方法規則定義 * 匹配規則表達式含義 攔截 com.xxx.service 包下 以及子包下 全部類的全部方法 */ @Pointcut("execution (* com.xxx.service..*.*(..))") public void cut(){} /** * 聲明前置通知 並將通知應用到定義的切入點上 * 目標類方法執行前 執行該通知 */ @Before(value="cut()") public void before(){ System.out.println("前置通知....."); } /** * 聲明返回通知 並將通知應用到切入點上 * 目標類方法執行完畢執行該通知 */ @AfterReturning(value="cut()") public void afterReturning(){ System.out.println("返回通知...."); } /** * 聲明最終通知 並將通知應用到切入點上 * 目標類方法執行過程當中是否發生異常 均會執行該通知 至關於異常中的 finally */ @After(value="cut()") public void after(){ System.out.println("最終通知...."); } /** * 聲明異常通知 並將通知應用到切入點上 * 目標類方法執行時發生異常 執行該通知 */ @AfterThrowing(value="cut()",throwing="e") public void afterThrowing(Exception e){ System.out.println("異常通知....方法執行異常時執行:"+e); } /** * 聲明環繞通知 並將通知應用到切入點上 * 方法執行先後 經過環繞通知定義相應處理 */ @Around(value="cut()") public Object around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("環繞前置..."); System.out.println("環繞通知"); System.out.println(pjp.getTarget()+"--"+pjp.getSignature()); Object result=pjp.proceed();//執行目標對象方法 System.out.println("環繞後置..."); return result; } }
Aop 切入點表達式簡介 編程
執行任意公共方法:ide
execution(public *(..))
執行任意的 set 方法oop
execution(* set*(..))
執行 com.xxx.service 包下任意類的任意方法url
execution(* com.xxx.service.*.*(..))
執行 com.xxx.service 包 以及子包下任意類的任意方法代理
execution(* com.xxx.service..*.*(..))
<!-- aop 相關配置 --> <aop:config> <!-- aop 切面配置 --> <aop:aspect ref="logCut"> <!-- 定義 aop 切入點 --> <aop:pointcut expression="execution (* com.xxx.service..*.*(..))" id="cut"/> <!-- 配置前置通知 指定前置通知方法名 並引用切入點定義 --> <aop:before method="before" pointcut-ref="cut"/> <!-- 配置返回通知 指定返回通知方法名 並引用切入點定義 --> <aop:after-returning method="afterReturning" pointcut-ref="cut"/> <!-- 配置異常通知 指定異常通知方法名 並引用切入點定義 --> <aop:after-throwing method="afterThrowing" throwing="e" pointcut-ref="cut"/> <!-- 配置最終通知 指定最終通知方法名 並引用切入點定義 --> <aop:after method="after" pointcut-ref="cut"/> <!-- 配置環繞通知 指定環繞通知方法名 並引用切入點定義 --> <aop:around method="around" pointcut-ref="cut"/> </aop:aspect> </aop:config>
/** * 聲明切面組件 */ @Component public class LogCut { public void before(){ System.out.println("前置通知....."); } public void afterReturning(){ System.out.println("返回通知...."); } public void after(){ System.out.println("最終通知...."); } public void afterThrowing(Exception e){ System.out.println("異常通知....方法執行異常時執行:" + e); } public Object around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("環繞前置..."); System.out.println("環繞通知"); System.out.println(pjp.getTarget()+"--"+pjp.getSignature()); Object result=pjp.proceed(); System.out.println("環繞後置..."); return result; } }
被攔截到的每一個點,spring 中指被攔截到的每個方法,spring aop 一個鏈接點即表明一個方法的執行。code
對鏈接點進行攔截的定義(匹配規則定義 規定攔截哪些方法,對哪些方法進行處理),spring 這塊有專門的表達式語言定義。xml
攔截到每個鏈接點即(每個方法)先後所要作的操做
切入點與通知的結合,決定了切面的定義,切入點定義了要攔截哪些類的 哪些方法,通知則定義了攔截方法後要作什麼,切面則是橫切關注點的抽象,與類類似,類是對物體特徵的抽象,切面則是橫切關注點抽象。
被代理的目標對象
將切面應用到目標對象並生成代理對象的這個過程即爲織入(過程)。
在不修改原有應用程序代碼的狀況下,在程序運行期爲類動態添加方法或者字段的過程稱爲引入。