AOP、、
基本概念:
AOP:面向切面編程,一種編程范式,指導(dǎo)開發(fā)者如何組織結(jié)構(gòu)
作用:在不驚動原始設(shè)計的基礎(chǔ)上為其進行功能增強
連接點:程序在執(zhí)行過程中的任意位置,粒度為執(zhí)行方法,拋出異常,設(shè)置變量等
切入點:匹配連接點的式子
通知:在切入點處執(zhí)行的操作,也就是共性功能
通知類:定義通知的類
切面:描述通知和切入點的對應(yīng)關(guān)系
AOP入門
1.導(dǎo)入aspectj的坐標
<dependency><groupId> org.aspectj</groupId ><artifactId> aspectjweaver</artifactId ><version> 1.8.7</version > </dependency>2.制作共性功能–mehtod方法
3.定義切入點–pt()
4.綁定切入點和切面的關(guān)系–@Before
//通知類必須配置成Spring管理的bean @Component //設(shè)置當前類為切面類類 @Aspect public class MyAdvice {//設(shè)置切入點,要求配置在方法上方@Pointcut("execution(void com.itheima.dao.BookDao.update())")private void pt(){}//設(shè)置在切入點pt()的前面運行當前操作(前置通知)@Before("pt()")public void method(){System.out.println(System.currentTimeMillis());} }在配置類中
//開啟注解開發(fā)AOP功能 @EnableAspectJAutoProxy測試:
public static void main(String[] args) {ApplicationContext applicationContext=new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bean = applicationContext.getBean(BookDao.class);bean.save(); }AOP核心概念
目標對象:原始功能去掉共性功能對應(yīng)的類產(chǎn)生的對象。這種對象是無法直接完成最終工作的
代理:目標對象無法發(fā)直接完成工作,需要對其進行功能回填,通過原始對象的代理對象實現(xiàn)
SpringAOP本質(zhì):代理模式
AOP切入點表達式:要進行增強的方法的就描述方式
切入點表達式標準格式:動作關(guān)鍵字(訪問修飾符,返回值,包名.類/接口名.方法名 (參數(shù)) 異常名)
動作關(guān)鍵字:描述切入點的行為動作,例如execution表示執(zhí)行到切入點
訪問修飾符:public,private等,可以省略
異常名:可以省略
在AOP中可以使用通配符,快速描述
*:單個獨立的任意符號
…:多個連續(xù)的任意符號,可以獨立出現(xiàn),用于簡化包名與參數(shù)的書寫
+:專用于匹配子類類型
書寫規(guī)則:
所有代碼按照標準規(guī)范開發(fā),否則以下技巧全部失效
描述切入點通常描述接口而不是描述實現(xiàn)類
訪問控制修飾符針對接口開發(fā)均采用public描述
返回值類型對于增刪改查類使用精準類型加速匹配,對于查詢類使用*通配快速描述
包名書寫盡量不使用…匹配,效率過低,常用*做單個包描述匹配,或精準匹配
接口名/類名書寫名稱與模塊相關(guān)的采用匹配,例如UserService寫成Service
方法名書寫以動詞進行精準匹配,動詞采用匹配,例如getById書寫成getBy,
參數(shù)規(guī)則較為復(fù)雜,根據(jù)業(yè)務(wù)方法靈活調(diào)整
通常不使用異常作為匹配規(guī)則
AOP的五種通知類型:
@Before:前置通知,在原始方法運行之前執(zhí)行
@After:后置通知,在原始方法運行之后執(zhí)行
@Around:環(huán)繞通知,在原始方法運行的前后執(zhí)行
@AfterReturning:返回后通知,在原始方法執(zhí)行完畢后運行,且原始方法執(zhí)行過程中未出現(xiàn)異常現(xiàn)象
@AfterThrowing:拋出異常后通知,在原始方法執(zhí)行過程中出現(xiàn)異常后運行
案例:測量業(yè)務(wù)層接口的萬次執(zhí)行效率
@Component @Aspect public class ProjectAdvice {//匹配業(yè)務(wù)層的所有方法@Pointcut("execution(* com.itheima.service.*Service.*(..))")private void servicePt(){}//設(shè)置環(huán)繞通知,在原始操作的運行前后記錄執(zhí)行時間@Around("ProjectAdvice.servicePt()")public void runSpeed(ProceedingJoinPoint pjp) throws Throwable {//獲取執(zhí)行的簽名對象Signature signature = pjp.getSignature();String className = signature.getDeclaringTypeName();String methodName = signature.getName();long start = System.currentTimeMillis();for (int i = 0; i < 10000; i++) {//表示對原始方法的調(diào)用pjp.proceed();}long end = System.currentTimeMillis();System.out.println("萬次執(zhí)行:"+ className+"."+methodName+"---->" +(end-start) + "ms");}}AOP通知獲取參數(shù)數(shù)據(jù)
JoinPoint對象描述了連接點方法的運行狀態(tài),可以獲取調(diào)用參數(shù)
@Before("pt()") public void before(JoinPoint jp) {Object[] args = jp.getArgs();//獲取參數(shù)的數(shù)組System.out.println(Arrays.toString(args));System.out.println("before advice ..." ); }其他方法也一樣可以通過JoinPoint調(diào)用getArgs獲取參數(shù)數(shù)組
AOP通知獲取返回值數(shù)據(jù)
//設(shè)置返回后通知獲取原始方法的返回值,要求returning屬性值必須與方法形參名相同 @AfterReturning(value = "pt()",returning = "ret") public void afterReturning(JoinPoint jp,String ret) {System.out.println("afterReturning advice ..."+ret); }環(huán)繞通知中可以手工書寫對原始方法的調(diào)用,得到的結(jié)果即為原始方法的返回值
AOP通知獲取異常數(shù)據(jù)(了解 )
//設(shè)置拋出異常后通知獲取原始方法運行時拋出的異常對象,要求throwing屬性值必須與方法形參名相同@AfterThrowing(value = "pt()",throwing = "t")public void afterThrowing(Throwable t) {System.out.println("afterThrowing advice ..."+t);} }總結(jié)
- 上一篇: 安卓跨进程通信
- 下一篇: Winform实时显示图像桌面程序