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表示后置通知。
此种方式很不好用,不推荐。