java AOP(面向切面)
一:反射
public class Reflect{
public static void main(String [] args){
Class c = Class.forname("包名+类名"); //forname(包的完整路径)
Object o = c.newInstance(); //这个方法会调用类的无参构造方法,完成对象创建,不过需要保证类中无参构造存在,如果只有有参构造,没有无参构造会报错
}
}
二:AOP(面向切面)
(1)表达式
execuption(访问权限 方法返回值 方法声明(方法参数) 异常类型) //表达式共四个部分,其中访问权限和异常类型可以省略,各部分中间用空格分开
例子1:execuption(public * *(..)) //指定切入点为公共方法
例子2:execuption(* set*(..)) //因为方法返回值和方法声明(方法参数)这两部分是不能省略,所以表达式表示的是任意返回值,以set开头的方法,任意参数
例子3:execuption(* com.baidu.service.*.*(..)) //这个表达式为:任意返回值,com.baidu.service包下的任意类,任意类下的任意方法
例子4:表示多级包一起用
例如 :com.util.service.impl
com.baidu.service.impl
com.tengxun.service.impl
execuption(* *..service.*.*(..)) //这样就可以不同的包共用一个表达式了
解析:第一个*表示方法返回值,第二个*表示任意字符, ..表示当前包和子包,service作为基类,service后面的第一个*表示任意包,第二个*表示包中的任意方法
(2)如何在项目中使用
五种通知注解:@Before //前置通知,在目标方法之前执行
@AfterReturning //后置通知 在目标方法之后执行
@Around //环绕通知(常用)目标方法前后都可以执行
@AfterThrowing //异常通知(了解)
@After //最终通知(了解)
第一步:需要在项目中添加aspectj依赖
第二步:新建一个普通类,在类上加上@Aspectj 注解,用来生命这个类是切面类
第三步:写表达式(前置通知例子)
@Aspectj
public class AspectjTest{
//定义切面执行方法,要求:方法无参数,无返回值
@Before(value = "execuption(public * *.*(..))") //在定义的方法上添加@Before注解,value = 中写需要表达式,如果方法带参数,只需要写参数的类型,不需要带形参名
public void myBefore(){
//里面写需要执行的逻辑代码,比如权限验证,日志记录
System.out.println("前置通知中的方法执行了");
}
}
扩展:
后置通知(在目标方法执行之后执行) 使用注解 @AfterReturning
//方法实例
@AfterReturning(valur="execuption(public * *.*(..))" returning="res")
public void myAfterReturning(Object res){ //需要注意的是:方法中Object 后的形参明可以随便定义,但是必须要和returning中的res值保持一致
System.out.println("后置通知要执行的代码");
}
JoinPoint参数,可以获取切入点接口信息,可用在后置通知,环绕通知,异常通知,最终通知等,要求必须唯一参数的第一位,否则会报错,切入点找不到错误
使用实例:
@AfterReturning(valur="execuption(public * *.*(..))" returning="res")
public void myAfterReturning(JoinPoint jp ,Object res){ //需要注意的是:方法中Object 后的形参明可以随便定义,但是必须要和returning中的res值保持一致
System.out.println("后置通知,方法定义:"+jp.getSignature) //获取接口信息
System.out.println("后置通知要执行的代码");
}
@Around 环绕通知,功能最强的,可在方法执行前,也可在方法执行后执行,必须有一个返回值,方法有参数,是固定的:proceedingJoinPoint
使用实例:
@Around(value = "execucpion(* *.*(..)))
public Object myAround(proceedingJoinPoint pjp){
//获取目标方法中的参数信息
Object args[] = pjp.getArgs(); //因为proceedingJoinPoint 继承自 JoinPoint,所以可以直接调用getArgs()方法获取目标方法的参数数组
//定义一个返回值
Object obj = null;
System.out.println("在执行目标方法之前执行,相当于前置通知"); //
obj = pjp.proceed(); //这句就是执行目标类的方法
System.out.println("这里在目标方法之后执行,相当于后置通知");
return obj; //返回目标方法执行结果
}
@After最终通知,作用:无论接口方法是否报错都会执行,一般是做资源清理工作
@AfterThrowing 异常通知,作用:一般是做程序监控,出现异常会通知
Pointcut:注解,不执行代码,只是做切入点表达式,之后就可以引用这个切入点
使用实例:
第一步:定义Pointcut切入点
@Pointcut(value = "execuption(* *.*(..))")
private void mypt(){
//无需代码,就是一个辅助作用
}
第二步:引用
@Around(value = "mypt()") //这里就可以直接引用定义的那个切面表达式方法
public Object myAround(proceedingJoinPoint){
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏