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