-
介紹
- AspectJ是一個基于Java語言的AOP框架
- Spring2.0以后新增了對AspectJ切點表達支持
- @AspectJ是AspectJ1.5新增功能,通過JDK5注解技術,允許Bean類中定義切面,新版本Spring框架,建議使用AspectJ方式來開發AOP
- 主要用途:自定義開發
-
切入點表達式
-
execution() 用于描述方法
<!--創建目標類--> <bean id="userService" class="com.adolph.AOP.jdk.UserServiceImpl"></bean><!--創建切面類--> <bean id="myAspect" class="com.adolph.AOP.jdk.MyAspect"></bean><!--aop編程使用<aop:config>進行配置proxy-target-class="true":使用cglib代理<aop:pointcut>切入點,從目標對象獲得具體方法<aop:advisor> 特殊的切面,只有一個通知和一個切入點advice-ref:通知引用pointcut-ref:切入點引用切入點表達式:execution(* com.adolph.AOP.jdk.*.*(..))選擇方法 返回值任意 包 類名任意 方法名任意 參數任意 --> <aop:config proxy-target-class="true"><aop:pointcut id="myPointCut" expression="execution(* com.adolph.AOP.jdk.*.*(..))"/><aop:advisor advice-ref="myAspect" pointcut-ref="myPointCut"/> </aop:config> 復制代碼
-
語法:execution(修飾符 返回值 包.類.方法(參數) throws 異常)
- 修飾符:一般省略
- 返回值:*(任意)
- 包
- 省略
- con.adolph.cn 固定包
- com.adolph. adolph包下面子包任意*
- com.adolph.. adolph包下面的所有子包(含自己)
- 省略
- 類
- 省略
- UserServiceImpl 指定類
- *Impl 以Impl結尾
- User 以User開頭*
- *. 任意
- 方法名
- 不能省略
- addUser 固定方法
- add 以add開頭*
- *Do 以Do結尾
- *. 任意
- 參數
- () 無參
- (int) 一個整型
- (int,int) 兩個
- (..) 參數任意
- throws
- 可省略,一般不寫
-
綜合
`execution(* com.adolph.AOP.jdk.*.*(..))` 復制代碼
-
-
-
AspectJ通知類型
- aop聯盟定義通知類型,具有特性接口,必須實現,從而確定方法名稱
- aspectj 通知類型,只定義類型名稱。以及方法格式
- 個數:6種,知道5種,掌握一種
- before:前置通知
- afterReturning:后置通知(應用:常規數據處理)
- around:環繞通知(應用:十分強大,可以做任何事情)
- 方法執行前后分別執行、可以阻止方法的執行
- 必須手動執行目標方法
- afterThrowing:拋出異常通知(應用:包裝異常信息)
- after:最終通知(應用:清理現場)
-
基于XML
-
目標類:接口+實現
-
切面類:編寫多個通知,采用aspectJ通知名稱任意(方法名任意)
-
aop編程:將通知應用到目標類
-
測試
-
目標類
public class UserServiceImpl {public void addUser() {System.out.println("addUser");}public void updateUser() {System.out.println("updateUser");}public void deleteUser() {System.out.println("deleteUser");} } 復制代碼
-
切面類
/*** 切面類,含有多個通知*/ public class MyAspect {public void myBefore(JoinPoint joinPoint) {System.out.println("前置通知" + joinPoint.getSignature().getName()); //獲得目標方法名}public void myAfterReturning(JoinPoint joinPoint, Object ret) {System.out.println("后置通知" + joinPoint.getSignature().getName() + "____" + ret); //獲得目標方法名}public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("前");//手動執行目標方法Object proceed = joinPoint.proceed();System.out.println("后");return proceed;}public void MyAfterThrowing(JoinPoint joinPoint,Throwable e){System.out.println("拋出異常通知:");}public void after(JoinPoint joinPoint){System.out.println("最終");} } 復制代碼
-
xml
<!--創建目標類--> <bean id="userService" class="com.adolph.AOP.jdk.UserServiceImpl"></bean><!--創建切面類--> <bean id="myAspect" class="com.adolph.AOP.jdk.MyAspect"></bean> <!--aop編程 --> <aop:config><!--將切面類 聲明成切面,從而獲得通知(方法),ref:切面類引用--><aop:aspect ref="myAspect"><!--聲明一個切入點,所有的通知都可以使用expression:切入點表達式id:名稱用于其他通知引用--><aop:pointcut id="myPointcut" expression="execution(* com.adolph.AOP.jdk.UserServiceImpl.*(..))"></aop:pointcut><!--前置通知method:通知,及方法名pointcut:切入點表達式,此表達式只能當前通知使用pointcut-ref:切入點引用,可以與其他通知點共享切入點通知方法格式:public void myBefore(JoinPoint joinPoint)參數JoinPoint 用于描述連接點(目標方法),獲得目標方法名稱等--><aop:before method="myBefore" pointcut-ref="myPointcut"></aop:before><!--后置通知,目標方法執行,獲得返回值public void myAfterReturning(JoinPoint joinPoint,Object ret)參數1:連接點描述參數2:類型Object,參數名returning配置的--><aop:after-returning method="myAfterReturning" pointcut-ref="myPointcut" returning="ret"></aop:after-returning><!--環繞通知public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable返回值:Object方法名:任意參數:Proceeding JoinPoint拋出異常--><aop:around method="myAround" pointcut-ref="myPointcut"></aop:around><!--異常通知throwing:通知方法的第二個參數名稱--><aop:after-throwing method="MyAfterThrowing" pointcut-ref="myPointcut" throwing="e"></aop:after-throwing><!--最終通知--><aop:after method="after" pointcut-ref="myPointcut"></aop:after></aop:aspect> </aop:config> 復制代碼
-
-
基于注解
-
替換bean
<!--掃描--> <context:component-scan base-package="com.adolph.AOP"></context:component-scan> 復制代碼
@Component public class MyAspect 復制代碼
-
必須進行aspectj自動代理
<!--確定aop注解生效--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 復制代碼
-
聲明切面
@Component @Aspect public class MyAspect 復制代碼
-
設置前置通知
@Before("execution(* com.adolph.AOP.jdk.UserServiceImpl.*(..))")public void myBefore(JoinPoint joinPoint) {System.out.println("前置通知" + joinPoint.getSignature().getName()); //獲得目標方法名} 復制代碼
-
替換公共切入點
@Pointcut("execution(* com.adolph.AOP.jdk.UserServiceImpl.*(..))") private void myPointCut(){} 復制代碼
-
設置后置通知
@AfterReturning(value = "myPointCut()",returning = "ret") public void myAfterReturning(JoinPoint joinPoint, Object ret) {System.out.println("后置通知" + joinPoint.getSignature().getName() + "____" + ret); //獲得目標方法名 } 復制代碼
-
設置環繞通知
@Around(value = "myPointCut()") public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("前");//手動執行目標方法Object proceed = joinPoint.proceed();System.out.println("后");return proceed; } 復制代碼
-
設置拋出異常
@AfterThrowing(value = "myPointCut()",throwing = "e") public void MyAfterThrowing(JoinPoint joinPoint,Throwable e){System.out.println("拋出異常通知:"); } 復制代碼
-
最終通知
@AfterThrowing(value = "myPointCut()",throwing = "e") public void MyAfterThrowing(JoinPoint joinPoint,Throwable e){System.out.println("拋出異常通知:"); } 復制代碼
-
轉載于:https://juejin.im/post/5ca23972e51d453c0f7d8e93