一.AOP是什麼?
面向切面編程,就是將交叉業務邏輯封裝成切面,利用AOP功能將切面織入到主業務邏輯中。交叉業務邏輯就是通用的,與主業務邏輯無關的代碼。比如日誌記錄,事務管理,異常處理,安全控制。
二.AOP優點
1.降低了代碼的耦合度
2.提高了代碼的重用性,減輕了程序員的工作量
3.系統更加容易擴展
三.AOP關鍵字
1.切面:泛指交叉的業務邏輯。比如日誌記錄,事務管理就是一個切面。
2.切點:符合切點表達式的連接點,也就是被切入的位置
3.通知:切面類要完成工作,切面類的工作就是通知,通知定義了切面做什麼以及何時使用。
四.AOP的實現
AOP的底層實現就是反射加上代理模式。
反射和代理模式可以參考我之前的博客。
反射:https://blog.csdn.net/x_christ1/article/details/104591277
代理模式:https://blog.csdn.net/x_christ1/article/details/104594560
五.AOP的使用方式
1.註解使用
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> 開啓事物註解權限
@Aspect 指定一個類爲切面類
@Pointcut("execution(* com.xhz.service.UserService.add(..))") 指定切入點表達式
@Before("pointCut_()") 前置通知: 目標方法之前執行
@After("pointCut_()") 後置通知:目標方法之後執行(始終執行)
@AfterReturning("pointCut_()") 返回後通知: 執行方法結束前執行(異常不執行)
@AfterThrowing("pointCut_()") 異常通知: 出現異常時候執行
@Around("pointCut_()") 環繞通知: 環繞目標方法執行
@Component
@Aspect
public class AopLog {
// 前置通知
@Before("execution(* com.cxy.service.UserService.add(..))")
public void begin() {
System.out.println("前置通知");
}
//
// 後置通知
@After("execution(* com.cxy.service.UserService.add(..))")
public void commit() {
System.out.println("後置通知");
}
// 運行通知
@AfterReturning("execution(* com.cxy.service.UserService.add(..))")
public void returning() {
System.out.println("運行通知");
}
// 異常通知
@AfterThrowing("execution(* com.cxy.service.UserService.add(..))")
public void afterThrowing() {
System.out.println("異常通知");
}
// 環繞通知
@Around("execution(* com.cxy.service.UserService.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("環繞通知開始");
proceedingJoinPoint.proceed();
System.out.println("環繞通知結束");
}
}
2.通過xml方式
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- dao 實例 -->
<bean id="userService" class="com.cxy.service.UserService"></bean>
<!-- 切面類 -->
<bean id="aop" class="com.cxy.aop2.AopLog2"></bean>
<!-- Aop配置 -->
<aop:config>
<!-- 定義一個切入點表達式: 攔截哪些方法 -->
<aop:pointcut expression="execution(* com.cxy.service.UserService.*(..))"
id="pt" />
<!-- 切面 -->
<aop:aspect ref="aop">
<!-- 環繞通知 -->
<aop:around method="around" pointcut-ref="pt" />
<!-- 前置通知: 在目標方法調用前執行 -->
<aop:before method="begin" pointcut-ref="pt" />
<!-- 後置通知: -->
<aop:after method="after" pointcut-ref="pt" />
<!-- 返回後通知 -->
<aop:after-returning method="afterReturning"
pointcut-ref="pt" />
<!-- 異常通知 -->
<aop:after-throwing method="afterThrowing"
pointcut-ref="pt" />
</aop:aspect>
</aop:config>
</beans>
public class AopLog2 {
// 前置通知
public void begin() {
System.out.println("前置通知");
}
//
// 後置通知
public void commit() {
System.out.println("後置通知");
}
// 運行通知
public void returning() {
System.out.println("運行通知");
}
// 異常通知
public void afterThrowing() {
System.out.println("異常通知");
}
// 環繞通知
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("環繞通知開始");
proceedingJoinPoint.proceed();
System.out.println("環繞通知結束");
}
}