spring aop 面向切面編程
- 什么是aop
aop 是面向切面編程,是一種編程思維肿孵,也是面向?qū)ο缶幊痰囊环N補(bǔ)充唠粥,面向?qū)ο髮⒊绦虺橄蟪筛鱾€層次的對象,而面向切面變成是將程序抽象給個切面 - 為什么需要aop
為什么需要 aop了颁井,因為在我們開發(fā)中厅贪,很多時候有些方法里面有很多重復(fù)代碼,我們通常處理的方式是雅宾,粘貼來解決辦法养涮,還有的時候我們想在很多地方插入相同的代碼,比如日志等眉抬,我們可能會把相同代碼抽離處理贯吓,然后在需要的地方,來調(diào)用他蜀变,這樣這段代碼需要修改時悄谐,我們只需要改變這個方法就可以了,然而需求總在在變的库北,有一天爬舰,新增一個需求,需要在多出做修改寒瓦,情屹,我們需要在抽象一個方法,然后在需要的地方分別調(diào)用這個方法杂腰,又或者我們不需要這個方法了垃你,我們還是得刪除掉每一處調(diào)用該方法的地方,實際上涉及到多個地方具有相同的修改的問題我們度可以通過aop 來解決喂很。 - aop 術(shù)語
- 通知(advice):AOP 框架中增強(qiáng)處理惜颇。通知描述了切面何時執(zhí)行預(yù)計如何執(zhí)行增強(qiáng)處理
- 連接點(join point):連接點表示應(yīng)用執(zhí)行過程中能夠插入切面的一個點,這個點可以是方法的調(diào)用少辣,異常的拋出凌摄,spring aop 中,連接點終始方法調(diào)用漓帅。
- 切點 (PointCut) : 可以插入增強(qiáng)處理的連接點
- 切面 (Aspect) :切面是通知和切點的結(jié)合望伦。
- 引入 (introduction):引入允許我們向現(xiàn)有的類添加新的方法或者屬性
- 織入 (weaving) : 將增強(qiáng)處理添加到目標(biāo)對象中林说,并創(chuàng)建一個被增強(qiáng)的對象,這個過程就是織入屯伞。
- 簡單的使用
我們使用springboot 整合aop,先導(dǎo)入aop 包
<!-- 引入aop支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
我們使用 @Aspect 把一個類變成切面腿箩,使用@Component 把一個類交給spring 管理,使用@pointcut 注解把一個方法變成切點劣摇,通知
@Component
@Aspect
public class WebLogAop1 {
//ThreadLocal保證不受其他線程影響珠移,用于記錄接口響應(yīng)時間
private static ThreadLocal<Long> threadLocal = new ThreadLocal<Long>();
//切點
@Pointcut("execution(public * com.ljh.mybatisplus.aop..*.*(..))")
public void pointCut(){
System.out.println("pointcut");
}
//通知
//前置通知
@Before(value = "pointCut()")
public void doBefore(JoinPoint joinPoint){
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//請求的內(nèi)容,記錄url末融、method钧惧、ip
System.out.println("URL==>" + request.getRequestURL().toString() + "," +
"METHOD==>" + request.getMethod() + "," +
"IP==>" + request.getRemoteAddr());
Map<String, String[]> params = request.getParameterMap();
Map<String,String> args = new HashMap<>();
for (Map.Entry<String,String[]> temp : params.entrySet()) {
args.put(temp.getKey(), Arrays.toString(temp.getValue()));
}
//連接點的簽名可以跟蹤到程序具體類、具體方法勾习,記錄一下方法和參數(shù)
System.out.println("Before==>" + joinPoint.getSignature().getDeclaringTypeName() + "." +joinPoint.getSignature().getName() + "," +
"ARGS==>" + args);
//記錄請求接口開始時間
threadLocal.set(System.currentTimeMillis());
/* String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));*/
}
//后置返回通知
@AfterReturning(pointcut = "pointCut()",returning = "returnMsg")
public void doAfterReturn(JoinPoint joinPoint,Object returnMsg) {
System.out.println("CLASS_METHOD==>" + joinPoint.getSignature().getDeclaringTypeName() + "." +
joinPoint.getSignature().getName());
//記錄一下接口響應(yīng)時間
Long reponseTime = System.currentTimeMillis() - threadLocal.get();
System.out.println("接口響應(yīng)時間(毫秒)==>" + reponseTime);
//刪除threadLocal變量副本
threadLocal.remove();
Object[] args = joinPoint.getArgs();
for (Object arg : args) {
System.out.println(arg);
}
}
//環(huán)繞通知
@Around("pointCut()")
public Object arround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object object = null;
System.out.println("環(huán)繞通知開始");
object = proceedingJoinPoint.proceed();
System.out.println("環(huán)繞通知結(jié)束");
return object;
}
//異常通知
@AfterThrowing(pointcut = "pointCut()",throwing = "exception")
public void afterThrowing(JoinPoint joinPoint,Exception exception){
String methodName = joinPoint.getSignature().getName();
System.out.println("AfterThrowing The method " + methodName + " occurs exception: " + exception);
}
@After("pointCut()")
public void after(JoinPoint joinPoint){
System.out.println("最終通知");
}
}
被增強(qiáng)的對象屬性和方法
@Component
public class Pointcut {
public String showIndex(String a,String s){
try {
int i = 0;
i = i/0;
}catch (Exception e){
System.out.println(e.getMessage());
}
System.out.println("1");
return a+"----"+s;
}
public String showIndex(int a,String b){
return "";
}
}
測試
@SpringBootTest
@RunWith(SpringRunner.class)
class MybatisplusApplicationTests {
@Autowired
public Pointcut pointcut;
@Test
public void test() {
pointcut.showIndex("ljh","sdfs");
}
@Test
public void test1() {
pointcut.showIndex(15,"ljh");
}
}
image.png