AOP稱為面向切面編程奸绷,在程序開發(fā)中主要用來解決一些系統(tǒng)層面上的問題,比如日志借浊,事務(wù)塘淑,權(quán)限等等
一、AOP基本概念
Aspect(切面):通常是一個(gè)類蚂斤,里面可以定義切入點(diǎn)和通知
JointPoint(連接點(diǎn)):程序執(zhí)行過程中明確的點(diǎn)存捺,一般是方法的調(diào)用
Advice(通知):AOP在特定的切入點(diǎn)上執(zhí)行的增強(qiáng)處理,定義了切面是什么及何時(shí)使用曙蒸,應(yīng)該應(yīng)用在某個(gè)方法被調(diào)用之前捌治,調(diào)用之后,還是拋出異常時(shí)纽窟。有before,after,afterReturning,afterThrowing,around
Pointcut(切入點(diǎn)):就是帶有通知的連接點(diǎn)肖油,在程序中主要體現(xiàn)為書寫切入點(diǎn)表達(dá)式(即aop攔截的方法)
AOP代理:AOP框架創(chuàng)建的對(duì)象,代理就是目標(biāo)對(duì)象的加強(qiáng)师倔。Spring中的AOP代理可以使JDK動(dòng)態(tài)代理构韵,也可以是CGLIB代理,前者基于接口趋艘,后者基于子類
二疲恢、實(shí)現(xiàn)策略
Java SE動(dòng)態(tài)代理:
使用動(dòng)態(tài)代理可以為一個(gè)或多個(gè)接口在運(yùn)行期動(dòng)態(tài)生成實(shí)現(xiàn)對(duì)象,生成的對(duì)象中實(shí)現(xiàn)接口的方法時(shí)可以添加增強(qiáng)代碼瓷胧,從而實(shí)現(xiàn)AOP显拳。缺點(diǎn)是只能針對(duì)接口進(jìn)行代理,另外由于動(dòng)態(tài)代理是通過反射實(shí)現(xiàn)的搓萧,有時(shí)可能要考慮反射調(diào)用的開銷杂数。字節(jié)碼生成(CGLib 動(dòng)態(tài)代理)
動(dòng)態(tài)字節(jié)碼生成技術(shù)是指在運(yùn)行時(shí)動(dòng)態(tài)生成指定類的一個(gè)子類對(duì)象,并覆蓋其中特定方法瘸洛,覆蓋方法時(shí)可以添加增強(qiáng)代碼揍移,從而實(shí)現(xiàn)AOP。其常用工具是cglib反肋。定制的類加載器
當(dāng)需要對(duì)類的所有對(duì)象都添加增強(qiáng)那伐,動(dòng)態(tài)代理和字節(jié)碼生成本質(zhì)上都需要?jiǎng)討B(tài)構(gòu)造代理對(duì)象,即最終被增強(qiáng)的對(duì)象是由AOP框架生成石蔗,不是開發(fā)者new出來的罕邀。解決的辦法就是實(shí)現(xiàn)自定義的類加載器,在一個(gè)類被加載時(shí)對(duì)其進(jìn)行增強(qiáng)养距。JBoss就是采用這種方式實(shí)現(xiàn)AOP功能诉探。代碼生成
利用工具在已有代碼基礎(chǔ)上生成新的代碼,其中可以添加任何橫切代碼來實(shí)現(xiàn)AOP棍厌。語言擴(kuò)展
可以對(duì)構(gòu)造方法和屬性的賦值操作進(jìn)行增強(qiáng)肾胯,AspectJ是采用這種方式實(shí)現(xiàn)AOP的一個(gè)常見Java語言擴(kuò)展竖席。
三、使用AOP記錄異常信息
1阳液、啟用@AsjectJ支持
//注解啟用的方式
@EnableAspectJAutoProxy
//xml啟用的方式
<aop:aspectj-autoproxy/>
2怕敬、定義一個(gè)切面
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class ExceptionTaken {
@AfterThrowing(throwing = "ex", pointcut = "execution(* com.lzhwy.boot_1.service.BootService..*(..))")
public void takeExceptionLog(JoinPoint joinPoint, Throwable ex) {
System.out.println(joinPoint.getSignature().getName() + "出現(xiàn)異常了");
System.out.println(ex.getMessage());
}
}