1.AOP介紹
AOP(Aspect Oriented Programming)面向切面編程,一種編程范式,指導開發者如何組織程序結構,作用是在不改動原始設計的基礎上為其進行功能增強
2.AOP的核心概念
概念 | 定義 | SpringAOP(注解開發)中的具體形式 |
---|---|---|
連接點(JoinPoint) | 程序執行過程中的任意位置,粒度為執行方法、拋出異常、設置變量等 | 執行方法 |
切入點(PointCut) | 匹配連接點的式子 | 一個切入點可以只描述一個方法,也可以匹配多個方法 |
通知(Advice) | 在切入點處執行的操作,也就是共性功能 | 以方法的形式呈現 |
切面(Aspect) | 描述通知與切入點的對應關系 | @Aspect 、@Before、@After、@Around、@AfterReturning、@AfterThrowing等注解 |
3.SpringAOP的使用步驟
(1)導入SpringAOP依賴坐標
注:spring-context中包含AOP相關依賴
<!--spring-context--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.0.RELEASE</version></dependency><!--aspect--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency>
(2)定義連接點
package com.example.service;public interface IUser {void eat();void sleep();
}
package com.example.service.impl;import com.example.service.IUser;
import org.springframework.stereotype.Service;@Service
public class UserImpl implements IUser {@Overridepublic void eat() {System.out.println("炫飯中... ...");}@Overridepublic void sleep() {System.out.println("深度睡眠中... ...");}
}
(3)定義通知類,制作通知
package com.example.aop;public class MyAdvice {public void advice(){System.out.println("在連接點之前執行的共性功能");}
}
(4)定義切入點
注:切入點定義依托一個不具有實際意義的方法進行,即無參數,無返回值,方法體無實際邏輯
package com.example.aop;import org.aspectj.lang.annotation.Pointcut;public class MyAdvice {@Pointcut("execution(void com.example.service.IUser.eat())")private void pt(){}public void advice(){System.out.println("在連接點之前執行的共性功能");}
}
(5)綁定切入點和通知關系,并指定通知添加到原始連接點的具體執行位置
package com.example.aop;import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;public class MyAdvice {@Pointcut("execution(void com.example.service.IUser.eat())")private void pt(){}@Before("pt()")public void advice(){System.out.println("在連接點之前執行的共性功能");}}
(6)定義通知類受Spring容器管理,并定義當前類為切面類
package com.example.aop;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Component
@Aspect// 代表這個類是一個切面
public class MyAdvice {@Pointcut("execution(void com.example.service.IUser.eat())")private void pt(){}@Before("pt()")public void advice(){System.out.println("在連接點之前執行的共性功能");}
}
(7)開啟Spring對AOP注解驅動支持
package com.example.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@ComponentScan("com.example")
@EnableAspectJAutoProxy// 開啟Spring對AOP注解驅動支持
public class SpringConfig {
}
4.SpringAOP的工作流程
(1)Spring容器啟動
(2)讀取所有切面配置中的切入點
(3)初始化Bean,判定Bean對應的類中的方法是否匹配到任意切入點
- 匹配失敗,創建對象
- 匹配成功,創建原始對象(目標對象)的代理對象
(4)獲取Bean執行方法
- 獲取Bean,調用方法并執行,完成操作(對應步驟(3)匹配失敗的情況)
- 獲取的Bean是代理對象時,根據代理對象的運行模式運行原始方法與增強的內容,完成操作(對應步驟(3)匹配成功的情況)