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){

 

}

 

posted @   每天坚持亿点点  阅读(572)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
点击右上角即可分享
微信分享提示