spectJ是Java的一個AOP框架,可以單獨使用,也可以整合到其它框架中。
單獨使用AspectJ時需要使用專門的編譯器ajc。
java的編譯器是javac,AspectJ的編譯器是ajc,aj是首字母縮寫,c即compiler。
此處介紹如何單獨使用AspectJ。
下載AspectJ所需的jar包
https://www.eclipse.org/aspectj/downloads.php
下載得到的是一個jar包,不能直接使用,解壓,得到3個jar包:
單獨使用AspectJ時,只需添加aspectjrt.jar。
IDEA環境配置
1、安裝插件
2、使用專門的編譯器
Demo
(1)新建Java項目,添加aspectjrt.jar。只添加這一個jar包就ok。
(2)新建包com.chy.dao,包下新建接口UserDao、實現類UserDaoImpl:
public interface UserDao { public void addUser(int i,String str); public void deleteUser(); }
public class UserDaoImpl implements UserDao { @Override public void addUser(int i,String str) { System.out.println("正在添加用戶..."); } @Override public void deleteUser() { System.out.println("正在刪除用戶..."); } }
(3)新建包com.chy.aspect,包下新建類UserDaoAspect:
//需要用@Aspect標注 @org.aspectj.lang.annotation.Aspect public class UserDaoAspect { /* 配置全局切入點 返回值類型 類|接口名.方法名(參數表) 參數表可使用具體類型,比如(int,String),也可用(..)表示任意類型、個數的參數 */ @Pointcut("execution(* com.chy.dao.UserDao.*(..))") private void pointCut(){} /* 前置通知 可以引用全局切入點,也可以現配: @Before("execution(void com.chy.dao.UserDao.*(..))") */ @Before("pointCut()") public void before(){ System.out.println("正在執行前置通知..."); } //后置通知 @After("pointCut()") public void after(){ System.out.println("正在執行后置通知..."); } //返回通知 @AfterReturning("pointCut()") public void afterReturning(){ System.out.println("正在執行返回通知..."); } //異常通知 @AfterThrowing("pointCut()") public void afterThrowing(JoinPoint point){ System.out.println("正在執行異常通知..."); //獲取目標對象,返回值是Object類型 Object target = point.getTarget(); //目標方法名,String System.out.println("目標方法:"+point.getSignature()); //需要轉換一下才能得到具體的實參 List<Object> args = Arrays.asList(point.getArgs()); System.out.println("實參表:"+args); } }
方法名任意,因為要用注解標注此方法是用來實現哪種通知的。
可傳入一個JointPoint類型的參數,表示連接點。
環繞通知:
/* 環繞通知 需要傳入一個ProceedingJoinPoint類型的參數,用於調用目標方法。 如果要代理多個方法,返回值最好聲明為Object,因為多個方法的返回值類型可能不相同 */ @Around("pointCut()") public Object around(ProceedingJoinPoint point) throws Throwable { //前增強 System.out.println("正在執行前增強..."); //調用目標方法 Object obj = point.proceed(); //后增強 System.out.println("正在執行后增強..."); //返回目標方法的返回值 return obj; }
環繞通知與其它通知有重疊,不能一起使用。
(4)使用
UserDao user=new UserDaoImpl(); user.addUser();
AspectJ增強的是方法,調用方法時,會自動調用對應的通知來增強。
切面的另一種寫法(了解)
包下新建Aspect:
//注意是aspect,不是class public aspect UserDaoAspect { //配置全局切入點 @Pointcut("execution(* com.chy.dao.UserDao.*(..))") private void pointCut(){} /* 前置通知 可以使用引用切入點,也可以現配: before():execution(void com.chy.dao.UserDao.*(..)){ } */ before():pointCut(){ System.out.println("正在執行前置通知..."); } //后置通知 after():pointCut(){ System.out.println("正在執行后置通知..."); } }
方法名是固定的:before、after,都是關鍵字,before表示前置通知,after表示后置通知。
此種方式很不好用,不推薦。