Aop:面向切面編程,即是橫向重複、縱向抽取思想。
springAop:底層封裝了動態代理和cglib代理的代碼,我們不需要手寫動態代理的代碼,封裝的兩個代理可以對任何類進行增強。
使用Aop的注意事項/坑:
1)、不宜把重要業務放在Aop中處理。
2)、Aop不處理Static、final、private方法
3)、無法攔截內部方法調用
spring名詞:
1)連接點(JoinCut):目標對象中所有可以增強的方法,可以認爲是類中的所欲方法
2)切入點(PointCut):目標對象中需要對它進行增強的方法
3)切面(Aspect):切入點+通知
4)織入(Weaving):將通知織入到切入點的過程叫做織入
5)目標對象(Target):即是需要增強的類
6)代理(Proxy):將通知織入到目標對象之後生成代理對象
7)通知/增強(Advice):對切入點所增強的代碼
通知類型:
前置通知:(在調用目標對象之前執行)
環繞通知:(在目標對象調用之前和調用之後都會執行)
異常通知:(在調用目標對象之後執行)
後置通知(出現異常也會執行):(在調用目標對象之後異常情況下也會執行)
後置通知(出現異常不會執行):(在調用目標對象之後異常情況下不會執行)
springBoot整合Aop實例介紹
1、導入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2、設置方法接口
package com.ltj.demo.Service.Interface;
/**
* 接口測試類
*/
public interface interfaceA {
//增加
public String save(int args1,int args2);
}
3、實現接口
package com.ltj.demo.Service;
import com.ltj.demo.Service.Interface.interfaceA;
import org.springframework.stereotype.Service;
/**
* 設置通知
*/
@Service
public class interfaceAImpl implements interfaceA {
@Override
public String save(int mathScore,int engScore) {
System.out.println("保存成功");
System.out.println("the total score is : " + mathScore+engScore);
return "保存成功22";
}
}
4、設置通知類
package com.ltj.demo.Service;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* 通知/增強名詞
* 前置通知(在調用目標對象之前執行)
* 後置通知(異常情況下不會執行)
* 環繞通知(在目標對象調用之前和調用之後都會執行)
* 異常通知(在調用目標對象之後執行)
* 後置通知(異常情況下也會執行)
*/
/**
* @Aspect:該註解設置該類爲切面
* @Component
*/
@Aspect
@Component
public class MyAdvice {
//設置方法作爲切入點
@Pointcut(value = "execution(* com.ltj.demo.Service.interfaceAImpl.*(..))")
public void pointCut(){}
//設置前置通知
@Before("MyAdvice.pointCut()")
public void before(JoinPoint joinPoint){
Object[] obj = joinPoint.getArgs(); //獲取連接點方法運行時的入參列表
String methodName = joinPoint.getSignature().getName();
Object paramter1 = joinPoint.getSignature().getDeclaringType();
Object paramter2 = joinPoint.getSignature().getDeclaringTypeName();
Object paramter3 = joinPoint.getSignature().getModifiers();
System.out.println(methodName); //獲取目標對象的方法名
System.out.println(paramter1);
System.out.println(paramter2);
System.out.println(paramter3);
System.out.println(joinPoint.getThis()); //獲取代理對象本身
System.out.println(joinPoint.getTarget()); //獲取連接點所在的目標對象
for (Object objs: obj) { //循環獲取入參值
System.out.println("入參:" + objs);
}
System.out.println("我是前置通知");
}
/**
* 設置後置通知(異常情況下也會執行)
* @param joinPoint 目標類連接點對象
*/
@After("MyAdvice.pointCut()")
public void after(JoinPoint joinPoint){
System.out.println("設置後置通知(異常情況下也會執行)");
}
//設置後置通知(異常情況下不會執行)
@AfterReturning(value="MyAdvice.pointCut()", returning ="results") //value設置切入點,results爲返回值
public void afterReturn(JoinPoint joinPoint,Object results){ //results設置參數接收返回值
System.out.println("設置後置通知(異常情況下不會執行)");
System.out.println("返回值爲:" + results); //輸出results返回值,即是目標對象的返回值
}
/**
* 設置異常通知
* @param proceedingJoinPoint JoinPoint的子接口
*/
@AfterThrowing("MyAdvice.pointCut()")
public void afterThrow(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("我是異常通知");
}
/**
* 設置環繞通知
* @param proceedingJoinPoint JoinPoint的子接口
*/
@Around("MyAdvice.pointCut()")
public void around(ProceedingJoinPoint proceedingJoinPoint){
String methodName = proceedingJoinPoint.getSignature().getName();
Object result = null;
try {
System.out.println("我是環繞通知");
result = proceedingJoinPoint.proceed(); //通過反射執行目標對象的連接點處的方法
System.out.println("環繞通知的名稱爲:" + methodName +
",返回的執行結果是:" + result);
}catch (Throwable throwable){
throwable.printStackTrace();
System.out.println("異常返回");
}
}
}
5、使用測試類進行測試
package com.ltj.demo.Service;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.*;
@SpringBootTest
@RunWith(SpringRunner.class)
public class interfaceAImplTest {
//自動注入
@Autowired
interfaceAImpl interfaceAImp;
@Test
public void example() {
//調用保存方法
interfaceAImp.save(1,2);
}
}
友情鏈接:
AspectJ JoinPoint及ProceedingJoinPoint 簡要api文檔:https://blog.csdn.net/airjordon/article/details/83623830
SpringBoot集成ApringAOP:https://www.cnblogs.com/zdj-/p/8665454.html
springAop視同註解實現5種通知類型:https://www.cnblogs.com/fengxiangyu/p/10896547.html